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)
247	pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes))
248
249	pk.setFingerPrintAndKeyId()
250	return pk
251}
252
253func (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
300func (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.
311func (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.
339func (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.
368func (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.
393func (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
421func (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.
459func (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
493func (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.
499func (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.
547func (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.
591func 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.
607func (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
636func 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.
651func (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.
661func 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.
685func (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.
695func (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").
705func (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").
711func (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.
718type 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.
725func 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.
736func (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}
749