diff options
author | Radek Simko <radek.simko@gmail.com> | 2017-08-10 14:38:14 +0200 |
---|---|---|
committer | Radek Simko <radek.simko@gmail.com> | 2017-08-10 14:38:14 +0200 |
commit | c680a8e1622ed0f18751d9d167c836ee24f5e897 (patch) | |
tree | 864f925049d422033dd25a73bafce32b361c8827 /vendor/golang.org/x/crypto/openpgp/packet/public_key.go | |
parent | 38f8880ac81bfabc6d7f82e4dc89661f20fc559e (diff) | |
download | terraform-provider-statuscake-c680a8e1622ed0f18751d9d167c836ee24f5e897.tar.gz terraform-provider-statuscake-c680a8e1622ed0f18751d9d167c836ee24f5e897.tar.zst terraform-provider-statuscake-c680a8e1622ed0f18751d9d167c836ee24f5e897.zip |
vendor: github.com/hashicorp/terraform/...@v0.10.0
Diffstat (limited to 'vendor/golang.org/x/crypto/openpgp/packet/public_key.go')
-rw-r--r-- | vendor/golang.org/x/crypto/openpgp/packet/public_key.go | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go new file mode 100644 index 0000000..ead2623 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go | |||
@@ -0,0 +1,748 @@ | |||
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 | "bytes" | ||
9 | "crypto" | ||
10 | "crypto/dsa" | ||
11 | "crypto/ecdsa" | ||
12 | "crypto/elliptic" | ||
13 | "crypto/rsa" | ||
14 | "crypto/sha1" | ||
15 | _ "crypto/sha256" | ||
16 | _ "crypto/sha512" | ||
17 | "encoding/binary" | ||
18 | "fmt" | ||
19 | "hash" | ||
20 | "io" | ||
21 | "math/big" | ||
22 | "strconv" | ||
23 | "time" | ||
24 | |||
25 | "golang.org/x/crypto/openpgp/elgamal" | ||
26 | "golang.org/x/crypto/openpgp/errors" | ||
27 | ) | ||
28 | |||
29 | var ( | ||
30 | // NIST curve P-256 | ||
31 | oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} | ||
32 | // NIST curve P-384 | ||
33 | oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} | ||
34 | // NIST curve P-521 | ||
35 | oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} | ||
36 | ) | ||
37 | |||
38 | const maxOIDLength = 8 | ||
39 | |||
40 | // ecdsaKey stores the algorithm-specific fields for ECDSA keys. | ||
41 | // as defined in RFC 6637, Section 9. | ||
42 | type ecdsaKey struct { | ||
43 | // oid contains the OID byte sequence identifying the elliptic curve used | ||
44 | oid []byte | ||
45 | // p contains the elliptic curve point that represents the public key | ||
46 | p parsedMPI | ||
47 | } | ||
48 | |||
49 | // parseOID reads the OID for the curve as defined in RFC 6637, Section 9. | ||
50 | func parseOID(r io.Reader) (oid []byte, err error) { | ||
51 | buf := make([]byte, maxOIDLength) | ||
52 | if _, err = readFull(r, buf[:1]); err != nil { | ||
53 | return | ||
54 | } | ||
55 | oidLen := buf[0] | ||
56 | if int(oidLen) > len(buf) { | ||
57 | err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) | ||
58 | return | ||
59 | } | ||
60 | oid = buf[:oidLen] | ||
61 | _, err = readFull(r, oid) | ||
62 | return | ||
63 | } | ||
64 | |||
65 | func (f *ecdsaKey) parse(r io.Reader) (err error) { | ||
66 | if f.oid, err = parseOID(r); err != nil { | ||
67 | return err | ||
68 | } | ||
69 | f.p.bytes, f.p.bitLength, err = readMPI(r) | ||
70 | return | ||
71 | } | ||
72 | |||
73 | func (f *ecdsaKey) serialize(w io.Writer) (err error) { | ||
74 | buf := make([]byte, maxOIDLength+1) | ||
75 | buf[0] = byte(len(f.oid)) | ||
76 | copy(buf[1:], f.oid) | ||
77 | if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { | ||
78 | return | ||
79 | } | ||
80 | return writeMPIs(w, f.p) | ||
81 | } | ||
82 | |||
83 | func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { | ||
84 | var c elliptic.Curve | ||
85 | if bytes.Equal(f.oid, oidCurveP256) { | ||
86 | c = elliptic.P256() | ||
87 | } else if bytes.Equal(f.oid, oidCurveP384) { | ||
88 | c = elliptic.P384() | ||
89 | } else if bytes.Equal(f.oid, oidCurveP521) { | ||
90 | c = elliptic.P521() | ||
91 | } else { | ||
92 | return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) | ||
93 | } | ||
94 | x, y := elliptic.Unmarshal(c, f.p.bytes) | ||
95 | if x == nil { | ||
96 | return nil, errors.UnsupportedError("failed to parse EC point") | ||
97 | } | ||
98 | return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil | ||
99 | } | ||
100 | |||
101 | func (f *ecdsaKey) byteLen() int { | ||
102 | return 1 + len(f.oid) + 2 + len(f.p.bytes) | ||
103 | } | ||
104 | |||
105 | type kdfHashFunction byte | ||
106 | type kdfAlgorithm byte | ||
107 | |||
108 | // ecdhKdf stores key derivation function parameters | ||
109 | // used for ECDH encryption. See RFC 6637, Section 9. | ||
110 | type ecdhKdf struct { | ||
111 | KdfHash kdfHashFunction | ||
112 | KdfAlgo kdfAlgorithm | ||
113 | } | ||
114 | |||
115 | func (f *ecdhKdf) parse(r io.Reader) (err error) { | ||
116 | buf := make([]byte, 1) | ||
117 | if _, err = readFull(r, buf); err != nil { | ||
118 | return | ||
119 | } | ||
120 | kdfLen := int(buf[0]) | ||
121 | if kdfLen < 3 { | ||
122 | return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) | ||
123 | } | ||
124 | buf = make([]byte, kdfLen) | ||
125 | if _, err = readFull(r, buf); err != nil { | ||
126 | return | ||
127 | } | ||
128 | reserved := int(buf[0]) | ||
129 | f.KdfHash = kdfHashFunction(buf[1]) | ||
130 | f.KdfAlgo = kdfAlgorithm(buf[2]) | ||
131 | if reserved != 0x01 { | ||
132 | return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) | ||
133 | } | ||
134 | return | ||
135 | } | ||
136 | |||
137 | func (f *ecdhKdf) serialize(w io.Writer) (err error) { | ||
138 | buf := make([]byte, 4) | ||
139 | // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. | ||
140 | buf[0] = byte(0x03) // Length of the following fields | ||
141 | buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now | ||
142 | buf[2] = byte(f.KdfHash) | ||
143 | buf[3] = byte(f.KdfAlgo) | ||
144 | _, err = w.Write(buf[:]) | ||
145 | return | ||
146 | } | ||
147 | |||
148 | func (f *ecdhKdf) byteLen() int { | ||
149 | return 4 | ||
150 | } | ||
151 | |||
152 | // PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. | ||
153 | type PublicKey struct { | ||
154 | CreationTime time.Time | ||
155 | PubKeyAlgo PublicKeyAlgorithm | ||
156 | PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey | ||
157 | Fingerprint [20]byte | ||
158 | KeyId uint64 | ||
159 | IsSubkey bool | ||
160 | |||
161 | n, e, p, q, g, y parsedMPI | ||
162 | |||
163 | // RFC 6637 fields | ||
164 | ec *ecdsaKey | ||
165 | ecdh *ecdhKdf | ||
166 | } | ||
167 | |||
168 | // signingKey provides a convenient abstraction over signature verification | ||
169 | // for v3 and v4 public keys. | ||
170 | type signingKey interface { | ||
171 | SerializeSignaturePrefix(io.Writer) | ||
172 | serializeWithoutHeaders(io.Writer) error | ||
173 | } | ||
174 | |||
175 | func fromBig(n *big.Int) parsedMPI { | ||
176 | return parsedMPI{ | ||
177 | bytes: n.Bytes(), | ||
178 | bitLength: uint16(n.BitLen()), | ||
179 | } | ||
180 | } | ||
181 | |||
182 | // NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. | ||
183 | func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { | ||
184 | pk := &PublicKey{ | ||
185 | CreationTime: creationTime, | ||
186 | PubKeyAlgo: PubKeyAlgoRSA, | ||
187 | PublicKey: pub, | ||
188 | n: fromBig(pub.N), | ||
189 | e: fromBig(big.NewInt(int64(pub.E))), | ||
190 | } | ||
191 | |||
192 | pk.setFingerPrintAndKeyId() | ||
193 | return pk | ||
194 | } | ||
195 | |||
196 | // NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. | ||
197 | func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { | ||
198 | pk := &PublicKey{ | ||
199 | CreationTime: creationTime, | ||
200 | PubKeyAlgo: PubKeyAlgoDSA, | ||
201 | PublicKey: pub, | ||
202 | p: fromBig(pub.P), | ||
203 | q: fromBig(pub.Q), | ||
204 | g: fromBig(pub.G), | ||
205 | y: fromBig(pub.Y), | ||
206 | } | ||
207 | |||
208 | pk.setFingerPrintAndKeyId() | ||
209 | return pk | ||
210 | } | ||
211 | |||
212 | // NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. | ||
213 | func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { | ||
214 | pk := &PublicKey{ | ||
215 | CreationTime: creationTime, | ||
216 | PubKeyAlgo: PubKeyAlgoElGamal, | ||
217 | PublicKey: pub, | ||
218 | p: fromBig(pub.P), | ||
219 | g: fromBig(pub.G), | ||
220 | y: fromBig(pub.Y), | ||
221 | } | ||
222 | |||
223 | pk.setFingerPrintAndKeyId() | ||
224 | return pk | ||
225 | } | ||
226 | |||
227 | func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { | ||
228 | pk := &PublicKey{ | ||
229 | CreationTime: creationTime, | ||
230 | PubKeyAlgo: PubKeyAlgoECDSA, | ||
231 | PublicKey: pub, | ||
232 | ec: new(ecdsaKey), | ||
233 | } | ||
234 | |||
235 | switch pub.Curve { | ||
236 | case elliptic.P256(): | ||
237 | pk.ec.oid = oidCurveP256 | ||
238 | case elliptic.P384(): | ||
239 | pk.ec.oid = oidCurveP384 | ||
240 | case elliptic.P521(): | ||
241 | pk.ec.oid = oidCurveP521 | ||
242 | default: | ||
243 | panic("unknown elliptic curve") | ||
244 | } | ||
245 | |||
246 | pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) | ||
247 | pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes)) | ||
248 | |||
249 | pk.setFingerPrintAndKeyId() | ||
250 | return pk | ||
251 | } | ||
252 | |||
253 | func (pk *PublicKey) parse(r io.Reader) (err error) { | ||
254 | // RFC 4880, section 5.5.2 | ||
255 | var buf [6]byte | ||
256 | _, err = readFull(r, buf[:]) | ||
257 | if err != nil { | ||
258 | return | ||
259 | } | ||
260 | if buf[0] != 4 { | ||
261 | return errors.UnsupportedError("public key version") | ||
262 | } | ||
263 | pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) | ||
264 | pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) | ||
265 | switch pk.PubKeyAlgo { | ||
266 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
267 | err = pk.parseRSA(r) | ||
268 | case PubKeyAlgoDSA: | ||
269 | err = pk.parseDSA(r) | ||
270 | case PubKeyAlgoElGamal: | ||
271 | err = pk.parseElGamal(r) | ||
272 | case PubKeyAlgoECDSA: | ||
273 | pk.ec = new(ecdsaKey) | ||
274 | if err = pk.ec.parse(r); err != nil { | ||
275 | return err | ||
276 | } | ||
277 | pk.PublicKey, err = pk.ec.newECDSA() | ||
278 | case PubKeyAlgoECDH: | ||
279 | pk.ec = new(ecdsaKey) | ||
280 | if err = pk.ec.parse(r); err != nil { | ||
281 | return | ||
282 | } | ||
283 | pk.ecdh = new(ecdhKdf) | ||
284 | if err = pk.ecdh.parse(r); err != nil { | ||
285 | return | ||
286 | } | ||
287 | // The ECDH key is stored in an ecdsa.PublicKey for convenience. | ||
288 | pk.PublicKey, err = pk.ec.newECDSA() | ||
289 | default: | ||
290 | err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) | ||
291 | } | ||
292 | if err != nil { | ||
293 | return | ||
294 | } | ||
295 | |||
296 | pk.setFingerPrintAndKeyId() | ||
297 | return | ||
298 | } | ||
299 | |||
300 | func (pk *PublicKey) setFingerPrintAndKeyId() { | ||
301 | // RFC 4880, section 12.2 | ||
302 | fingerPrint := sha1.New() | ||
303 | pk.SerializeSignaturePrefix(fingerPrint) | ||
304 | pk.serializeWithoutHeaders(fingerPrint) | ||
305 | copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) | ||
306 | pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) | ||
307 | } | ||
308 | |||
309 | // parseRSA parses RSA public key material from the given Reader. See RFC 4880, | ||
310 | // section 5.5.2. | ||
311 | func (pk *PublicKey) parseRSA(r io.Reader) (err error) { | ||
312 | pk.n.bytes, pk.n.bitLength, err = readMPI(r) | ||
313 | if err != nil { | ||
314 | return | ||
315 | } | ||
316 | pk.e.bytes, pk.e.bitLength, err = readMPI(r) | ||
317 | if err != nil { | ||
318 | return | ||
319 | } | ||
320 | |||
321 | if len(pk.e.bytes) > 3 { | ||
322 | err = errors.UnsupportedError("large public exponent") | ||
323 | return | ||
324 | } | ||
325 | rsa := &rsa.PublicKey{ | ||
326 | N: new(big.Int).SetBytes(pk.n.bytes), | ||
327 | E: 0, | ||
328 | } | ||
329 | for i := 0; i < len(pk.e.bytes); i++ { | ||
330 | rsa.E <<= 8 | ||
331 | rsa.E |= int(pk.e.bytes[i]) | ||
332 | } | ||
333 | pk.PublicKey = rsa | ||
334 | return | ||
335 | } | ||
336 | |||
337 | // parseDSA parses DSA public key material from the given Reader. See RFC 4880, | ||
338 | // section 5.5.2. | ||
339 | func (pk *PublicKey) parseDSA(r io.Reader) (err error) { | ||
340 | pk.p.bytes, pk.p.bitLength, err = readMPI(r) | ||
341 | if err != nil { | ||
342 | return | ||
343 | } | ||
344 | pk.q.bytes, pk.q.bitLength, err = readMPI(r) | ||
345 | if err != nil { | ||
346 | return | ||
347 | } | ||
348 | pk.g.bytes, pk.g.bitLength, err = readMPI(r) | ||
349 | if err != nil { | ||
350 | return | ||
351 | } | ||
352 | pk.y.bytes, pk.y.bitLength, err = readMPI(r) | ||
353 | if err != nil { | ||
354 | return | ||
355 | } | ||
356 | |||
357 | dsa := new(dsa.PublicKey) | ||
358 | dsa.P = new(big.Int).SetBytes(pk.p.bytes) | ||
359 | dsa.Q = new(big.Int).SetBytes(pk.q.bytes) | ||
360 | dsa.G = new(big.Int).SetBytes(pk.g.bytes) | ||
361 | dsa.Y = new(big.Int).SetBytes(pk.y.bytes) | ||
362 | pk.PublicKey = dsa | ||
363 | return | ||
364 | } | ||
365 | |||
366 | // parseElGamal parses ElGamal public key material from the given Reader. See | ||
367 | // RFC 4880, section 5.5.2. | ||
368 | func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { | ||
369 | pk.p.bytes, pk.p.bitLength, err = readMPI(r) | ||
370 | if err != nil { | ||
371 | return | ||
372 | } | ||
373 | pk.g.bytes, pk.g.bitLength, err = readMPI(r) | ||
374 | if err != nil { | ||
375 | return | ||
376 | } | ||
377 | pk.y.bytes, pk.y.bitLength, err = readMPI(r) | ||
378 | if err != nil { | ||
379 | return | ||
380 | } | ||
381 | |||
382 | elgamal := new(elgamal.PublicKey) | ||
383 | elgamal.P = new(big.Int).SetBytes(pk.p.bytes) | ||
384 | elgamal.G = new(big.Int).SetBytes(pk.g.bytes) | ||
385 | elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) | ||
386 | pk.PublicKey = elgamal | ||
387 | return | ||
388 | } | ||
389 | |||
390 | // SerializeSignaturePrefix writes the prefix for this public key to the given Writer. | ||
391 | // The prefix is used when calculating a signature over this public key. See | ||
392 | // RFC 4880, section 5.2.4. | ||
393 | func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { | ||
394 | var pLength uint16 | ||
395 | switch pk.PubKeyAlgo { | ||
396 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
397 | pLength += 2 + uint16(len(pk.n.bytes)) | ||
398 | pLength += 2 + uint16(len(pk.e.bytes)) | ||
399 | case PubKeyAlgoDSA: | ||
400 | pLength += 2 + uint16(len(pk.p.bytes)) | ||
401 | pLength += 2 + uint16(len(pk.q.bytes)) | ||
402 | pLength += 2 + uint16(len(pk.g.bytes)) | ||
403 | pLength += 2 + uint16(len(pk.y.bytes)) | ||
404 | case PubKeyAlgoElGamal: | ||
405 | pLength += 2 + uint16(len(pk.p.bytes)) | ||
406 | pLength += 2 + uint16(len(pk.g.bytes)) | ||
407 | pLength += 2 + uint16(len(pk.y.bytes)) | ||
408 | case PubKeyAlgoECDSA: | ||
409 | pLength += uint16(pk.ec.byteLen()) | ||
410 | case PubKeyAlgoECDH: | ||
411 | pLength += uint16(pk.ec.byteLen()) | ||
412 | pLength += uint16(pk.ecdh.byteLen()) | ||
413 | default: | ||
414 | panic("unknown public key algorithm") | ||
415 | } | ||
416 | pLength += 6 | ||
417 | h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) | ||
418 | return | ||
419 | } | ||
420 | |||
421 | func (pk *PublicKey) Serialize(w io.Writer) (err error) { | ||
422 | length := 6 // 6 byte header | ||
423 | |||
424 | switch pk.PubKeyAlgo { | ||
425 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
426 | length += 2 + len(pk.n.bytes) | ||
427 | length += 2 + len(pk.e.bytes) | ||
428 | case PubKeyAlgoDSA: | ||
429 | length += 2 + len(pk.p.bytes) | ||
430 | length += 2 + len(pk.q.bytes) | ||
431 | length += 2 + len(pk.g.bytes) | ||
432 | length += 2 + len(pk.y.bytes) | ||
433 | case PubKeyAlgoElGamal: | ||
434 | length += 2 + len(pk.p.bytes) | ||
435 | length += 2 + len(pk.g.bytes) | ||
436 | length += 2 + len(pk.y.bytes) | ||
437 | case PubKeyAlgoECDSA: | ||
438 | length += pk.ec.byteLen() | ||
439 | case PubKeyAlgoECDH: | ||
440 | length += pk.ec.byteLen() | ||
441 | length += pk.ecdh.byteLen() | ||
442 | default: | ||
443 | panic("unknown public key algorithm") | ||
444 | } | ||
445 | |||
446 | packetType := packetTypePublicKey | ||
447 | if pk.IsSubkey { | ||
448 | packetType = packetTypePublicSubkey | ||
449 | } | ||
450 | err = serializeHeader(w, packetType, length) | ||
451 | if err != nil { | ||
452 | return | ||
453 | } | ||
454 | return pk.serializeWithoutHeaders(w) | ||
455 | } | ||
456 | |||
457 | // serializeWithoutHeaders marshals the PublicKey to w in the form of an | ||
458 | // OpenPGP public key packet, not including the packet header. | ||
459 | func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { | ||
460 | var buf [6]byte | ||
461 | buf[0] = 4 | ||
462 | t := uint32(pk.CreationTime.Unix()) | ||
463 | buf[1] = byte(t >> 24) | ||
464 | buf[2] = byte(t >> 16) | ||
465 | buf[3] = byte(t >> 8) | ||
466 | buf[4] = byte(t) | ||
467 | buf[5] = byte(pk.PubKeyAlgo) | ||
468 | |||
469 | _, err = w.Write(buf[:]) | ||
470 | if err != nil { | ||
471 | return | ||
472 | } | ||
473 | |||
474 | switch pk.PubKeyAlgo { | ||
475 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
476 | return writeMPIs(w, pk.n, pk.e) | ||
477 | case PubKeyAlgoDSA: | ||
478 | return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) | ||
479 | case PubKeyAlgoElGamal: | ||
480 | return writeMPIs(w, pk.p, pk.g, pk.y) | ||
481 | case PubKeyAlgoECDSA: | ||
482 | return pk.ec.serialize(w) | ||
483 | case PubKeyAlgoECDH: | ||
484 | if err = pk.ec.serialize(w); err != nil { | ||
485 | return | ||
486 | } | ||
487 | return pk.ecdh.serialize(w) | ||
488 | } | ||
489 | return errors.InvalidArgumentError("bad public-key algorithm") | ||
490 | } | ||
491 | |||
492 | // CanSign returns true iff this public key can generate signatures | ||
493 | func (pk *PublicKey) CanSign() bool { | ||
494 | return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal | ||
495 | } | ||
496 | |||
497 | // VerifySignature returns nil iff sig is a valid signature, made by this | ||
498 | // public key, of the data hashed into signed. signed is mutated by this call. | ||
499 | func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { | ||
500 | if !pk.CanSign() { | ||
501 | return errors.InvalidArgumentError("public key cannot generate signatures") | ||
502 | } | ||
503 | |||
504 | signed.Write(sig.HashSuffix) | ||
505 | hashBytes := signed.Sum(nil) | ||
506 | |||
507 | if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { | ||
508 | return errors.SignatureError("hash tag doesn't match") | ||
509 | } | ||
510 | |||
511 | if pk.PubKeyAlgo != sig.PubKeyAlgo { | ||
512 | return errors.InvalidArgumentError("public key and signature use different algorithms") | ||
513 | } | ||
514 | |||
515 | switch pk.PubKeyAlgo { | ||
516 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | ||
517 | rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) | ||
518 | err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes) | ||
519 | if err != nil { | ||
520 | return errors.SignatureError("RSA verification failure") | ||
521 | } | ||
522 | return nil | ||
523 | case PubKeyAlgoDSA: | ||
524 | dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) | ||
525 | // Need to truncate hashBytes to match FIPS 186-3 section 4.6. | ||
526 | subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 | ||
527 | if len(hashBytes) > subgroupSize { | ||
528 | hashBytes = hashBytes[:subgroupSize] | ||
529 | } | ||
530 | if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { | ||
531 | return errors.SignatureError("DSA verification failure") | ||
532 | } | ||
533 | return nil | ||
534 | case PubKeyAlgoECDSA: | ||
535 | ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) | ||
536 | if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { | ||
537 | return errors.SignatureError("ECDSA verification failure") | ||
538 | } | ||
539 | return nil | ||
540 | default: | ||
541 | return errors.SignatureError("Unsupported public key algorithm used in signature") | ||
542 | } | ||
543 | } | ||
544 | |||
545 | // VerifySignatureV3 returns nil iff sig is a valid signature, made by this | ||
546 | // public key, of the data hashed into signed. signed is mutated by this call. | ||
547 | func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { | ||
548 | if !pk.CanSign() { | ||
549 | return errors.InvalidArgumentError("public key cannot generate signatures") | ||
550 | } | ||
551 | |||
552 | suffix := make([]byte, 5) | ||
553 | suffix[0] = byte(sig.SigType) | ||
554 | binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) | ||
555 | signed.Write(suffix) | ||
556 | hashBytes := signed.Sum(nil) | ||
557 | |||
558 | if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { | ||
559 | return errors.SignatureError("hash tag doesn't match") | ||
560 | } | ||
561 | |||
562 | if pk.PubKeyAlgo != sig.PubKeyAlgo { | ||
563 | return errors.InvalidArgumentError("public key and signature use different algorithms") | ||
564 | } | ||
565 | |||
566 | switch pk.PubKeyAlgo { | ||
567 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | ||
568 | rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) | ||
569 | if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { | ||
570 | return errors.SignatureError("RSA verification failure") | ||
571 | } | ||
572 | return | ||
573 | case PubKeyAlgoDSA: | ||
574 | dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) | ||
575 | // Need to truncate hashBytes to match FIPS 186-3 section 4.6. | ||
576 | subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 | ||
577 | if len(hashBytes) > subgroupSize { | ||
578 | hashBytes = hashBytes[:subgroupSize] | ||
579 | } | ||
580 | if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { | ||
581 | return errors.SignatureError("DSA verification failure") | ||
582 | } | ||
583 | return nil | ||
584 | default: | ||
585 | panic("shouldn't happen") | ||
586 | } | ||
587 | } | ||
588 | |||
589 | // keySignatureHash returns a Hash of the message that needs to be signed for | ||
590 | // pk to assert a subkey relationship to signed. | ||
591 | func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { | ||
592 | if !hashFunc.Available() { | ||
593 | return nil, errors.UnsupportedError("hash function") | ||
594 | } | ||
595 | h = hashFunc.New() | ||
596 | |||
597 | // RFC 4880, section 5.2.4 | ||
598 | pk.SerializeSignaturePrefix(h) | ||
599 | pk.serializeWithoutHeaders(h) | ||
600 | signed.SerializeSignaturePrefix(h) | ||
601 | signed.serializeWithoutHeaders(h) | ||
602 | return | ||
603 | } | ||
604 | |||
605 | // VerifyKeySignature returns nil iff sig is a valid signature, made by this | ||
606 | // public key, of signed. | ||
607 | func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { | ||
608 | h, err := keySignatureHash(pk, signed, sig.Hash) | ||
609 | if err != nil { | ||
610 | return err | ||
611 | } | ||
612 | if err = pk.VerifySignature(h, sig); err != nil { | ||
613 | return err | ||
614 | } | ||
615 | |||
616 | if sig.FlagSign { | ||
617 | // Signing subkeys must be cross-signed. See | ||
618 | // https://www.gnupg.org/faq/subkey-cross-certify.html. | ||
619 | if sig.EmbeddedSignature == nil { | ||
620 | return errors.StructuralError("signing subkey is missing cross-signature") | ||
621 | } | ||
622 | // Verify the cross-signature. This is calculated over the same | ||
623 | // data as the main signature, so we cannot just recursively | ||
624 | // call signed.VerifyKeySignature(...) | ||
625 | if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { | ||
626 | return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) | ||
627 | } | ||
628 | if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { | ||
629 | return errors.StructuralError("error while verifying cross-signature: " + err.Error()) | ||
630 | } | ||
631 | } | ||
632 | |||
633 | return nil | ||
634 | } | ||
635 | |||
636 | func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { | ||
637 | if !hashFunc.Available() { | ||
638 | return nil, errors.UnsupportedError("hash function") | ||
639 | } | ||
640 | h = hashFunc.New() | ||
641 | |||
642 | // RFC 4880, section 5.2.4 | ||
643 | pk.SerializeSignaturePrefix(h) | ||
644 | pk.serializeWithoutHeaders(h) | ||
645 | |||
646 | return | ||
647 | } | ||
648 | |||
649 | // VerifyRevocationSignature returns nil iff sig is a valid signature, made by this | ||
650 | // public key. | ||
651 | func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { | ||
652 | h, err := keyRevocationHash(pk, sig.Hash) | ||
653 | if err != nil { | ||
654 | return err | ||
655 | } | ||
656 | return pk.VerifySignature(h, sig) | ||
657 | } | ||
658 | |||
659 | // userIdSignatureHash returns a Hash of the message that needs to be signed | ||
660 | // to assert that pk is a valid key for id. | ||
661 | func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { | ||
662 | if !hashFunc.Available() { | ||
663 | return nil, errors.UnsupportedError("hash function") | ||
664 | } | ||
665 | h = hashFunc.New() | ||
666 | |||
667 | // RFC 4880, section 5.2.4 | ||
668 | pk.SerializeSignaturePrefix(h) | ||
669 | pk.serializeWithoutHeaders(h) | ||
670 | |||
671 | var buf [5]byte | ||
672 | buf[0] = 0xb4 | ||
673 | buf[1] = byte(len(id) >> 24) | ||
674 | buf[2] = byte(len(id) >> 16) | ||
675 | buf[3] = byte(len(id) >> 8) | ||
676 | buf[4] = byte(len(id)) | ||
677 | h.Write(buf[:]) | ||
678 | h.Write([]byte(id)) | ||
679 | |||
680 | return | ||
681 | } | ||
682 | |||
683 | // VerifyUserIdSignature returns nil iff sig is a valid signature, made by this | ||
684 | // public key, that id is the identity of pub. | ||
685 | func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { | ||
686 | h, err := userIdSignatureHash(id, pub, sig.Hash) | ||
687 | if err != nil { | ||
688 | return err | ||
689 | } | ||
690 | return pk.VerifySignature(h, sig) | ||
691 | } | ||
692 | |||
693 | // VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this | ||
694 | // public key, that id is the identity of pub. | ||
695 | func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { | ||
696 | h, err := userIdSignatureV3Hash(id, pub, sig.Hash) | ||
697 | if err != nil { | ||
698 | return err | ||
699 | } | ||
700 | return pk.VerifySignatureV3(h, sig) | ||
701 | } | ||
702 | |||
703 | // KeyIdString returns the public key's fingerprint in capital hex | ||
704 | // (e.g. "6C7EE1B8621CC013"). | ||
705 | func (pk *PublicKey) KeyIdString() string { | ||
706 | return fmt.Sprintf("%X", pk.Fingerprint[12:20]) | ||
707 | } | ||
708 | |||
709 | // KeyIdShortString returns the short form of public key's fingerprint | ||
710 | // in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). | ||
711 | func (pk *PublicKey) KeyIdShortString() string { | ||
712 | return fmt.Sprintf("%X", pk.Fingerprint[16:20]) | ||
713 | } | ||
714 | |||
715 | // A parsedMPI is used to store the contents of a big integer, along with the | ||
716 | // bit length that was specified in the original input. This allows the MPI to | ||
717 | // be reserialized exactly. | ||
718 | type parsedMPI struct { | ||
719 | bytes []byte | ||
720 | bitLength uint16 | ||
721 | } | ||
722 | |||
723 | // writeMPIs is a utility function for serializing several big integers to the | ||
724 | // given Writer. | ||
725 | func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { | ||
726 | for _, mpi := range mpis { | ||
727 | err = writeMPI(w, mpi.bitLength, mpi.bytes) | ||
728 | if err != nil { | ||
729 | return | ||
730 | } | ||
731 | } | ||
732 | return | ||
733 | } | ||
734 | |||
735 | // BitLength returns the bit length for the given public key. | ||
736 | func (pk *PublicKey) BitLength() (bitLength uint16, err error) { | ||
737 | switch pk.PubKeyAlgo { | ||
738 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | ||
739 | bitLength = pk.n.bitLength | ||
740 | case PubKeyAlgoDSA: | ||
741 | bitLength = pk.p.bitLength | ||
742 | case PubKeyAlgoElGamal: | ||
743 | bitLength = pk.p.bitLength | ||
744 | default: | ||
745 | err = errors.InvalidArgumentError("bad public-key algorithm") | ||
746 | } | ||
747 | return | ||
748 | } | ||