main
Raw Download raw file
   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}