...

Source file src/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go

Documentation: github.com/ProtonMail/go-crypto/openpgp/packet

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

View as plain text