diff options
Diffstat (limited to 'vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go')
-rw-r--r-- | vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go new file mode 100644 index 0000000..266840d --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go | |||
@@ -0,0 +1,199 @@ | |||
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. | ||
4 | |||
5 | package packet | ||
6 | |||
7 | import ( | ||
8 | "crypto/rsa" | ||
9 | "encoding/binary" | ||
10 | "io" | ||
11 | "math/big" | ||
12 | "strconv" | ||
13 | |||
14 | "golang.org/x/crypto/openpgp/elgamal" | ||
15 | "golang.org/x/crypto/openpgp/errors" | ||
16 | ) | ||
17 | |||
18 | const encryptedKeyVersion = 3 | ||
19 | |||
20 | // EncryptedKey represents a public-key encrypted session key. See RFC 4880, | ||
21 | // section 5.1. | ||
22 | type EncryptedKey struct { | ||
23 | KeyId uint64 | ||
24 | Algo PublicKeyAlgorithm | ||
25 | CipherFunc CipherFunction // only valid after a successful Decrypt | ||
26 | Key []byte // only valid after a successful Decrypt | ||
27 | |||
28 | encryptedMPI1, encryptedMPI2 parsedMPI | ||
29 | } | ||
30 | |||
31 | func (e *EncryptedKey) parse(r io.Reader) (err error) { | ||
32 | var buf [10]byte | ||
33 | _, err = readFull(r, buf[:]) | ||
34 | if err != nil { | ||
35 | return | ||
36 | } | ||
37 | if buf[0] != encryptedKeyVersion { | ||
38 | return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) | ||
39 | } | ||
40 | e.KeyId = binary.BigEndian.Uint64(buf[1:9]) | ||
41 | e.Algo = PublicKeyAlgorithm(buf[9]) | ||
42 | switch e.Algo { | ||
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) | ||
47 | if err != nil { | ||
48 | return | ||
49 | } | ||
50 | e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) | ||
51 | } | ||
52 | _, err = consumeAll(r) | ||
53 | return | ||
54 | } | ||
55 | |||
56 | func checksumKeyMaterial(key []byte) uint16 { | ||
57 | var checksum uint16 | ||
58 | for _, v := range key { | ||
59 | checksum += uint16(v) | ||
60 | } | ||
61 | return checksum | ||
62 | } | ||
63 | |||
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 { | ||
68 | var err error | ||
69 | var b []byte | ||
70 | |||
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) | ||
80 | default: | ||
81 | err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) | ||
82 | } | ||
83 | |||
84 | if err != nil { | ||
85 | return err | ||
86 | } | ||
87 | |||
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") | ||
94 | } | ||
95 | |||
96 | return nil | ||
97 | } | ||
98 | |||
99 | // Serialize writes the encrypted key packet, e, to w. | ||
100 | func (e *EncryptedKey) Serialize(w io.Writer) error { | ||
101 | var mpiLen int | ||
102 | switch e.Algo { | ||
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) | ||
107 | default: | ||
108 | return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) | ||
109 | } | ||
110 | |||
111 | serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) | ||
112 | |||
113 | w.Write([]byte{encryptedKeyVersion}) | ||
114 | binary.Write(w, binary.BigEndian, e.KeyId) | ||
115 | w.Write([]byte{byte(e.Algo)}) | ||
116 | |||
117 | switch e.Algo { | ||
118 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: | ||
119 | writeMPIs(w, e.encryptedMPI1) | ||
120 | case PubKeyAlgoElGamal: | ||
121 | writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2) | ||
122 | default: | ||
123 | panic("internal error") | ||
124 | } | ||
125 | |||
126 | return nil | ||
127 | } | ||
128 | |||
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 { | ||
133 | var buf [10]byte | ||
134 | buf[0] = encryptedKeyVersion | ||
135 | binary.BigEndian.PutUint64(buf[1:9], pub.KeyId) | ||
136 | buf[9] = byte(pub.PubKeyAlgo) | ||
137 | |||
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) | ||
144 | |||
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))) | ||
152 | } | ||
153 | |||
154 | return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) | ||
155 | } | ||
156 | |||
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) | ||
159 | if err != nil { | ||
160 | return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) | ||
161 | } | ||
162 | |||
163 | packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) | ||
164 | |||
165 | err = serializeHeader(w, packetTypeEncryptedKey, packetLen) | ||
166 | if err != nil { | ||
167 | return err | ||
168 | } | ||
169 | _, err = w.Write(header[:]) | ||
170 | if err != nil { | ||
171 | return err | ||
172 | } | ||
173 | return writeMPI(w, 8*uint16(len(cipherText)), cipherText) | ||
174 | } | ||
175 | |||
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) | ||
178 | if err != nil { | ||
179 | return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) | ||
180 | } | ||
181 | |||
182 | packetLen := 10 /* header length */ | ||
183 | packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 | ||
184 | packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 | ||
185 | |||
186 | err = serializeHeader(w, packetTypeEncryptedKey, packetLen) | ||
187 | if err != nil { | ||
188 | return err | ||
189 | } | ||
190 | _, err = w.Write(header[:]) | ||
191 | if err != nil { | ||
192 | return err | ||
193 | } | ||
194 | err = writeBig(w, c1) | ||
195 | if err != nil { | ||
196 | return err | ||
197 | } | ||
198 | return writeBig(w, c2) | ||
199 | } | ||