diff options
Diffstat (limited to 'vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go')
-rw-r--r-- | vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go new file mode 100644 index 0000000..5daf7b6 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go | |||
@@ -0,0 +1,279 @@ | |||
1 | // Copyright 2013 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" | ||
9 | "crypto/md5" | ||
10 | "crypto/rsa" | ||
11 | "encoding/binary" | ||
12 | "fmt" | ||
13 | "hash" | ||
14 | "io" | ||
15 | "math/big" | ||
16 | "strconv" | ||
17 | "time" | ||
18 | |||
19 | "golang.org/x/crypto/openpgp/errors" | ||
20 | ) | ||
21 | |||
22 | // PublicKeyV3 represents older, version 3 public keys. These keys are less secure and | ||
23 | // should not be used for signing or encrypting. They are supported here only for | ||
24 | // parsing version 3 key material and validating signatures. | ||
25 | // See RFC 4880, section 5.5.2. | ||
26 | type PublicKeyV3 struct { | ||
27 | CreationTime time.Time | ||
28 | DaysToExpire uint16 | ||
29 | PubKeyAlgo PublicKeyAlgorithm | ||
30 | PublicKey *rsa.PublicKey | ||
31 | Fingerprint [16]byte | ||
32 | KeyId uint64 | ||
33 | IsSubkey bool | ||
34 | |||
35 | n, e parsedMPI | ||
36 | } | ||
37 | |||
38 | // newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. | ||
39 | // Included here for testing purposes only. RFC 4880, section 5.5.2: | ||
40 | // "an implementation MUST NOT generate a V3 key, but MAY accept it." | ||
41 | func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { | ||
42 | pk := &PublicKeyV3{ | ||
43 | CreationTime: creationTime, | ||
44 | PublicKey: pub, | ||
45 | n: fromBig(pub.N), | ||
46 | e: fromBig(big.NewInt(int64(pub.E))), | ||
47 | } | ||
48 | |||
49 | pk.setFingerPrintAndKeyId() | ||
50 | return pk | ||
51 | } | ||
52 | |||
53 | func (pk *PublicKeyV3) parse(r io.Reader) (err error) { | ||
54 | // RFC 4880, section 5.5.2 | ||
55 | var buf [8]byte | ||
56 | if _, err = readFull(r, buf[:]); err != nil { | ||
57 | return | ||
58 | } | ||
59 | if buf[0] < 2 || buf[0] > 3 { | ||
60 | return errors.UnsupportedError("public key version") | ||
61 | } | ||
62 | pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) | ||
63 | pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) | ||
64 | pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) | ||
65 | switch pk.PubKeyAlgo { | ||
66 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
67 | err = pk.parseRSA(r) | ||
68 | default: | ||
69 | err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) | ||
70 | } | ||
71 | if err != nil { | ||
72 | return | ||
73 | } | ||
74 | |||
75 | pk.setFingerPrintAndKeyId() | ||
76 | return | ||
77 | } | ||
78 | |||
79 | func (pk *PublicKeyV3) setFingerPrintAndKeyId() { | ||
80 | // RFC 4880, section 12.2 | ||
81 | fingerPrint := md5.New() | ||
82 | fingerPrint.Write(pk.n.bytes) | ||
83 | fingerPrint.Write(pk.e.bytes) | ||
84 | fingerPrint.Sum(pk.Fingerprint[:0]) | ||
85 | pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) | ||
86 | } | ||
87 | |||
88 | // parseRSA parses RSA public key material from the given Reader. See RFC 4880, | ||
89 | // section 5.5.2. | ||
90 | func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { | ||
91 | if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { | ||
92 | return | ||
93 | } | ||
94 | if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { | ||
95 | return | ||
96 | } | ||
97 | |||
98 | // RFC 4880 Section 12.2 requires the low 8 bytes of the | ||
99 | // modulus to form the key id. | ||
100 | if len(pk.n.bytes) < 8 { | ||
101 | return errors.StructuralError("v3 public key modulus is too short") | ||
102 | } | ||
103 | if len(pk.e.bytes) > 3 { | ||
104 | err = errors.UnsupportedError("large public exponent") | ||
105 | return | ||
106 | } | ||
107 | rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} | ||
108 | for i := 0; i < len(pk.e.bytes); i++ { | ||
109 | rsa.E <<= 8 | ||
110 | rsa.E |= int(pk.e.bytes[i]) | ||
111 | } | ||
112 | pk.PublicKey = rsa | ||
113 | return | ||
114 | } | ||
115 | |||
116 | // SerializeSignaturePrefix writes the prefix for this public key to the given Writer. | ||
117 | // The prefix is used when calculating a signature over this public key. See | ||
118 | // RFC 4880, section 5.2.4. | ||
119 | func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { | ||
120 | var pLength uint16 | ||
121 | switch pk.PubKeyAlgo { | ||
122 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
123 | pLength += 2 + uint16(len(pk.n.bytes)) | ||
124 | pLength += 2 + uint16(len(pk.e.bytes)) | ||
125 | default: | ||
126 | panic("unknown public key algorithm") | ||
127 | } | ||
128 | pLength += 6 | ||
129 | w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) | ||
130 | return | ||
131 | } | ||
132 | |||
133 | func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { | ||
134 | length := 8 // 8 byte header | ||
135 | |||
136 | switch pk.PubKeyAlgo { | ||
137 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
138 | length += 2 + len(pk.n.bytes) | ||
139 | length += 2 + len(pk.e.bytes) | ||
140 | default: | ||
141 | panic("unknown public key algorithm") | ||
142 | } | ||
143 | |||
144 | packetType := packetTypePublicKey | ||
145 | if pk.IsSubkey { | ||
146 | packetType = packetTypePublicSubkey | ||
147 | } | ||
148 | if err = serializeHeader(w, packetType, length); err != nil { | ||
149 | return | ||
150 | } | ||
151 | return pk.serializeWithoutHeaders(w) | ||
152 | } | ||
153 | |||
154 | // serializeWithoutHeaders marshals the PublicKey to w in the form of an | ||
155 | // OpenPGP public key packet, not including the packet header. | ||
156 | func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { | ||
157 | var buf [8]byte | ||
158 | // Version 3 | ||
159 | buf[0] = 3 | ||
160 | // Creation time | ||
161 | t := uint32(pk.CreationTime.Unix()) | ||
162 | buf[1] = byte(t >> 24) | ||
163 | buf[2] = byte(t >> 16) | ||
164 | buf[3] = byte(t >> 8) | ||
165 | buf[4] = byte(t) | ||
166 | // Days to expire | ||
167 | buf[5] = byte(pk.DaysToExpire >> 8) | ||
168 | buf[6] = byte(pk.DaysToExpire) | ||
169 | // Public key algorithm | ||
170 | buf[7] = byte(pk.PubKeyAlgo) | ||
171 | |||
172 | if _, err = w.Write(buf[:]); err != nil { | ||
173 | return | ||
174 | } | ||
175 | |||
176 | switch pk.PubKeyAlgo { | ||
177 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
178 | return writeMPIs(w, pk.n, pk.e) | ||
179 | } | ||
180 | return errors.InvalidArgumentError("bad public-key algorithm") | ||
181 | } | ||
182 | |||
183 | // CanSign returns true iff this public key can generate signatures | ||
184 | func (pk *PublicKeyV3) CanSign() bool { | ||
185 | return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly | ||
186 | } | ||
187 | |||
188 | // VerifySignatureV3 returns nil iff sig is a valid signature, made by this | ||
189 | // public key, of the data hashed into signed. signed is mutated by this call. | ||
190 | func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { | ||
191 | if !pk.CanSign() { | ||
192 | return errors.InvalidArgumentError("public key cannot generate signatures") | ||
193 | } | ||
194 | |||
195 | suffix := make([]byte, 5) | ||
196 | suffix[0] = byte(sig.SigType) | ||
197 | binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) | ||
198 | signed.Write(suffix) | ||
199 | hashBytes := signed.Sum(nil) | ||
200 | |||
201 | if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { | ||
202 | return errors.SignatureError("hash tag doesn't match") | ||
203 | } | ||
204 | |||
205 | if pk.PubKeyAlgo != sig.PubKeyAlgo { | ||
206 | return errors.InvalidArgumentError("public key and signature use different algorithms") | ||
207 | } | ||
208 | |||
209 | switch pk.PubKeyAlgo { | ||
210 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | ||
211 | if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { | ||
212 | return errors.SignatureError("RSA verification failure") | ||
213 | } | ||
214 | return | ||
215 | default: | ||
216 | // V3 public keys only support RSA. | ||
217 | panic("shouldn't happen") | ||
218 | } | ||
219 | } | ||
220 | |||
221 | // VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this | ||
222 | // public key, that id is the identity of pub. | ||
223 | func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { | ||
224 | h, err := userIdSignatureV3Hash(id, pk, sig.Hash) | ||
225 | if err != nil { | ||
226 | return err | ||
227 | } | ||
228 | return pk.VerifySignatureV3(h, sig) | ||
229 | } | ||
230 | |||
231 | // VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this | ||
232 | // public key, of signed. | ||
233 | func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { | ||
234 | h, err := keySignatureHash(pk, signed, sig.Hash) | ||
235 | if err != nil { | ||
236 | return err | ||
237 | } | ||
238 | return pk.VerifySignatureV3(h, sig) | ||
239 | } | ||
240 | |||
241 | // userIdSignatureV3Hash returns a Hash of the message that needs to be signed | ||
242 | // to assert that pk is a valid key for id. | ||
243 | func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { | ||
244 | if !hfn.Available() { | ||
245 | return nil, errors.UnsupportedError("hash function") | ||
246 | } | ||
247 | h = hfn.New() | ||
248 | |||
249 | // RFC 4880, section 5.2.4 | ||
250 | pk.SerializeSignaturePrefix(h) | ||
251 | pk.serializeWithoutHeaders(h) | ||
252 | |||
253 | h.Write([]byte(id)) | ||
254 | |||
255 | return | ||
256 | } | ||
257 | |||
258 | // KeyIdString returns the public key's fingerprint in capital hex | ||
259 | // (e.g. "6C7EE1B8621CC013"). | ||
260 | func (pk *PublicKeyV3) KeyIdString() string { | ||
261 | return fmt.Sprintf("%X", pk.KeyId) | ||
262 | } | ||
263 | |||
264 | // KeyIdShortString returns the short form of public key's fingerprint | ||
265 | // in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). | ||
266 | func (pk *PublicKeyV3) KeyIdShortString() string { | ||
267 | return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) | ||
268 | } | ||
269 | |||
270 | // BitLength returns the bit length for the given public key. | ||
271 | func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { | ||
272 | switch pk.PubKeyAlgo { | ||
273 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
274 | bitLength = pk.n.bitLength | ||
275 | default: | ||
276 | err = errors.InvalidArgumentError("bad public-key algorithm") | ||
277 | } | ||
278 | return | ||
279 | } | ||