main
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/dsa"
9 "crypto/rsa"
10 "crypto/sha1"
11 "crypto/sha256"
12 _ "crypto/sha512"
13 "encoding/binary"
14 "fmt"
15 "hash"
16 "io"
17 "math/big"
18 "strconv"
19 "time"
20
21 "github.com/ProtonMail/go-crypto/openpgp/ecdh"
22 "github.com/ProtonMail/go-crypto/openpgp/ecdsa"
23 "github.com/ProtonMail/go-crypto/openpgp/ed25519"
24 "github.com/ProtonMail/go-crypto/openpgp/ed448"
25 "github.com/ProtonMail/go-crypto/openpgp/eddsa"
26 "github.com/ProtonMail/go-crypto/openpgp/elgamal"
27 "github.com/ProtonMail/go-crypto/openpgp/errors"
28 "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
29 "github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
30 "github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
31 "github.com/ProtonMail/go-crypto/openpgp/x25519"
32 "github.com/ProtonMail/go-crypto/openpgp/x448"
33)
34
35// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
36type PublicKey struct {
37 Version int
38 CreationTime time.Time
39 PubKeyAlgo PublicKeyAlgorithm
40 PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey, *x25519.PublicKey, *x448.PublicKey, *ed25519.PublicKey, *ed448.PublicKey
41 Fingerprint []byte
42 KeyId uint64
43 IsSubkey bool
44
45 // RFC 4880 fields
46 n, e, p, q, g, y encoding.Field
47
48 // RFC 6637 fields
49 // oid contains the OID byte sequence identifying the elliptic curve used
50 oid encoding.Field
51
52 // kdf stores key derivation function parameters
53 // used for ECDH encryption. See RFC 6637, Section 9.
54 kdf encoding.Field
55}
56
57// UpgradeToV5 updates the version of the key to v5, and updates all necessary
58// fields.
59func (pk *PublicKey) UpgradeToV5() {
60 pk.Version = 5
61 pk.setFingerprintAndKeyId()
62}
63
64// UpgradeToV6 updates the version of the key to v6, and updates all necessary
65// fields.
66func (pk *PublicKey) UpgradeToV6() error {
67 pk.Version = 6
68 pk.setFingerprintAndKeyId()
69 return pk.checkV6Compatibility()
70}
71
72// signingKey provides a convenient abstraction over signature verification
73// for v3 and v4 public keys.
74type signingKey interface {
75 SerializeForHash(io.Writer) error
76 SerializeSignaturePrefix(io.Writer) error
77 serializeWithoutHeaders(io.Writer) error
78}
79
80// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
81func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
82 pk := &PublicKey{
83 Version: 4,
84 CreationTime: creationTime,
85 PubKeyAlgo: PubKeyAlgoRSA,
86 PublicKey: pub,
87 n: new(encoding.MPI).SetBig(pub.N),
88 e: new(encoding.MPI).SetBig(big.NewInt(int64(pub.E))),
89 }
90
91 pk.setFingerprintAndKeyId()
92 return pk
93}
94
95// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey.
96func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
97 pk := &PublicKey{
98 Version: 4,
99 CreationTime: creationTime,
100 PubKeyAlgo: PubKeyAlgoDSA,
101 PublicKey: pub,
102 p: new(encoding.MPI).SetBig(pub.P),
103 q: new(encoding.MPI).SetBig(pub.Q),
104 g: new(encoding.MPI).SetBig(pub.G),
105 y: new(encoding.MPI).SetBig(pub.Y),
106 }
107
108 pk.setFingerprintAndKeyId()
109 return pk
110}
111
112// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
113func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
114 pk := &PublicKey{
115 Version: 4,
116 CreationTime: creationTime,
117 PubKeyAlgo: PubKeyAlgoElGamal,
118 PublicKey: pub,
119 p: new(encoding.MPI).SetBig(pub.P),
120 g: new(encoding.MPI).SetBig(pub.G),
121 y: new(encoding.MPI).SetBig(pub.Y),
122 }
123
124 pk.setFingerprintAndKeyId()
125 return pk
126}
127
128func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
129 pk := &PublicKey{
130 Version: 4,
131 CreationTime: creationTime,
132 PubKeyAlgo: PubKeyAlgoECDSA,
133 PublicKey: pub,
134 p: encoding.NewMPI(pub.MarshalPoint()),
135 }
136
137 curveInfo := ecc.FindByCurve(pub.GetCurve())
138 if curveInfo == nil {
139 panic("unknown elliptic curve")
140 }
141 pk.oid = curveInfo.Oid
142 pk.setFingerprintAndKeyId()
143 return pk
144}
145
146func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey {
147 var pk *PublicKey
148 var kdf = encoding.NewOID([]byte{0x1, pub.Hash.Id(), pub.Cipher.Id()})
149 pk = &PublicKey{
150 Version: 4,
151 CreationTime: creationTime,
152 PubKeyAlgo: PubKeyAlgoECDH,
153 PublicKey: pub,
154 p: encoding.NewMPI(pub.MarshalPoint()),
155 kdf: kdf,
156 }
157
158 curveInfo := ecc.FindByCurve(pub.GetCurve())
159
160 if curveInfo == nil {
161 panic("unknown elliptic curve")
162 }
163
164 pk.oid = curveInfo.Oid
165 pk.setFingerprintAndKeyId()
166 return pk
167}
168
169func NewEdDSAPublicKey(creationTime time.Time, pub *eddsa.PublicKey) *PublicKey {
170 curveInfo := ecc.FindByCurve(pub.GetCurve())
171 pk := &PublicKey{
172 Version: 4,
173 CreationTime: creationTime,
174 PubKeyAlgo: PubKeyAlgoEdDSA,
175 PublicKey: pub,
176 oid: curveInfo.Oid,
177 // Native point format, see draft-koch-eddsa-for-openpgp-04, Appendix B
178 p: encoding.NewMPI(pub.MarshalPoint()),
179 }
180
181 pk.setFingerprintAndKeyId()
182 return pk
183}
184
185func NewX25519PublicKey(creationTime time.Time, pub *x25519.PublicKey) *PublicKey {
186 pk := &PublicKey{
187 Version: 4,
188 CreationTime: creationTime,
189 PubKeyAlgo: PubKeyAlgoX25519,
190 PublicKey: pub,
191 }
192
193 pk.setFingerprintAndKeyId()
194 return pk
195}
196
197func NewX448PublicKey(creationTime time.Time, pub *x448.PublicKey) *PublicKey {
198 pk := &PublicKey{
199 Version: 4,
200 CreationTime: creationTime,
201 PubKeyAlgo: PubKeyAlgoX448,
202 PublicKey: pub,
203 }
204
205 pk.setFingerprintAndKeyId()
206 return pk
207}
208
209func NewEd25519PublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey {
210 pk := &PublicKey{
211 Version: 4,
212 CreationTime: creationTime,
213 PubKeyAlgo: PubKeyAlgoEd25519,
214 PublicKey: pub,
215 }
216
217 pk.setFingerprintAndKeyId()
218 return pk
219}
220
221func NewEd448PublicKey(creationTime time.Time, pub *ed448.PublicKey) *PublicKey {
222 pk := &PublicKey{
223 Version: 4,
224 CreationTime: creationTime,
225 PubKeyAlgo: PubKeyAlgoEd448,
226 PublicKey: pub,
227 }
228
229 pk.setFingerprintAndKeyId()
230 return pk
231}
232
233func (pk *PublicKey) parse(r io.Reader) (err error) {
234 // RFC 4880, section 5.5.2
235 var buf [6]byte
236 _, err = readFull(r, buf[:])
237 if err != nil {
238 return
239 }
240
241 pk.Version = int(buf[0])
242 if pk.Version != 4 && pk.Version != 5 && pk.Version != 6 {
243 return errors.UnsupportedError("public key version " + strconv.Itoa(int(buf[0])))
244 }
245
246 if V5Disabled && pk.Version == 5 {
247 return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
248 }
249
250 if pk.Version >= 5 {
251 // Read the four-octet scalar octet count
252 // The count is not used in this implementation
253 var n [4]byte
254 _, err = readFull(r, n[:])
255 if err != nil {
256 return
257 }
258 }
259 pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
260 pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
261 // Ignore four-ocet length
262 switch pk.PubKeyAlgo {
263 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
264 err = pk.parseRSA(r)
265 case PubKeyAlgoDSA:
266 err = pk.parseDSA(r)
267 case PubKeyAlgoElGamal:
268 err = pk.parseElGamal(r)
269 case PubKeyAlgoECDSA:
270 err = pk.parseECDSA(r)
271 case PubKeyAlgoECDH:
272 err = pk.parseECDH(r)
273 case PubKeyAlgoEdDSA:
274 err = pk.parseEdDSA(r)
275 case PubKeyAlgoX25519:
276 err = pk.parseX25519(r)
277 case PubKeyAlgoX448:
278 err = pk.parseX448(r)
279 case PubKeyAlgoEd25519:
280 err = pk.parseEd25519(r)
281 case PubKeyAlgoEd448:
282 err = pk.parseEd448(r)
283 default:
284 err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
285 }
286 if err != nil {
287 return
288 }
289
290 pk.setFingerprintAndKeyId()
291 return
292}
293
294func (pk *PublicKey) setFingerprintAndKeyId() {
295 // RFC 4880, section 12.2
296 if pk.Version >= 5 {
297 fingerprint := sha256.New()
298 if err := pk.SerializeForHash(fingerprint); err != nil {
299 // Should not happen for a hash.
300 panic(err)
301 }
302 pk.Fingerprint = make([]byte, 32)
303 copy(pk.Fingerprint, fingerprint.Sum(nil))
304 pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[:8])
305 } else {
306 fingerprint := sha1.New()
307 if err := pk.SerializeForHash(fingerprint); err != nil {
308 // Should not happen for a hash.
309 panic(err)
310 }
311 pk.Fingerprint = make([]byte, 20)
312 copy(pk.Fingerprint, fingerprint.Sum(nil))
313 pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
314 }
315}
316
317func (pk *PublicKey) checkV6Compatibility() error {
318 // Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
319 switch pk.PubKeyAlgo {
320 case PubKeyAlgoECDH:
321 curveInfo := ecc.FindByOid(pk.oid)
322 if curveInfo == nil {
323 return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
324 }
325 if curveInfo.GenName == ecc.Curve25519GenName {
326 return errors.StructuralError("cannot generate v6 key with deprecated OID: Curve25519Legacy")
327 }
328 case PubKeyAlgoEdDSA:
329 return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy")
330 }
331 return nil
332}
333
334// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
335// section 5.5.2.
336func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
337 pk.n = new(encoding.MPI)
338 if _, err = pk.n.ReadFrom(r); err != nil {
339 return
340 }
341 pk.e = new(encoding.MPI)
342 if _, err = pk.e.ReadFrom(r); err != nil {
343 return
344 }
345
346 if len(pk.e.Bytes()) > 3 {
347 err = errors.UnsupportedError("large public exponent")
348 return
349 }
350 rsa := &rsa.PublicKey{
351 N: new(big.Int).SetBytes(pk.n.Bytes()),
352 E: 0,
353 }
354 for i := 0; i < len(pk.e.Bytes()); i++ {
355 rsa.E <<= 8
356 rsa.E |= int(pk.e.Bytes()[i])
357 }
358 pk.PublicKey = rsa
359 return
360}
361
362// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
363// section 5.5.2.
364func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
365 pk.p = new(encoding.MPI)
366 if _, err = pk.p.ReadFrom(r); err != nil {
367 return
368 }
369 pk.q = new(encoding.MPI)
370 if _, err = pk.q.ReadFrom(r); err != nil {
371 return
372 }
373 pk.g = new(encoding.MPI)
374 if _, err = pk.g.ReadFrom(r); err != nil {
375 return
376 }
377 pk.y = new(encoding.MPI)
378 if _, err = pk.y.ReadFrom(r); err != nil {
379 return
380 }
381
382 dsa := new(dsa.PublicKey)
383 dsa.P = new(big.Int).SetBytes(pk.p.Bytes())
384 dsa.Q = new(big.Int).SetBytes(pk.q.Bytes())
385 dsa.G = new(big.Int).SetBytes(pk.g.Bytes())
386 dsa.Y = new(big.Int).SetBytes(pk.y.Bytes())
387 pk.PublicKey = dsa
388 return
389}
390
391// parseElGamal parses ElGamal public key material from the given Reader. See
392// RFC 4880, section 5.5.2.
393func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
394 pk.p = new(encoding.MPI)
395 if _, err = pk.p.ReadFrom(r); err != nil {
396 return
397 }
398 pk.g = new(encoding.MPI)
399 if _, err = pk.g.ReadFrom(r); err != nil {
400 return
401 }
402 pk.y = new(encoding.MPI)
403 if _, err = pk.y.ReadFrom(r); err != nil {
404 return
405 }
406
407 elgamal := new(elgamal.PublicKey)
408 elgamal.P = new(big.Int).SetBytes(pk.p.Bytes())
409 elgamal.G = new(big.Int).SetBytes(pk.g.Bytes())
410 elgamal.Y = new(big.Int).SetBytes(pk.y.Bytes())
411 pk.PublicKey = elgamal
412 return
413}
414
415// parseECDSA parses ECDSA public key material from the given Reader. See
416// RFC 6637, Section 9.
417func (pk *PublicKey) parseECDSA(r io.Reader) (err error) {
418 pk.oid = new(encoding.OID)
419 if _, err = pk.oid.ReadFrom(r); err != nil {
420 return
421 }
422
423 curveInfo := ecc.FindByOid(pk.oid)
424 if curveInfo == nil {
425 return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
426 }
427
428 pk.p = new(encoding.MPI)
429 if _, err = pk.p.ReadFrom(r); err != nil {
430 return
431 }
432
433 c, ok := curveInfo.Curve.(ecc.ECDSACurve)
434 if !ok {
435 return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
436 }
437
438 ecdsaKey := ecdsa.NewPublicKey(c)
439 err = ecdsaKey.UnmarshalPoint(pk.p.Bytes())
440 pk.PublicKey = ecdsaKey
441
442 return
443}
444
445// parseECDH parses ECDH public key material from the given Reader. See
446// RFC 6637, Section 9.
447func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
448 pk.oid = new(encoding.OID)
449 if _, err = pk.oid.ReadFrom(r); err != nil {
450 return
451 }
452
453 curveInfo := ecc.FindByOid(pk.oid)
454 if curveInfo == nil {
455 return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
456 }
457
458 if pk.Version == 6 && curveInfo.GenName == ecc.Curve25519GenName {
459 // Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
460 return errors.StructuralError("cannot read v6 key with deprecated OID: Curve25519Legacy")
461 }
462
463 pk.p = new(encoding.MPI)
464 if _, err = pk.p.ReadFrom(r); err != nil {
465 return
466 }
467 pk.kdf = new(encoding.OID)
468 if _, err = pk.kdf.ReadFrom(r); err != nil {
469 return
470 }
471
472 c, ok := curveInfo.Curve.(ecc.ECDHCurve)
473 if !ok {
474 return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
475 }
476
477 if kdfLen := len(pk.kdf.Bytes()); kdfLen < 3 {
478 return errors.UnsupportedError("unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
479 }
480 if reserved := pk.kdf.Bytes()[0]; reserved != 0x01 {
481 return errors.UnsupportedError("unsupported KDF reserved field: " + strconv.Itoa(int(reserved)))
482 }
483 kdfHash, ok := algorithm.HashById[pk.kdf.Bytes()[1]]
484 if !ok {
485 return errors.UnsupportedError("unsupported ECDH KDF hash: " + strconv.Itoa(int(pk.kdf.Bytes()[1])))
486 }
487 kdfCipher, ok := algorithm.CipherById[pk.kdf.Bytes()[2]]
488 if !ok {
489 return errors.UnsupportedError("unsupported ECDH KDF cipher: " + strconv.Itoa(int(pk.kdf.Bytes()[2])))
490 }
491
492 ecdhKey := ecdh.NewPublicKey(c, kdfHash, kdfCipher)
493 err = ecdhKey.UnmarshalPoint(pk.p.Bytes())
494 pk.PublicKey = ecdhKey
495
496 return
497}
498
499func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
500 if pk.Version == 6 {
501 // Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
502 return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy")
503 }
504
505 pk.oid = new(encoding.OID)
506 if _, err = pk.oid.ReadFrom(r); err != nil {
507 return
508 }
509
510 curveInfo := ecc.FindByOid(pk.oid)
511 if curveInfo == nil {
512 return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
513 }
514
515 c, ok := curveInfo.Curve.(ecc.EdDSACurve)
516 if !ok {
517 return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
518 }
519
520 pk.p = new(encoding.MPI)
521 if _, err = pk.p.ReadFrom(r); err != nil {
522 return
523 }
524
525 if len(pk.p.Bytes()) == 0 {
526 return errors.StructuralError("empty EdDSA public key")
527 }
528
529 pub := eddsa.NewPublicKey(c)
530
531 switch flag := pk.p.Bytes()[0]; flag {
532 case 0x04:
533 // TODO: see _grcy_ecc_eddsa_ensure_compact in grcypt
534 return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
535 case 0x40:
536 err = pub.UnmarshalPoint(pk.p.Bytes())
537 default:
538 return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
539 }
540
541 pk.PublicKey = pub
542 return
543}
544
545func (pk *PublicKey) parseX25519(r io.Reader) (err error) {
546 point := make([]byte, x25519.KeySize)
547 _, err = io.ReadFull(r, point)
548 if err != nil {
549 return
550 }
551 pub := &x25519.PublicKey{
552 Point: point,
553 }
554 pk.PublicKey = pub
555 return
556}
557
558func (pk *PublicKey) parseX448(r io.Reader) (err error) {
559 point := make([]byte, x448.KeySize)
560 _, err = io.ReadFull(r, point)
561 if err != nil {
562 return
563 }
564 pub := &x448.PublicKey{
565 Point: point,
566 }
567 pk.PublicKey = pub
568 return
569}
570
571func (pk *PublicKey) parseEd25519(r io.Reader) (err error) {
572 point := make([]byte, ed25519.PublicKeySize)
573 _, err = io.ReadFull(r, point)
574 if err != nil {
575 return
576 }
577 pub := &ed25519.PublicKey{
578 Point: point,
579 }
580 pk.PublicKey = pub
581 return
582}
583
584func (pk *PublicKey) parseEd448(r io.Reader) (err error) {
585 point := make([]byte, ed448.PublicKeySize)
586 _, err = io.ReadFull(r, point)
587 if err != nil {
588 return
589 }
590 pub := &ed448.PublicKey{
591 Point: point,
592 }
593 pk.PublicKey = pub
594 return
595}
596
597// SerializeForHash serializes the PublicKey to w with the special packet
598// header format needed for hashing.
599func (pk *PublicKey) SerializeForHash(w io.Writer) error {
600 if err := pk.SerializeSignaturePrefix(w); err != nil {
601 return err
602 }
603 return pk.serializeWithoutHeaders(w)
604}
605
606// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
607// The prefix is used when calculating a signature over this public key. See
608// RFC 4880, section 5.2.4.
609func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) error {
610 var pLength = pk.algorithmSpecificByteCount()
611 // version, timestamp, algorithm
612 pLength += versionSize + timestampSize + algorithmSize
613 if pk.Version >= 5 {
614 // key octet count (4).
615 pLength += 4
616 _, err := w.Write([]byte{
617 // When a v4 signature is made over a key, the hash data starts with the octet 0x99, followed by a two-octet length
618 // of the key, and then the body of the key packet. When a v6 signature is made over a key, the hash data starts
619 // with the salt, then octet 0x9B, followed by a four-octet length of the key, and then the body of the key packet.
620 0x95 + byte(pk.Version),
621 byte(pLength >> 24),
622 byte(pLength >> 16),
623 byte(pLength >> 8),
624 byte(pLength),
625 })
626 return err
627 }
628 if _, err := w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}); err != nil {
629 return err
630 }
631 return nil
632}
633
634func (pk *PublicKey) Serialize(w io.Writer) (err error) {
635 length := uint32(versionSize + timestampSize + algorithmSize) // 6 byte header
636 length += pk.algorithmSpecificByteCount()
637 if pk.Version >= 5 {
638 length += 4 // octet key count
639 }
640 packetType := packetTypePublicKey
641 if pk.IsSubkey {
642 packetType = packetTypePublicSubkey
643 }
644 err = serializeHeader(w, packetType, int(length))
645 if err != nil {
646 return
647 }
648 return pk.serializeWithoutHeaders(w)
649}
650
651func (pk *PublicKey) algorithmSpecificByteCount() uint32 {
652 length := uint32(0)
653 switch pk.PubKeyAlgo {
654 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
655 length += uint32(pk.n.EncodedLength())
656 length += uint32(pk.e.EncodedLength())
657 case PubKeyAlgoDSA:
658 length += uint32(pk.p.EncodedLength())
659 length += uint32(pk.q.EncodedLength())
660 length += uint32(pk.g.EncodedLength())
661 length += uint32(pk.y.EncodedLength())
662 case PubKeyAlgoElGamal:
663 length += uint32(pk.p.EncodedLength())
664 length += uint32(pk.g.EncodedLength())
665 length += uint32(pk.y.EncodedLength())
666 case PubKeyAlgoECDSA:
667 length += uint32(pk.oid.EncodedLength())
668 length += uint32(pk.p.EncodedLength())
669 case PubKeyAlgoECDH:
670 length += uint32(pk.oid.EncodedLength())
671 length += uint32(pk.p.EncodedLength())
672 length += uint32(pk.kdf.EncodedLength())
673 case PubKeyAlgoEdDSA:
674 length += uint32(pk.oid.EncodedLength())
675 length += uint32(pk.p.EncodedLength())
676 case PubKeyAlgoX25519:
677 length += x25519.KeySize
678 case PubKeyAlgoX448:
679 length += x448.KeySize
680 case PubKeyAlgoEd25519:
681 length += ed25519.PublicKeySize
682 case PubKeyAlgoEd448:
683 length += ed448.PublicKeySize
684 default:
685 panic("unknown public key algorithm")
686 }
687 return length
688}
689
690// serializeWithoutHeaders marshals the PublicKey to w in the form of an
691// OpenPGP public key packet, not including the packet header.
692func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
693 t := uint32(pk.CreationTime.Unix())
694 if _, err = w.Write([]byte{
695 byte(pk.Version),
696 byte(t >> 24), byte(t >> 16), byte(t >> 8), byte(t),
697 byte(pk.PubKeyAlgo),
698 }); err != nil {
699 return
700 }
701
702 if pk.Version >= 5 {
703 n := pk.algorithmSpecificByteCount()
704 if _, err = w.Write([]byte{
705 byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
706 }); err != nil {
707 return
708 }
709 }
710
711 switch pk.PubKeyAlgo {
712 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
713 if _, err = w.Write(pk.n.EncodedBytes()); err != nil {
714 return
715 }
716 _, err = w.Write(pk.e.EncodedBytes())
717 return
718 case PubKeyAlgoDSA:
719 if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
720 return
721 }
722 if _, err = w.Write(pk.q.EncodedBytes()); err != nil {
723 return
724 }
725 if _, err = w.Write(pk.g.EncodedBytes()); err != nil {
726 return
727 }
728 _, err = w.Write(pk.y.EncodedBytes())
729 return
730 case PubKeyAlgoElGamal:
731 if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
732 return
733 }
734 if _, err = w.Write(pk.g.EncodedBytes()); err != nil {
735 return
736 }
737 _, err = w.Write(pk.y.EncodedBytes())
738 return
739 case PubKeyAlgoECDSA:
740 if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
741 return
742 }
743 _, err = w.Write(pk.p.EncodedBytes())
744 return
745 case PubKeyAlgoECDH:
746 if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
747 return
748 }
749 if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
750 return
751 }
752 _, err = w.Write(pk.kdf.EncodedBytes())
753 return
754 case PubKeyAlgoEdDSA:
755 if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
756 return
757 }
758 _, err = w.Write(pk.p.EncodedBytes())
759 return
760 case PubKeyAlgoX25519:
761 publicKey := pk.PublicKey.(*x25519.PublicKey)
762 _, err = w.Write(publicKey.Point)
763 return
764 case PubKeyAlgoX448:
765 publicKey := pk.PublicKey.(*x448.PublicKey)
766 _, err = w.Write(publicKey.Point)
767 return
768 case PubKeyAlgoEd25519:
769 publicKey := pk.PublicKey.(*ed25519.PublicKey)
770 _, err = w.Write(publicKey.Point)
771 return
772 case PubKeyAlgoEd448:
773 publicKey := pk.PublicKey.(*ed448.PublicKey)
774 _, err = w.Write(publicKey.Point)
775 return
776 }
777 return errors.InvalidArgumentError("bad public-key algorithm")
778}
779
780// CanSign returns true iff this public key can generate signatures
781func (pk *PublicKey) CanSign() bool {
782 return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal && pk.PubKeyAlgo != PubKeyAlgoECDH
783}
784
785// VerifyHashTag returns nil iff sig appears to be a plausible signature of the data
786// hashed into signed, based solely on its HashTag. signed is mutated by this call.
787func VerifyHashTag(signed hash.Hash, sig *Signature) (err error) {
788 if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
789 sig.AddMetadataToHashSuffix()
790 }
791 signed.Write(sig.HashSuffix)
792 hashBytes := signed.Sum(nil)
793 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
794 return errors.SignatureError("hash tag doesn't match")
795 }
796 return nil
797}
798
799// VerifySignature returns nil iff sig is a valid signature, made by this
800// public key, of the data hashed into signed. signed is mutated by this call.
801func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
802 if !pk.CanSign() {
803 return errors.InvalidArgumentError("public key cannot generate signatures")
804 }
805 if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
806 sig.AddMetadataToHashSuffix()
807 }
808 signed.Write(sig.HashSuffix)
809 hashBytes := signed.Sum(nil)
810 // see discussion https://github.com/ProtonMail/go-crypto/issues/107
811 if sig.Version >= 5 && (hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1]) {
812 return errors.SignatureError("hash tag doesn't match")
813 }
814
815 if pk.PubKeyAlgo != sig.PubKeyAlgo {
816 return errors.InvalidArgumentError("public key and signature use different algorithms")
817 }
818
819 switch pk.PubKeyAlgo {
820 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
821 rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
822 err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.Bytes()))
823 if err != nil {
824 return errors.SignatureError("RSA verification failure")
825 }
826 return nil
827 case PubKeyAlgoDSA:
828 dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
829 // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
830 subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
831 if len(hashBytes) > subgroupSize {
832 hashBytes = hashBytes[:subgroupSize]
833 }
834 if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.Bytes()), new(big.Int).SetBytes(sig.DSASigS.Bytes())) {
835 return errors.SignatureError("DSA verification failure")
836 }
837 return nil
838 case PubKeyAlgoECDSA:
839 ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
840 if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.Bytes()), new(big.Int).SetBytes(sig.ECDSASigS.Bytes())) {
841 return errors.SignatureError("ECDSA verification failure")
842 }
843 return nil
844 case PubKeyAlgoEdDSA:
845 eddsaPublicKey := pk.PublicKey.(*eddsa.PublicKey)
846 if !eddsa.Verify(eddsaPublicKey, hashBytes, sig.EdDSASigR.Bytes(), sig.EdDSASigS.Bytes()) {
847 return errors.SignatureError("EdDSA verification failure")
848 }
849 return nil
850 case PubKeyAlgoEd25519:
851 ed25519PublicKey := pk.PublicKey.(*ed25519.PublicKey)
852 if !ed25519.Verify(ed25519PublicKey, hashBytes, sig.EdSig) {
853 return errors.SignatureError("Ed25519 verification failure")
854 }
855 return nil
856 case PubKeyAlgoEd448:
857 ed448PublicKey := pk.PublicKey.(*ed448.PublicKey)
858 if !ed448.Verify(ed448PublicKey, hashBytes, sig.EdSig) {
859 return errors.SignatureError("ed448 verification failure")
860 }
861 return nil
862 default:
863 return errors.SignatureError("Unsupported public key algorithm used in signature")
864 }
865}
866
867// keySignatureHash returns a Hash of the message that needs to be signed for
868// pk to assert a subkey relationship to signed.
869func keySignatureHash(pk, signed signingKey, hashFunc hash.Hash) (h hash.Hash, err error) {
870 h = hashFunc
871
872 // RFC 4880, section 5.2.4
873 err = pk.SerializeForHash(h)
874 if err != nil {
875 return nil, err
876 }
877
878 err = signed.SerializeForHash(h)
879 return
880}
881
882// VerifyKeyHashTag returns nil iff sig appears to be a plausible signature over this
883// primary key and subkey, based solely on its HashTag.
884func (pk *PublicKey) VerifyKeyHashTag(signed *PublicKey, sig *Signature) error {
885 preparedHash, err := sig.PrepareVerify()
886 if err != nil {
887 return err
888 }
889 h, err := keySignatureHash(pk, signed, preparedHash)
890 if err != nil {
891 return err
892 }
893 return VerifyHashTag(h, sig)
894}
895
896// VerifyKeySignature returns nil iff sig is a valid signature, made by this
897// public key, of signed.
898func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
899 preparedHash, err := sig.PrepareVerify()
900 if err != nil {
901 return err
902 }
903 h, err := keySignatureHash(pk, signed, preparedHash)
904 if err != nil {
905 return err
906 }
907 if err = pk.VerifySignature(h, sig); err != nil {
908 return err
909 }
910
911 if sig.FlagSign {
912 // Signing subkeys must be cross-signed. See
913 // https://www.gnupg.org/faq/subkey-cross-certify.html.
914 if sig.EmbeddedSignature == nil {
915 return errors.StructuralError("signing subkey is missing cross-signature")
916 }
917 preparedHashEmbedded, err := sig.EmbeddedSignature.PrepareVerify()
918 if err != nil {
919 return err
920 }
921 // Verify the cross-signature. This is calculated over the same
922 // data as the main signature, so we cannot just recursively
923 // call signed.VerifyKeySignature(...)
924 if h, err = keySignatureHash(pk, signed, preparedHashEmbedded); err != nil {
925 return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
926 }
927 if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
928 return errors.StructuralError("error while verifying cross-signature: " + err.Error())
929 }
930 }
931
932 return nil
933}
934
935func keyRevocationHash(pk signingKey, hashFunc hash.Hash) (err error) {
936 return pk.SerializeForHash(hashFunc)
937}
938
939// VerifyRevocationHashTag returns nil iff sig appears to be a plausible signature
940// over this public key, based solely on its HashTag.
941func (pk *PublicKey) VerifyRevocationHashTag(sig *Signature) (err error) {
942 preparedHash, err := sig.PrepareVerify()
943 if err != nil {
944 return err
945 }
946 if err = keyRevocationHash(pk, preparedHash); err != nil {
947 return err
948 }
949 return VerifyHashTag(preparedHash, sig)
950}
951
952// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
953// public key.
954func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
955 preparedHash, err := sig.PrepareVerify()
956 if err != nil {
957 return err
958 }
959 if err = keyRevocationHash(pk, preparedHash); err != nil {
960 return err
961 }
962 return pk.VerifySignature(preparedHash, sig)
963}
964
965// VerifySubkeyRevocationSignature returns nil iff sig is a valid subkey revocation signature,
966// made by this public key, of signed.
967func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signed *PublicKey) (err error) {
968 preparedHash, err := sig.PrepareVerify()
969 if err != nil {
970 return err
971 }
972 h, err := keySignatureHash(pk, signed, preparedHash)
973 if err != nil {
974 return err
975 }
976 return pk.VerifySignature(h, sig)
977}
978
979// userIdSignatureHash returns a Hash of the message that needs to be signed
980// to assert that pk is a valid key for id.
981func userIdSignatureHash(id string, pk *PublicKey, h hash.Hash) (err error) {
982
983 // RFC 4880, section 5.2.4
984 if err := pk.SerializeSignaturePrefix(h); err != nil {
985 return err
986 }
987 if err := pk.serializeWithoutHeaders(h); err != nil {
988 return err
989 }
990
991 var buf [5]byte
992 buf[0] = 0xb4
993 buf[1] = byte(len(id) >> 24)
994 buf[2] = byte(len(id) >> 16)
995 buf[3] = byte(len(id) >> 8)
996 buf[4] = byte(len(id))
997 h.Write(buf[:])
998 h.Write([]byte(id))
999
1000 return nil
1001}
1002
1003// directKeySignatureHash returns a Hash of the message that needs to be signed.
1004func directKeySignatureHash(pk *PublicKey, h hash.Hash) (err error) {
1005 return pk.SerializeForHash(h)
1006}
1007
1008// VerifyUserIdHashTag returns nil iff sig appears to be a plausible signature over this
1009// public key and UserId, based solely on its HashTag
1010func (pk *PublicKey) VerifyUserIdHashTag(id string, sig *Signature) (err error) {
1011 preparedHash, err := sig.PrepareVerify()
1012 if err != nil {
1013 return err
1014 }
1015 err = userIdSignatureHash(id, pk, preparedHash)
1016 if err != nil {
1017 return err
1018 }
1019 return VerifyHashTag(preparedHash, sig)
1020}
1021
1022// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
1023// public key, that id is the identity of pub.
1024func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
1025 h, err := sig.PrepareVerify()
1026 if err != nil {
1027 return err
1028 }
1029 if err := userIdSignatureHash(id, pub, h); err != nil {
1030 return err
1031 }
1032 return pk.VerifySignature(h, sig)
1033}
1034
1035// VerifyDirectKeySignature returns nil iff sig is a valid signature, made by this
1036// public key.
1037func (pk *PublicKey) VerifyDirectKeySignature(sig *Signature) (err error) {
1038 h, err := sig.PrepareVerify()
1039 if err != nil {
1040 return err
1041 }
1042 if err := directKeySignatureHash(pk, h); err != nil {
1043 return err
1044 }
1045 return pk.VerifySignature(h, sig)
1046}
1047
1048// KeyIdString returns the public key's fingerprint in capital hex
1049// (e.g. "6C7EE1B8621CC013").
1050func (pk *PublicKey) KeyIdString() string {
1051 return fmt.Sprintf("%016X", pk.KeyId)
1052}
1053
1054// KeyIdShortString returns the short form of public key's fingerprint
1055// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
1056// This function will return the full key id for v5 and v6 keys
1057// since the short key id is undefined for them.
1058func (pk *PublicKey) KeyIdShortString() string {
1059 if pk.Version >= 5 {
1060 return pk.KeyIdString()
1061 }
1062 return fmt.Sprintf("%X", pk.Fingerprint[16:20])
1063}
1064
1065// BitLength returns the bit length for the given public key.
1066func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
1067 switch pk.PubKeyAlgo {
1068 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
1069 bitLength = pk.n.BitLength()
1070 case PubKeyAlgoDSA:
1071 bitLength = pk.p.BitLength()
1072 case PubKeyAlgoElGamal:
1073 bitLength = pk.p.BitLength()
1074 case PubKeyAlgoECDSA:
1075 bitLength = pk.p.BitLength()
1076 case PubKeyAlgoECDH:
1077 bitLength = pk.p.BitLength()
1078 case PubKeyAlgoEdDSA:
1079 bitLength = pk.p.BitLength()
1080 case PubKeyAlgoX25519:
1081 bitLength = x25519.KeySize * 8
1082 case PubKeyAlgoX448:
1083 bitLength = x448.KeySize * 8
1084 case PubKeyAlgoEd25519:
1085 bitLength = ed25519.PublicKeySize * 8
1086 case PubKeyAlgoEd448:
1087 bitLength = ed448.PublicKeySize * 8
1088 default:
1089 err = errors.InvalidArgumentError("bad public-key algorithm")
1090 }
1091 return
1092}
1093
1094// Curve returns the used elliptic curve of this public key.
1095// Returns an error if no elliptic curve is used.
1096func (pk *PublicKey) Curve() (curve Curve, err error) {
1097 switch pk.PubKeyAlgo {
1098 case PubKeyAlgoECDSA, PubKeyAlgoECDH, PubKeyAlgoEdDSA:
1099 curveInfo := ecc.FindByOid(pk.oid)
1100 if curveInfo == nil {
1101 return "", errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
1102 }
1103 curve = Curve(curveInfo.GenName)
1104 case PubKeyAlgoEd25519, PubKeyAlgoX25519:
1105 curve = Curve25519
1106 case PubKeyAlgoEd448, PubKeyAlgoX448:
1107 curve = Curve448
1108 default:
1109 err = errors.InvalidArgumentError("public key does not operate with an elliptic curve")
1110 }
1111 return
1112}
1113
1114// KeyExpired returns whether sig is a self-signature of a key that has
1115// expired or is created in the future.
1116func (pk *PublicKey) KeyExpired(sig *Signature, currentTime time.Time) bool {
1117 if pk.CreationTime.Unix() > currentTime.Unix() {
1118 return true
1119 }
1120 if sig.KeyLifetimeSecs == nil || *sig.KeyLifetimeSecs == 0 {
1121 return false
1122 }
1123 expiry := pk.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
1124 return currentTime.Unix() > expiry.Unix()
1125}