]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/golang.org/x/crypto/openpgp/packet/public_key.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / golang.org / x / crypto / openpgp / packet / public_key.go
CommitLineData
c680a8e1
RS
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
5package packet
6
7import (
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
29var (
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
38const maxOIDLength = 8
39
40// ecdsaKey stores the algorithm-specific fields for ECDSA keys.
41// as defined in RFC 6637, Section 9.
42type 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.
50func 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
65func (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
73func (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
83func (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
101func (f *ecdsaKey) byteLen() int {
102 return 1 + len(f.oid) + 2 + len(f.p.bytes)
103}
104
105type kdfHashFunction byte
106type kdfAlgorithm byte
107
108// ecdhKdf stores key derivation function parameters
109// used for ECDH encryption. See RFC 6637, Section 9.
110type ecdhKdf struct {
111 KdfHash kdfHashFunction
112 KdfAlgo kdfAlgorithm
113}
114
115func (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
137func (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
148func (f *ecdhKdf) byteLen() int {
149 return 4
150}
151
152// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
153type 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.
170type signingKey interface {
171 SerializeSignaturePrefix(io.Writer)
172 serializeWithoutHeaders(io.Writer) error
173}
174
175func 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.
183func 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.
197func 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.
213func 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
227func 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)
107c1cdb
ND
247
248 // The bit length is 3 (for the 0x04 specifying an uncompressed key)
249 // plus two field elements (for x and y), which are rounded up to the
250 // nearest byte. See https://tools.ietf.org/html/rfc6637#section-6
251 fieldBytes := (pub.Curve.Params().BitSize + 7) & ^7
252 pk.ec.p.bitLength = uint16(3 + fieldBytes + fieldBytes)
c680a8e1
RS
253
254 pk.setFingerPrintAndKeyId()
255 return pk
256}
257
258func (pk *PublicKey) parse(r io.Reader) (err error) {
259 // RFC 4880, section 5.5.2
260 var buf [6]byte
261 _, err = readFull(r, buf[:])
262 if err != nil {
263 return
264 }
265 if buf[0] != 4 {
266 return errors.UnsupportedError("public key version")
267 }
268 pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
269 pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
270 switch pk.PubKeyAlgo {
271 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
272 err = pk.parseRSA(r)
273 case PubKeyAlgoDSA:
274 err = pk.parseDSA(r)
275 case PubKeyAlgoElGamal:
276 err = pk.parseElGamal(r)
277 case PubKeyAlgoECDSA:
278 pk.ec = new(ecdsaKey)
279 if err = pk.ec.parse(r); err != nil {
280 return err
281 }
282 pk.PublicKey, err = pk.ec.newECDSA()
283 case PubKeyAlgoECDH:
284 pk.ec = new(ecdsaKey)
285 if err = pk.ec.parse(r); err != nil {
286 return
287 }
288 pk.ecdh = new(ecdhKdf)
289 if err = pk.ecdh.parse(r); err != nil {
290 return
291 }
292 // The ECDH key is stored in an ecdsa.PublicKey for convenience.
293 pk.PublicKey, err = pk.ec.newECDSA()
294 default:
295 err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
296 }
297 if err != nil {
298 return
299 }
300
301 pk.setFingerPrintAndKeyId()
302 return
303}
304
305func (pk *PublicKey) setFingerPrintAndKeyId() {
306 // RFC 4880, section 12.2
307 fingerPrint := sha1.New()
308 pk.SerializeSignaturePrefix(fingerPrint)
309 pk.serializeWithoutHeaders(fingerPrint)
310 copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
311 pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
312}
313
314// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
315// section 5.5.2.
316func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
317 pk.n.bytes, pk.n.bitLength, err = readMPI(r)
318 if err != nil {
319 return
320 }
321 pk.e.bytes, pk.e.bitLength, err = readMPI(r)
322 if err != nil {
323 return
324 }
325
326 if len(pk.e.bytes) > 3 {
327 err = errors.UnsupportedError("large public exponent")
328 return
329 }
330 rsa := &rsa.PublicKey{
331 N: new(big.Int).SetBytes(pk.n.bytes),
332 E: 0,
333 }
334 for i := 0; i < len(pk.e.bytes); i++ {
335 rsa.E <<= 8
336 rsa.E |= int(pk.e.bytes[i])
337 }
338 pk.PublicKey = rsa
339 return
340}
341
342// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
343// section 5.5.2.
344func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
345 pk.p.bytes, pk.p.bitLength, err = readMPI(r)
346 if err != nil {
347 return
348 }
349 pk.q.bytes, pk.q.bitLength, err = readMPI(r)
350 if err != nil {
351 return
352 }
353 pk.g.bytes, pk.g.bitLength, err = readMPI(r)
354 if err != nil {
355 return
356 }
357 pk.y.bytes, pk.y.bitLength, err = readMPI(r)
358 if err != nil {
359 return
360 }
361
362 dsa := new(dsa.PublicKey)
363 dsa.P = new(big.Int).SetBytes(pk.p.bytes)
364 dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
365 dsa.G = new(big.Int).SetBytes(pk.g.bytes)
366 dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
367 pk.PublicKey = dsa
368 return
369}
370
371// parseElGamal parses ElGamal public key material from the given Reader. See
372// RFC 4880, section 5.5.2.
373func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
374 pk.p.bytes, pk.p.bitLength, err = readMPI(r)
375 if err != nil {
376 return
377 }
378 pk.g.bytes, pk.g.bitLength, err = readMPI(r)
379 if err != nil {
380 return
381 }
382 pk.y.bytes, pk.y.bitLength, err = readMPI(r)
383 if err != nil {
384 return
385 }
386
387 elgamal := new(elgamal.PublicKey)
388 elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
389 elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
390 elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
391 pk.PublicKey = elgamal
392 return
393}
394
395// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
396// The prefix is used when calculating a signature over this public key. See
397// RFC 4880, section 5.2.4.
398func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) {
399 var pLength uint16
400 switch pk.PubKeyAlgo {
401 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
402 pLength += 2 + uint16(len(pk.n.bytes))
403 pLength += 2 + uint16(len(pk.e.bytes))
404 case PubKeyAlgoDSA:
405 pLength += 2 + uint16(len(pk.p.bytes))
406 pLength += 2 + uint16(len(pk.q.bytes))
407 pLength += 2 + uint16(len(pk.g.bytes))
408 pLength += 2 + uint16(len(pk.y.bytes))
409 case PubKeyAlgoElGamal:
410 pLength += 2 + uint16(len(pk.p.bytes))
411 pLength += 2 + uint16(len(pk.g.bytes))
412 pLength += 2 + uint16(len(pk.y.bytes))
413 case PubKeyAlgoECDSA:
414 pLength += uint16(pk.ec.byteLen())
415 case PubKeyAlgoECDH:
416 pLength += uint16(pk.ec.byteLen())
417 pLength += uint16(pk.ecdh.byteLen())
418 default:
419 panic("unknown public key algorithm")
420 }
421 pLength += 6
422 h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
423 return
424}
425
426func (pk *PublicKey) Serialize(w io.Writer) (err error) {
427 length := 6 // 6 byte header
428
429 switch pk.PubKeyAlgo {
430 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
431 length += 2 + len(pk.n.bytes)
432 length += 2 + len(pk.e.bytes)
433 case PubKeyAlgoDSA:
434 length += 2 + len(pk.p.bytes)
435 length += 2 + len(pk.q.bytes)
436 length += 2 + len(pk.g.bytes)
437 length += 2 + len(pk.y.bytes)
438 case PubKeyAlgoElGamal:
439 length += 2 + len(pk.p.bytes)
440 length += 2 + len(pk.g.bytes)
441 length += 2 + len(pk.y.bytes)
442 case PubKeyAlgoECDSA:
443 length += pk.ec.byteLen()
444 case PubKeyAlgoECDH:
445 length += pk.ec.byteLen()
446 length += pk.ecdh.byteLen()
447 default:
448 panic("unknown public key algorithm")
449 }
450
451 packetType := packetTypePublicKey
452 if pk.IsSubkey {
453 packetType = packetTypePublicSubkey
454 }
455 err = serializeHeader(w, packetType, length)
456 if err != nil {
457 return
458 }
459 return pk.serializeWithoutHeaders(w)
460}
461
462// serializeWithoutHeaders marshals the PublicKey to w in the form of an
463// OpenPGP public key packet, not including the packet header.
464func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
465 var buf [6]byte
466 buf[0] = 4
467 t := uint32(pk.CreationTime.Unix())
468 buf[1] = byte(t >> 24)
469 buf[2] = byte(t >> 16)
470 buf[3] = byte(t >> 8)
471 buf[4] = byte(t)
472 buf[5] = byte(pk.PubKeyAlgo)
473
474 _, err = w.Write(buf[:])
475 if err != nil {
476 return
477 }
478
479 switch pk.PubKeyAlgo {
480 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
481 return writeMPIs(w, pk.n, pk.e)
482 case PubKeyAlgoDSA:
483 return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
484 case PubKeyAlgoElGamal:
485 return writeMPIs(w, pk.p, pk.g, pk.y)
486 case PubKeyAlgoECDSA:
487 return pk.ec.serialize(w)
488 case PubKeyAlgoECDH:
489 if err = pk.ec.serialize(w); err != nil {
490 return
491 }
492 return pk.ecdh.serialize(w)
493 }
494 return errors.InvalidArgumentError("bad public-key algorithm")
495}
496
497// CanSign returns true iff this public key can generate signatures
498func (pk *PublicKey) CanSign() bool {
499 return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
500}
501
502// VerifySignature returns nil iff sig is a valid signature, made by this
503// public key, of the data hashed into signed. signed is mutated by this call.
504func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
505 if !pk.CanSign() {
506 return errors.InvalidArgumentError("public key cannot generate signatures")
507 }
508
509 signed.Write(sig.HashSuffix)
510 hashBytes := signed.Sum(nil)
511
512 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
513 return errors.SignatureError("hash tag doesn't match")
514 }
515
516 if pk.PubKeyAlgo != sig.PubKeyAlgo {
517 return errors.InvalidArgumentError("public key and signature use different algorithms")
518 }
519
520 switch pk.PubKeyAlgo {
521 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
522 rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
107c1cdb 523 err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes))
c680a8e1
RS
524 if err != nil {
525 return errors.SignatureError("RSA verification failure")
526 }
527 return nil
528 case PubKeyAlgoDSA:
529 dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
530 // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
531 subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
532 if len(hashBytes) > subgroupSize {
533 hashBytes = hashBytes[:subgroupSize]
534 }
535 if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
536 return errors.SignatureError("DSA verification failure")
537 }
538 return nil
539 case PubKeyAlgoECDSA:
540 ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
541 if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) {
542 return errors.SignatureError("ECDSA verification failure")
543 }
544 return nil
545 default:
546 return errors.SignatureError("Unsupported public key algorithm used in signature")
547 }
548}
549
550// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
551// public key, of the data hashed into signed. signed is mutated by this call.
552func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
553 if !pk.CanSign() {
554 return errors.InvalidArgumentError("public key cannot generate signatures")
555 }
556
557 suffix := make([]byte, 5)
558 suffix[0] = byte(sig.SigType)
559 binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
560 signed.Write(suffix)
561 hashBytes := signed.Sum(nil)
562
563 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
564 return errors.SignatureError("hash tag doesn't match")
565 }
566
567 if pk.PubKeyAlgo != sig.PubKeyAlgo {
568 return errors.InvalidArgumentError("public key and signature use different algorithms")
569 }
570
571 switch pk.PubKeyAlgo {
572 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
573 rsaPublicKey := pk.PublicKey.(*rsa.PublicKey)
107c1cdb 574 if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil {
c680a8e1
RS
575 return errors.SignatureError("RSA verification failure")
576 }
577 return
578 case PubKeyAlgoDSA:
579 dsaPublicKey := pk.PublicKey.(*dsa.PublicKey)
580 // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
581 subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
582 if len(hashBytes) > subgroupSize {
583 hashBytes = hashBytes[:subgroupSize]
584 }
585 if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
586 return errors.SignatureError("DSA verification failure")
587 }
588 return nil
589 default:
590 panic("shouldn't happen")
591 }
592}
593
594// keySignatureHash returns a Hash of the message that needs to be signed for
595// pk to assert a subkey relationship to signed.
596func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
597 if !hashFunc.Available() {
598 return nil, errors.UnsupportedError("hash function")
599 }
600 h = hashFunc.New()
601
602 // RFC 4880, section 5.2.4
603 pk.SerializeSignaturePrefix(h)
604 pk.serializeWithoutHeaders(h)
605 signed.SerializeSignaturePrefix(h)
606 signed.serializeWithoutHeaders(h)
607 return
608}
609
610// VerifyKeySignature returns nil iff sig is a valid signature, made by this
611// public key, of signed.
612func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
613 h, err := keySignatureHash(pk, signed, sig.Hash)
614 if err != nil {
615 return err
616 }
617 if err = pk.VerifySignature(h, sig); err != nil {
618 return err
619 }
620
621 if sig.FlagSign {
622 // Signing subkeys must be cross-signed. See
623 // https://www.gnupg.org/faq/subkey-cross-certify.html.
624 if sig.EmbeddedSignature == nil {
625 return errors.StructuralError("signing subkey is missing cross-signature")
626 }
627 // Verify the cross-signature. This is calculated over the same
628 // data as the main signature, so we cannot just recursively
629 // call signed.VerifyKeySignature(...)
630 if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil {
631 return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
632 }
633 if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
634 return errors.StructuralError("error while verifying cross-signature: " + err.Error())
635 }
636 }
637
638 return nil
639}
640
641func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
642 if !hashFunc.Available() {
643 return nil, errors.UnsupportedError("hash function")
644 }
645 h = hashFunc.New()
646
647 // RFC 4880, section 5.2.4
648 pk.SerializeSignaturePrefix(h)
649 pk.serializeWithoutHeaders(h)
650
651 return
652}
653
654// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
655// public key.
656func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
657 h, err := keyRevocationHash(pk, sig.Hash)
658 if err != nil {
659 return err
660 }
661 return pk.VerifySignature(h, sig)
662}
663
664// userIdSignatureHash returns a Hash of the message that needs to be signed
665// to assert that pk is a valid key for id.
666func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
667 if !hashFunc.Available() {
668 return nil, errors.UnsupportedError("hash function")
669 }
670 h = hashFunc.New()
671
672 // RFC 4880, section 5.2.4
673 pk.SerializeSignaturePrefix(h)
674 pk.serializeWithoutHeaders(h)
675
676 var buf [5]byte
677 buf[0] = 0xb4
678 buf[1] = byte(len(id) >> 24)
679 buf[2] = byte(len(id) >> 16)
680 buf[3] = byte(len(id) >> 8)
681 buf[4] = byte(len(id))
682 h.Write(buf[:])
683 h.Write([]byte(id))
684
685 return
686}
687
688// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
689// public key, that id is the identity of pub.
690func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
691 h, err := userIdSignatureHash(id, pub, sig.Hash)
692 if err != nil {
693 return err
694 }
695 return pk.VerifySignature(h, sig)
696}
697
698// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
699// public key, that id is the identity of pub.
700func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) {
701 h, err := userIdSignatureV3Hash(id, pub, sig.Hash)
702 if err != nil {
703 return err
704 }
705 return pk.VerifySignatureV3(h, sig)
706}
707
708// KeyIdString returns the public key's fingerprint in capital hex
709// (e.g. "6C7EE1B8621CC013").
710func (pk *PublicKey) KeyIdString() string {
711 return fmt.Sprintf("%X", pk.Fingerprint[12:20])
712}
713
714// KeyIdShortString returns the short form of public key's fingerprint
715// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
716func (pk *PublicKey) KeyIdShortString() string {
717 return fmt.Sprintf("%X", pk.Fingerprint[16:20])
718}
719
720// A parsedMPI is used to store the contents of a big integer, along with the
721// bit length that was specified in the original input. This allows the MPI to
722// be reserialized exactly.
723type parsedMPI struct {
724 bytes []byte
725 bitLength uint16
726}
727
728// writeMPIs is a utility function for serializing several big integers to the
729// given Writer.
730func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
731 for _, mpi := range mpis {
732 err = writeMPI(w, mpi.bitLength, mpi.bytes)
733 if err != nil {
734 return
735 }
736 }
737 return
738}
739
740// BitLength returns the bit length for the given public key.
741func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
742 switch pk.PubKeyAlgo {
743 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
744 bitLength = pk.n.bitLength
745 case PubKeyAlgoDSA:
746 bitLength = pk.p.bitLength
747 case PubKeyAlgoElGamal:
748 bitLength = pk.p.bitLength
749 default:
750 err = errors.InvalidArgumentError("bad public-key algorithm")
751 }
752 return
753}