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	"crypto"
9	"crypto/dsa"
10	"crypto/ecdsa"
11	"crypto/elliptic"
12	"crypto/rsa"
13	"crypto/sha1"
14	"crypto/sha256"
15	_ "crypto/sha512"
16	"encoding/binary"
17	"fmt"
18	"hash"
19	"io"
20	"math/big"
21	"strconv"
22	"time"
23
24	"github.com/ProtonMail/go-crypto/openpgp/ecdh"
25	"github.com/ProtonMail/go-crypto/openpgp/elgamal"
26	"github.com/ProtonMail/go-crypto/openpgp/errors"
27	"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
28	"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
29	"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
30	"golang.org/x/crypto/ed25519"
31)
32
33type kdfHashFunction byte
34type kdfAlgorithm byte
35
36// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
37type PublicKey struct {
38	Version      int
39	CreationTime time.Time
40	PubKeyAlgo   PublicKeyAlgorithm
41	PublicKey    interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey
42	Fingerprint  []byte
43	KeyId        uint64
44	IsSubkey     bool
45
46	// RFC 4880 fields
47	n, e, p, q, g, y encoding.Field
48
49	// RFC 6637 fields
50	// oid contains the OID byte sequence identifying the elliptic curve used
51	oid encoding.Field
52
53	// kdf stores key derivation function parameters
54	// used for ECDH encryption. See RFC 6637, Section 9.
55	kdf encoding.Field
56}
57
58// UpgradeToV5 updates the version of the key to v5, and updates all necessary
59// fields.
60func (pk *PublicKey) UpgradeToV5() {
61	pk.Version = 5
62	pk.setFingerprintAndKeyId()
63}
64
65// signingKey provides a convenient abstraction over signature verification
66// for v3 and v4 public keys.
67type signingKey interface {
68	SerializeForHash(io.Writer) error
69	SerializeSignaturePrefix(io.Writer)
70	serializeWithoutHeaders(io.Writer) error
71}
72
73// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
74func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
75	pk := &PublicKey{
76		Version:      4,
77		CreationTime: creationTime,
78		PubKeyAlgo:   PubKeyAlgoRSA,
79		PublicKey:    pub,
80		n:            new(encoding.MPI).SetBig(pub.N),
81		e:            new(encoding.MPI).SetBig(big.NewInt(int64(pub.E))),
82	}
83
84	pk.setFingerprintAndKeyId()
85	return pk
86}
87
88// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey.
89func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
90	pk := &PublicKey{
91		Version:      4,
92		CreationTime: creationTime,
93		PubKeyAlgo:   PubKeyAlgoDSA,
94		PublicKey:    pub,
95		p:            new(encoding.MPI).SetBig(pub.P),
96		q:            new(encoding.MPI).SetBig(pub.Q),
97		g:            new(encoding.MPI).SetBig(pub.G),
98		y:            new(encoding.MPI).SetBig(pub.Y),
99	}
100
101	pk.setFingerprintAndKeyId()
102	return pk
103}
104
105// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
106func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
107	pk := &PublicKey{
108		Version:      4,
109		CreationTime: creationTime,
110		PubKeyAlgo:   PubKeyAlgoElGamal,
111		PublicKey:    pub,
112		p:            new(encoding.MPI).SetBig(pub.P),
113		g:            new(encoding.MPI).SetBig(pub.G),
114		y:            new(encoding.MPI).SetBig(pub.Y),
115	}
116
117	pk.setFingerprintAndKeyId()
118	return pk
119}
120
121func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
122	pk := &PublicKey{
123		Version:      4,
124		CreationTime: creationTime,
125		PubKeyAlgo:   PubKeyAlgoECDSA,
126		PublicKey:    pub,
127		p:            encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)),
128	}
129
130	curveInfo := ecc.FindByCurve(pub.Curve)
131	if curveInfo == nil {
132		panic("unknown elliptic curve")
133	}
134	pk.oid = curveInfo.Oid
135	pk.setFingerprintAndKeyId()
136	return pk
137}
138
139func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey {
140	var pk *PublicKey
141	var curveInfo *ecc.CurveInfo
142	var kdf = encoding.NewOID([]byte{0x1, pub.Hash.Id(), pub.Cipher.Id()})
143	if pub.CurveType == ecc.Curve25519 {
144		pk = &PublicKey{
145			Version:      4,
146			CreationTime: creationTime,
147			PubKeyAlgo:   PubKeyAlgoECDH,
148			PublicKey:    pub,
149			p:            encoding.NewMPI(pub.X.Bytes()),
150			kdf:          kdf,
151		}
152		curveInfo = ecc.FindByName("Curve25519")
153	} else {
154		pk = &PublicKey{
155			Version:      4,
156			CreationTime: creationTime,
157			PubKeyAlgo:   PubKeyAlgoECDH,
158			PublicKey:    pub,
159			p:            encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)),
160			kdf:          kdf,
161		}
162		curveInfo = ecc.FindByCurve(pub.Curve)
163	}
164	if curveInfo == nil {
165		panic("unknown elliptic curve")
166	}
167	pk.oid = curveInfo.Oid
168	pk.setFingerprintAndKeyId()
169	return pk
170}
171
172func NewEdDSAPublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey {
173	curveInfo := ecc.FindByName("Ed25519")
174	pk := &PublicKey{
175		Version:      4,
176		CreationTime: creationTime,
177		PubKeyAlgo:   PubKeyAlgoEdDSA,
178		PublicKey:    pub,
179		oid:          curveInfo.Oid,
180		// Native point format, see draft-koch-eddsa-for-openpgp-04, Appendix B
181		p: encoding.NewMPI(append([]byte{0x40}, *pub...)),
182	}
183
184	pk.setFingerprintAndKeyId()
185	return pk
186}
187
188func (pk *PublicKey) parse(r io.Reader) (err error) {
189	// RFC 4880, section 5.5.2
190	var buf [6]byte
191	_, err = readFull(r, buf[:])
192	if err != nil {
193		return
194	}
195	if buf[0] != 4 && buf[0] != 5 {
196		return errors.UnsupportedError("public key version " + strconv.Itoa(int(buf[0])))
197	}
198
199	pk.Version = int(buf[0])
200	if pk.Version == 5 {
201		var n [4]byte
202		_, err = readFull(r, n[:])
203		if err != nil {
204			return
205		}
206	}
207	pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
208	pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
209	switch pk.PubKeyAlgo {
210	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
211		err = pk.parseRSA(r)
212	case PubKeyAlgoDSA:
213		err = pk.parseDSA(r)
214	case PubKeyAlgoElGamal:
215		err = pk.parseElGamal(r)
216	case PubKeyAlgoECDSA:
217		err = pk.parseECDSA(r)
218	case PubKeyAlgoECDH:
219		err = pk.parseECDH(r)
220	case PubKeyAlgoEdDSA:
221		err = pk.parseEdDSA(r)
222	default:
223		err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
224	}
225	if err != nil {
226		return
227	}
228
229	pk.setFingerprintAndKeyId()
230	return
231}
232
233func (pk *PublicKey) setFingerprintAndKeyId() {
234	// RFC 4880, section 12.2
235	if pk.Version == 5 {
236		fingerprint := sha256.New()
237		pk.SerializeForHash(fingerprint)
238		pk.Fingerprint = make([]byte, 32)
239		copy(pk.Fingerprint, fingerprint.Sum(nil))
240		pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[:8])
241	} else {
242		fingerprint := sha1.New()
243		pk.SerializeForHash(fingerprint)
244		pk.Fingerprint = make([]byte, 20)
245		copy(pk.Fingerprint, fingerprint.Sum(nil))
246		pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
247	}
248}
249
250// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
251// section 5.5.2.
252func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
253	pk.n = new(encoding.MPI)
254	if _, err = pk.n.ReadFrom(r); err != nil {
255		return
256	}
257	pk.e = new(encoding.MPI)
258	if _, err = pk.e.ReadFrom(r); err != nil {
259		return
260	}
261
262	if len(pk.e.Bytes()) > 3 {
263		err = errors.UnsupportedError("large public exponent")
264		return
265	}
266	rsa := &rsa.PublicKey{
267		N: new(big.Int).SetBytes(pk.n.Bytes()),
268		E: 0,
269	}
270	for i := 0; i < len(pk.e.Bytes()); i++ {
271		rsa.E <<= 8
272		rsa.E |= int(pk.e.Bytes()[i])
273	}
274	pk.PublicKey = rsa
275	return
276}
277
278// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
279// section 5.5.2.
280func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
281	pk.p = new(encoding.MPI)
282	if _, err = pk.p.ReadFrom(r); err != nil {
283		return
284	}
285	pk.q = new(encoding.MPI)
286	if _, err = pk.q.ReadFrom(r); err != nil {
287		return
288	}
289	pk.g = new(encoding.MPI)
290	if _, err = pk.g.ReadFrom(r); err != nil {
291		return
292	}
293	pk.y = new(encoding.MPI)
294	if _, err = pk.y.ReadFrom(r); err != nil {
295		return
296	}
297
298	dsa := new(dsa.PublicKey)
299	dsa.P = new(big.Int).SetBytes(pk.p.Bytes())
300	dsa.Q = new(big.Int).SetBytes(pk.q.Bytes())
301	dsa.G = new(big.Int).SetBytes(pk.g.Bytes())
302	dsa.Y = new(big.Int).SetBytes(pk.y.Bytes())
303	pk.PublicKey = dsa
304	return
305}
306
307// parseElGamal parses ElGamal public key material from the given Reader. See
308// RFC 4880, section 5.5.2.
309func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
310	pk.p = new(encoding.MPI)
311	if _, err = pk.p.ReadFrom(r); err != nil {
312		return
313	}
314	pk.g = new(encoding.MPI)
315	if _, err = pk.g.ReadFrom(r); err != nil {
316		return
317	}
318	pk.y = new(encoding.MPI)
319	if _, err = pk.y.ReadFrom(r); err != nil {
320		return
321	}
322
323	elgamal := new(elgamal.PublicKey)
324	elgamal.P = new(big.Int).SetBytes(pk.p.Bytes())
325	elgamal.G = new(big.Int).SetBytes(pk.g.Bytes())
326	elgamal.Y = new(big.Int).SetBytes(pk.y.Bytes())
327	pk.PublicKey = elgamal
328	return
329}
330
331// parseECDSA parses ECDSA public key material from the given Reader. See
332// RFC 6637, Section 9.
333func (pk *PublicKey) parseECDSA(r io.Reader) (err error) {
334	pk.oid = new(encoding.OID)
335	if _, err = pk.oid.ReadFrom(r); err != nil {
336		return
337	}
338	pk.p = new(encoding.MPI)
339	if _, err = pk.p.ReadFrom(r); err != nil {
340		return
341	}
342
343	var c elliptic.Curve
344	curveInfo := ecc.FindByOid(pk.oid)
345	if curveInfo == nil || curveInfo.SigAlgorithm != ecc.ECDSA {
346		return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
347	}
348	c = curveInfo.Curve
349	x, y := elliptic.Unmarshal(c, pk.p.Bytes())
350	if x == nil {
351		return errors.UnsupportedError("failed to parse EC point")
352	}
353	pk.PublicKey = &ecdsa.PublicKey{Curve: c, X: x, Y: y}
354	return
355}
356
357// parseECDH parses ECDH public key material from the given Reader. See
358// RFC 6637, Section 9.
359func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
360	pk.oid = new(encoding.OID)
361	if _, err = pk.oid.ReadFrom(r); err != nil {
362		return
363	}
364	pk.p = new(encoding.MPI)
365	if _, err = pk.p.ReadFrom(r); err != nil {
366		return
367	}
368	pk.kdf = new(encoding.OID)
369	if _, err = pk.kdf.ReadFrom(r); err != nil {
370		return
371	}
372
373	curveInfo := ecc.FindByOid(pk.oid)
374	if curveInfo == nil {
375		return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
376	}
377
378	c := curveInfo.Curve
379	cType := curveInfo.CurveType
380
381	var x, y *big.Int
382	if cType == ecc.Curve25519 {
383		x = new(big.Int)
384		x.SetBytes(pk.p.Bytes())
385	} else {
386		x, y = elliptic.Unmarshal(c, pk.p.Bytes())
387	}
388	if x == nil {
389		return errors.UnsupportedError("failed to parse EC point")
390	}
391
392	if kdfLen := len(pk.kdf.Bytes()); kdfLen < 3 {
393		return errors.UnsupportedError("unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
394	}
395	if reserved := pk.kdf.Bytes()[0]; reserved != 0x01 {
396		return errors.UnsupportedError("unsupported KDF reserved field: " + strconv.Itoa(int(reserved)))
397	}
398	kdfHash, ok := algorithm.HashById[pk.kdf.Bytes()[1]]
399	if !ok {
400		return errors.UnsupportedError("unsupported ECDH KDF hash: " + strconv.Itoa(int(pk.kdf.Bytes()[1])))
401	}
402	kdfCipher, ok := algorithm.CipherById[pk.kdf.Bytes()[2]]
403	if !ok {
404		return errors.UnsupportedError("unsupported ECDH KDF cipher: " + strconv.Itoa(int(pk.kdf.Bytes()[2])))
405	}
406
407	pk.PublicKey = &ecdh.PublicKey{
408		CurveType: cType,
409		Curve:     c,
410		X:         x,
411		Y:         y,
412		KDF: ecdh.KDF{
413			Hash:   kdfHash,
414			Cipher: kdfCipher,
415		},
416	}
417	return
418}
419
420func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
421	pk.oid = new(encoding.OID)
422	if _, err = pk.oid.ReadFrom(r); err != nil {
423		return
424	}
425	curveInfo := ecc.FindByOid(pk.oid)
426	if curveInfo == nil || curveInfo.SigAlgorithm != ecc.EdDSA {
427		return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
428	}
429	pk.p = new(encoding.MPI)
430	if _, err = pk.p.ReadFrom(r); err != nil {
431		return
432	}
433
434	eddsa := make(ed25519.PublicKey, ed25519.PublicKeySize)
435	switch flag := pk.p.Bytes()[0]; flag {
436	case 0x04:
437		// TODO: see _grcy_ecc_eddsa_ensure_compact in grcypt
438		return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
439	case 0x40:
440		copy(eddsa[:], pk.p.Bytes()[1:])
441	default:
442		return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
443	}
444
445	pk.PublicKey = &eddsa
446	return
447}
448
449// SerializeForHash serializes the PublicKey to w with the special packet
450// header format needed for hashing.
451func (pk *PublicKey) SerializeForHash(w io.Writer) error {
452	pk.SerializeSignaturePrefix(w)
453	return pk.serializeWithoutHeaders(w)
454}
455
456// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
457// The prefix is used when calculating a signature over this public key. See
458// RFC 4880, section 5.2.4.
459func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) {
460	var pLength = pk.algorithmSpecificByteCount()
461	if pk.Version == 5 {
462		pLength += 10 // version, timestamp (4), algorithm, key octet count (4).
463		w.Write([]byte{
464			0x9A,
465			byte(pLength >> 24),
466			byte(pLength >> 16),
467			byte(pLength >> 8),
468			byte(pLength),
469		})
470		return
471	}
472	pLength += 6
473	w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
474}
475
476func (pk *PublicKey) Serialize(w io.Writer) (err error) {
477	length := 6 // 6 byte header
478	length += pk.algorithmSpecificByteCount()
479	if pk.Version == 5 {
480		length += 4 // octet key count
481	}
482	packetType := packetTypePublicKey
483	if pk.IsSubkey {
484		packetType = packetTypePublicSubkey
485	}
486	err = serializeHeader(w, packetType, length)
487	if err != nil {
488		return
489	}
490	return pk.serializeWithoutHeaders(w)
491}
492
493func (pk *PublicKey) algorithmSpecificByteCount() int {
494	length := 0
495	switch pk.PubKeyAlgo {
496	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
497		length += int(pk.n.EncodedLength())
498		length += int(pk.e.EncodedLength())
499	case PubKeyAlgoDSA:
500		length += int(pk.p.EncodedLength())
501		length += int(pk.q.EncodedLength())
502		length += int(pk.g.EncodedLength())
503		length += int(pk.y.EncodedLength())
504	case PubKeyAlgoElGamal:
505		length += int(pk.p.EncodedLength())
506		length += int(pk.g.EncodedLength())
507		length += int(pk.y.EncodedLength())
508	case PubKeyAlgoECDSA:
509		length += int(pk.oid.EncodedLength())
510		length += int(pk.p.EncodedLength())
511	case PubKeyAlgoECDH:
512		length += int(pk.oid.EncodedLength())
513		length += int(pk.p.EncodedLength())
514		length += int(pk.kdf.EncodedLength())
515	case PubKeyAlgoEdDSA:
516		length += int(pk.oid.EncodedLength())
517		length += int(pk.p.EncodedLength())
518	default:
519		panic("unknown public key algorithm")
520	}
521	return length
522}
523
524// serializeWithoutHeaders marshals the PublicKey to w in the form of an
525// OpenPGP public key packet, not including the packet header.
526func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
527	t := uint32(pk.CreationTime.Unix())
528	if _, err = w.Write([]byte{
529		byte(pk.Version),
530		byte(t >> 24), byte(t >> 16), byte(t >> 8), byte(t),
531		byte(pk.PubKeyAlgo),
532	}); err != nil {
533		return
534	}
535
536	if pk.Version == 5 {
537		n := pk.algorithmSpecificByteCount()
538		if _, err = w.Write([]byte{
539			byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
540		}); err != nil {
541			return
542		}
543	}
544
545	switch pk.PubKeyAlgo {
546	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
547		if _, err = w.Write(pk.n.EncodedBytes()); err != nil {
548			return
549		}
550		_, err = w.Write(pk.e.EncodedBytes())
551		return
552	case PubKeyAlgoDSA:
553		if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
554			return
555		}
556		if _, err = w.Write(pk.q.EncodedBytes()); err != nil {
557			return
558		}
559		if _, err = w.Write(pk.g.EncodedBytes()); err != nil {
560			return
561		}
562		_, err = w.Write(pk.y.EncodedBytes())
563		return
564	case PubKeyAlgoElGamal:
565		if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
566			return
567		}
568		if _, err = w.Write(pk.g.EncodedBytes()); err != nil {
569			return
570		}
571		_, err = w.Write(pk.y.EncodedBytes())
572		return
573	case PubKeyAlgoECDSA:
574		if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
575			return
576		}
577		_, err = w.Write(pk.p.EncodedBytes())
578		return
579	case PubKeyAlgoECDH:
580		if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
581			return
582		}
583		if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
584			return
585		}
586		_, err = w.Write(pk.kdf.EncodedBytes())
587		return
588	case PubKeyAlgoEdDSA:
589		if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
590			return
591		}
592		_, err = w.Write(pk.p.EncodedBytes())
593		return
594	}
595	return errors.InvalidArgumentError("bad public-key algorithm")
596}
597
598// CanSign returns true iff this public key can generate signatures
599func (pk *PublicKey) CanSign() bool {
600	return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal && pk.PubKeyAlgo != PubKeyAlgoECDH
601}
602
603// VerifySignature returns nil iff sig is a valid signature, made by this
604// public key, of the data hashed into signed. signed is mutated by this call.
605func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
606	if !pk.CanSign() {
607		return errors.InvalidArgumentError("public key cannot generate signatures")
608	}
609	if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
610		sig.AddMetadataToHashSuffix()
611	}
612	signed.Write(sig.HashSuffix)
613	hashBytes := signed.Sum(nil)
614	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
615		return errors.SignatureError("hash tag doesn't match")
616	}
617
618	if pk.PubKeyAlgo != sig.PubKeyAlgo {
619		return errors.InvalidArgumentError("public key and signature use different algorithms")
620	}
621
622	switch pk.PubKeyAlgo {
623	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
624		rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
625		err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.Bytes()))
626		if err != nil {
627			return errors.SignatureError("RSA verification failure")
628		}
629		return nil
630	case PubKeyAlgoDSA:
631		dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
632		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
633		subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
634		if len(hashBytes) > subgroupSize {
635			hashBytes = hashBytes[:subgroupSize]
636		}
637		if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.Bytes()), new(big.Int).SetBytes(sig.DSASigS.Bytes())) {
638			return errors.SignatureError("DSA verification failure")
639		}
640		return nil
641	case PubKeyAlgoECDSA:
642		ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
643		if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.Bytes()), new(big.Int).SetBytes(sig.ECDSASigS.Bytes())) {
644			return errors.SignatureError("ECDSA verification failure")
645		}
646		return nil
647	case PubKeyAlgoEdDSA:
648		eddsaPublicKey := pk.PublicKey.(*ed25519.PublicKey)
649
650		sigR := sig.EdDSASigR.Bytes()
651		sigS := sig.EdDSASigS.Bytes()
652
653		eddsaSig := make([]byte, ed25519.SignatureSize)
654		copy(eddsaSig[32-len(sigR):32], sigR)
655		copy(eddsaSig[64-len(sigS):], sigS)
656
657		if !ed25519.Verify(*eddsaPublicKey, hashBytes, eddsaSig) {
658			return errors.SignatureError("EdDSA verification failure")
659		}
660		return nil
661	default:
662		return errors.SignatureError("Unsupported public key algorithm used in signature")
663	}
664}
665
666// keySignatureHash returns a Hash of the message that needs to be signed for
667// pk to assert a subkey relationship to signed.
668func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
669	if !hashFunc.Available() {
670		return nil, errors.UnsupportedError("hash function")
671	}
672	h = hashFunc.New()
673
674	// RFC 4880, section 5.2.4
675	err = pk.SerializeForHash(h)
676	if err != nil {
677		return nil, err
678	}
679
680	err = signed.SerializeForHash(h)
681	return
682}
683
684// VerifyKeySignature returns nil iff sig is a valid signature, made by this
685// public key, of signed.
686func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
687	h, err := keySignatureHash(pk, signed, sig.Hash)
688	if err != nil {
689		return err
690	}
691	if err = pk.VerifySignature(h, sig); err != nil {
692		return err
693	}
694
695	if sig.FlagSign {
696		// Signing subkeys must be cross-signed. See
697		// https://www.gnupg.org/faq/subkey-cross-certify.html.
698		if sig.EmbeddedSignature == nil {
699			return errors.StructuralError("signing subkey is missing cross-signature")
700		}
701		// Verify the cross-signature. This is calculated over the same
702		// data as the main signature, so we cannot just recursively
703		// call signed.VerifyKeySignature(...)
704		if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil {
705			return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
706		}
707		if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
708			return errors.StructuralError("error while verifying cross-signature: " + err.Error())
709		}
710	}
711
712	return nil
713}
714
715func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
716	if !hashFunc.Available() {
717		return nil, errors.UnsupportedError("hash function")
718	}
719	h = hashFunc.New()
720
721	// RFC 4880, section 5.2.4
722	err = pk.SerializeForHash(h)
723
724	return
725}
726
727// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
728// public key.
729func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
730	h, err := keyRevocationHash(pk, sig.Hash)
731	if err != nil {
732		return err
733	}
734	return pk.VerifySignature(h, sig)
735}
736
737// VerifySubkeyRevocationSignature returns nil iff sig is a valid subkey revocation signature,
738// made by the passed in signingKey.
739func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signingKey *PublicKey) (err error) {
740	h, err := keyRevocationHash(pk, sig.Hash)
741	if err != nil {
742		return err
743	}
744	return signingKey.VerifySignature(h, sig)
745}
746
747// userIdSignatureHash returns a Hash of the message that needs to be signed
748// to assert that pk is a valid key for id.
749func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
750	if !hashFunc.Available() {
751		return nil, errors.UnsupportedError("hash function")
752	}
753	h = hashFunc.New()
754
755	// RFC 4880, section 5.2.4
756	pk.SerializeSignaturePrefix(h)
757	pk.serializeWithoutHeaders(h)
758
759	var buf [5]byte
760	buf[0] = 0xb4
761	buf[1] = byte(len(id) >> 24)
762	buf[2] = byte(len(id) >> 16)
763	buf[3] = byte(len(id) >> 8)
764	buf[4] = byte(len(id))
765	h.Write(buf[:])
766	h.Write([]byte(id))
767
768	return
769}
770
771// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
772// public key, that id is the identity of pub.
773func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
774	h, err := userIdSignatureHash(id, pub, sig.Hash)
775	if err != nil {
776		return err
777	}
778	return pk.VerifySignature(h, sig)
779}
780
781// KeyIdString returns the public key's fingerprint in capital hex
782// (e.g. "6C7EE1B8621CC013").
783func (pk *PublicKey) KeyIdString() string {
784	return fmt.Sprintf("%X", pk.Fingerprint[12:20])
785}
786
787// KeyIdShortString returns the short form of public key's fingerprint
788// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
789func (pk *PublicKey) KeyIdShortString() string {
790	return fmt.Sprintf("%X", pk.Fingerprint[16:20])
791}
792
793// BitLength returns the bit length for the given public key.
794func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
795	switch pk.PubKeyAlgo {
796	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
797		bitLength = pk.n.BitLength()
798	case PubKeyAlgoDSA:
799		bitLength = pk.p.BitLength()
800	case PubKeyAlgoElGamal:
801		bitLength = pk.p.BitLength()
802	case PubKeyAlgoECDSA:
803		bitLength = pk.p.BitLength()
804	case PubKeyAlgoECDH:
805		bitLength = pk.p.BitLength()
806	case PubKeyAlgoEdDSA:
807		bitLength = pk.p.BitLength()
808	default:
809		err = errors.InvalidArgumentError("bad public-key algorithm")
810	}
811	return
812}
813
814// KeyExpired returns whether sig is a self-signature of a key that has
815// expired or is created in the future.
816func (pk *PublicKey) KeyExpired(sig *Signature, currentTime time.Time) bool {
817	if pk.CreationTime.After(currentTime) {
818		return true
819	}
820	if sig.KeyLifetimeSecs == nil || *sig.KeyLifetimeSecs == 0 {
821		return false
822	}
823	expiry := pk.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
824	return currentTime.After(expiry)
825}
826