1
// Copyright 2011 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
14
"golang.org/x/crypto/openpgp/elgamal"
15
"golang.org/x/crypto/openpgp/errors"
18
const encryptedKeyVersion = 3
20
// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
22
type EncryptedKey struct {
24
Algo PublicKeyAlgorithm
25
CipherFunc CipherFunction // only valid after a successful Decrypt
26
Key []byte // only valid after a successful Decrypt
28
encryptedMPI1, encryptedMPI2 parsedMPI
31
func (e *EncryptedKey) parse(r io.Reader) (err error) {
33
_, err = readFull(r, buf[:])
37
if buf[0] != encryptedKeyVersion {
38
return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
40
e.KeyId = binary.BigEndian.Uint64(buf[1:9])
41
e.Algo = PublicKeyAlgorithm(buf[9])
43
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
44
e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
45
case PubKeyAlgoElGamal:
46
e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
50
e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
52
_, err = consumeAll(r)
56
func checksumKeyMaterial(key []byte) uint16 {
58
for _, v := range key {
64
// Decrypt decrypts an encrypted session key with the given private key. The
65
// private key must have been decrypted first.
66
// If config is nil, sensible defaults will be used.
67
func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
71
// TODO(agl): use session key decryption routines here to avoid
72
// padding oracle attacks.
73
switch priv.PubKeyAlgo {
74
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
75
b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes)
76
case PubKeyAlgoElGamal:
77
c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
78
c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
79
b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
81
err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
88
e.CipherFunc = CipherFunction(b[0])
89
e.Key = b[1 : len(b)-2]
90
expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
91
checksum := checksumKeyMaterial(e.Key)
92
if checksum != expectedChecksum {
93
return errors.StructuralError("EncryptedKey checksum incorrect")
99
// Serialize writes the encrypted key packet, e, to w.
100
func (e *EncryptedKey) Serialize(w io.Writer) error {
103
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
104
mpiLen = 2 + len(e.encryptedMPI1.bytes)
105
case PubKeyAlgoElGamal:
106
mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes)
108
return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
111
serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
113
w.Write([]byte{encryptedKeyVersion})
114
binary.Write(w, binary.BigEndian, e.KeyId)
115
w.Write([]byte{byte(e.Algo)})
118
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
119
writeMPIs(w, e.encryptedMPI1)
120
case PubKeyAlgoElGamal:
121
writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2)
123
panic("internal error")
129
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
130
// key, encrypted to pub.
131
// If config is nil, sensible defaults will be used.
132
func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
134
buf[0] = encryptedKeyVersion
135
binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
136
buf[9] = byte(pub.PubKeyAlgo)
138
keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */)
139
keyBlock[0] = byte(cipherFunc)
140
copy(keyBlock[1:], key)
141
checksum := checksumKeyMaterial(key)
142
keyBlock[1+len(key)] = byte(checksum >> 8)
143
keyBlock[1+len(key)+1] = byte(checksum)
145
switch pub.PubKeyAlgo {
146
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
147
return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
148
case PubKeyAlgoElGamal:
149
return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
150
case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
151
return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
154
return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
157
func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
158
cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
160
return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
163
packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
165
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
169
_, err = w.Write(header[:])
173
return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
176
func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
177
c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
179
return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
182
packetLen := 10 /* header length */
183
packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
184
packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
186
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
190
_, err = w.Write(header[:])
194
err = writeBig(w, c1)
198
return writeBig(w, c2)