...

Source file src/golang.org/x/crypto/openpgp/packet/signature.go

Documentation: golang.org/x/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  	"bytes"
     9  	"crypto"
    10  	"crypto/dsa"
    11  	"crypto/ecdsa"
    12  	"encoding/asn1"
    13  	"encoding/binary"
    14  	"hash"
    15  	"io"
    16  	"math/big"
    17  	"strconv"
    18  	"time"
    19  
    20  	"golang.org/x/crypto/openpgp/errors"
    21  	"golang.org/x/crypto/openpgp/s2k"
    22  )
    23  
    24  const (
    25  	// See RFC 4880, section 5.2.3.21 for details.
    26  	KeyFlagCertify = 1 << iota
    27  	KeyFlagSign
    28  	KeyFlagEncryptCommunications
    29  	KeyFlagEncryptStorage
    30  )
    31  
    32  // Signature represents a signature. See RFC 4880, section 5.2.
    33  type Signature struct {
    34  	SigType    SignatureType
    35  	PubKeyAlgo PublicKeyAlgorithm
    36  	Hash       crypto.Hash
    37  
    38  	// HashSuffix is extra data that is hashed in after the signed data.
    39  	HashSuffix []byte
    40  	// HashTag contains the first two bytes of the hash for fast rejection
    41  	// of bad signed data.
    42  	HashTag      [2]byte
    43  	CreationTime time.Time
    44  
    45  	RSASignature         parsedMPI
    46  	DSASigR, DSASigS     parsedMPI
    47  	ECDSASigR, ECDSASigS parsedMPI
    48  
    49  	// rawSubpackets contains the unparsed subpackets, in order.
    50  	rawSubpackets []outputSubpacket
    51  
    52  	// The following are optional so are nil when not included in the
    53  	// signature.
    54  
    55  	SigLifetimeSecs, KeyLifetimeSecs                        *uint32
    56  	PreferredSymmetric, PreferredHash, PreferredCompression []uint8
    57  	IssuerKeyId                                             *uint64
    58  	IsPrimaryId                                             *bool
    59  
    60  	// FlagsValid is set if any flags were given. See RFC 4880, section
    61  	// 5.2.3.21 for details.
    62  	FlagsValid                                                           bool
    63  	FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
    64  
    65  	// RevocationReason is set if this signature has been revoked.
    66  	// See RFC 4880, section 5.2.3.23 for details.
    67  	RevocationReason     *uint8
    68  	RevocationReasonText string
    69  
    70  	// MDC is set if this signature has a feature packet that indicates
    71  	// support for MDC subpackets.
    72  	MDC bool
    73  
    74  	// EmbeddedSignature, if non-nil, is a signature of the parent key, by
    75  	// this key. This prevents an attacker from claiming another's signing
    76  	// subkey as their own.
    77  	EmbeddedSignature *Signature
    78  
    79  	outSubpackets []outputSubpacket
    80  }
    81  
    82  func (sig *Signature) parse(r io.Reader) (err error) {
    83  	// RFC 4880, section 5.2.3
    84  	var buf [5]byte
    85  	_, err = readFull(r, buf[:1])
    86  	if err != nil {
    87  		return
    88  	}
    89  	if buf[0] != 4 {
    90  		err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
    91  		return
    92  	}
    93  
    94  	_, err = readFull(r, buf[:5])
    95  	if err != nil {
    96  		return
    97  	}
    98  	sig.SigType = SignatureType(buf[0])
    99  	sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
   100  	switch sig.PubKeyAlgo {
   101  	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
   102  	default:
   103  		err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
   104  		return
   105  	}
   106  
   107  	var ok bool
   108  	sig.Hash, ok = s2k.HashIdToHash(buf[2])
   109  	if !ok {
   110  		return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
   111  	}
   112  
   113  	hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
   114  	l := 6 + hashedSubpacketsLength
   115  	sig.HashSuffix = make([]byte, l+6)
   116  	sig.HashSuffix[0] = 4
   117  	copy(sig.HashSuffix[1:], buf[:5])
   118  	hashedSubpackets := sig.HashSuffix[6:l]
   119  	_, err = readFull(r, hashedSubpackets)
   120  	if err != nil {
   121  		return
   122  	}
   123  	// See RFC 4880, section 5.2.4
   124  	trailer := sig.HashSuffix[l:]
   125  	trailer[0] = 4
   126  	trailer[1] = 0xff
   127  	trailer[2] = uint8(l >> 24)
   128  	trailer[3] = uint8(l >> 16)
   129  	trailer[4] = uint8(l >> 8)
   130  	trailer[5] = uint8(l)
   131  
   132  	err = parseSignatureSubpackets(sig, hashedSubpackets, true)
   133  	if err != nil {
   134  		return
   135  	}
   136  
   137  	_, err = readFull(r, buf[:2])
   138  	if err != nil {
   139  		return
   140  	}
   141  	unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
   142  	unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
   143  	_, err = readFull(r, unhashedSubpackets)
   144  	if err != nil {
   145  		return
   146  	}
   147  	err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
   148  	if err != nil {
   149  		return
   150  	}
   151  
   152  	_, err = readFull(r, sig.HashTag[:2])
   153  	if err != nil {
   154  		return
   155  	}
   156  
   157  	switch sig.PubKeyAlgo {
   158  	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
   159  		sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
   160  	case PubKeyAlgoDSA:
   161  		sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
   162  		if err == nil {
   163  			sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
   164  		}
   165  	case PubKeyAlgoECDSA:
   166  		sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
   167  		if err == nil {
   168  			sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r)
   169  		}
   170  	default:
   171  		panic("unreachable")
   172  	}
   173  	return
   174  }
   175  
   176  // parseSignatureSubpackets parses subpackets of the main signature packet. See
   177  // RFC 4880, section 5.2.3.1.
   178  func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
   179  	for len(subpackets) > 0 {
   180  		subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
   181  		if err != nil {
   182  			return
   183  		}
   184  	}
   185  
   186  	if sig.CreationTime.IsZero() {
   187  		err = errors.StructuralError("no creation time in signature")
   188  	}
   189  
   190  	return
   191  }
   192  
   193  type signatureSubpacketType uint8
   194  
   195  const (
   196  	creationTimeSubpacket        signatureSubpacketType = 2
   197  	signatureExpirationSubpacket signatureSubpacketType = 3
   198  	keyExpirationSubpacket       signatureSubpacketType = 9
   199  	prefSymmetricAlgosSubpacket  signatureSubpacketType = 11
   200  	issuerSubpacket              signatureSubpacketType = 16
   201  	prefHashAlgosSubpacket       signatureSubpacketType = 21
   202  	prefCompressionSubpacket     signatureSubpacketType = 22
   203  	primaryUserIdSubpacket       signatureSubpacketType = 25
   204  	keyFlagsSubpacket            signatureSubpacketType = 27
   205  	reasonForRevocationSubpacket signatureSubpacketType = 29
   206  	featuresSubpacket            signatureSubpacketType = 30
   207  	embeddedSignatureSubpacket   signatureSubpacketType = 32
   208  )
   209  
   210  // parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
   211  func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
   212  	// RFC 4880, section 5.2.3.1
   213  	var (
   214  		length     uint32
   215  		packetType signatureSubpacketType
   216  		isCritical bool
   217  	)
   218  	switch {
   219  	case subpacket[0] < 192:
   220  		length = uint32(subpacket[0])
   221  		subpacket = subpacket[1:]
   222  	case subpacket[0] < 255:
   223  		if len(subpacket) < 2 {
   224  			goto Truncated
   225  		}
   226  		length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
   227  		subpacket = subpacket[2:]
   228  	default:
   229  		if len(subpacket) < 5 {
   230  			goto Truncated
   231  		}
   232  		length = uint32(subpacket[1])<<24 |
   233  			uint32(subpacket[2])<<16 |
   234  			uint32(subpacket[3])<<8 |
   235  			uint32(subpacket[4])
   236  		subpacket = subpacket[5:]
   237  	}
   238  	if length > uint32(len(subpacket)) {
   239  		goto Truncated
   240  	}
   241  	rest = subpacket[length:]
   242  	subpacket = subpacket[:length]
   243  	if len(subpacket) == 0 {
   244  		err = errors.StructuralError("zero length signature subpacket")
   245  		return
   246  	}
   247  	packetType = signatureSubpacketType(subpacket[0] & 0x7f)
   248  	isCritical = subpacket[0]&0x80 == 0x80
   249  	subpacket = subpacket[1:]
   250  	sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
   251  	switch packetType {
   252  	case creationTimeSubpacket:
   253  		if !isHashed {
   254  			err = errors.StructuralError("signature creation time in non-hashed area")
   255  			return
   256  		}
   257  		if len(subpacket) != 4 {
   258  			err = errors.StructuralError("signature creation time not four bytes")
   259  			return
   260  		}
   261  		t := binary.BigEndian.Uint32(subpacket)
   262  		sig.CreationTime = time.Unix(int64(t), 0)
   263  	case signatureExpirationSubpacket:
   264  		// Signature expiration time, section 5.2.3.10
   265  		if !isHashed {
   266  			return
   267  		}
   268  		if len(subpacket) != 4 {
   269  			err = errors.StructuralError("expiration subpacket with bad length")
   270  			return
   271  		}
   272  		sig.SigLifetimeSecs = new(uint32)
   273  		*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
   274  	case keyExpirationSubpacket:
   275  		// Key expiration time, section 5.2.3.6
   276  		if !isHashed {
   277  			return
   278  		}
   279  		if len(subpacket) != 4 {
   280  			err = errors.StructuralError("key expiration subpacket with bad length")
   281  			return
   282  		}
   283  		sig.KeyLifetimeSecs = new(uint32)
   284  		*sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
   285  	case prefSymmetricAlgosSubpacket:
   286  		// Preferred symmetric algorithms, section 5.2.3.7
   287  		if !isHashed {
   288  			return
   289  		}
   290  		sig.PreferredSymmetric = make([]byte, len(subpacket))
   291  		copy(sig.PreferredSymmetric, subpacket)
   292  	case issuerSubpacket:
   293  		// Issuer, section 5.2.3.5
   294  		if len(subpacket) != 8 {
   295  			err = errors.StructuralError("issuer subpacket with bad length")
   296  			return
   297  		}
   298  		sig.IssuerKeyId = new(uint64)
   299  		*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
   300  	case prefHashAlgosSubpacket:
   301  		// Preferred hash algorithms, section 5.2.3.8
   302  		if !isHashed {
   303  			return
   304  		}
   305  		sig.PreferredHash = make([]byte, len(subpacket))
   306  		copy(sig.PreferredHash, subpacket)
   307  	case prefCompressionSubpacket:
   308  		// Preferred compression algorithms, section 5.2.3.9
   309  		if !isHashed {
   310  			return
   311  		}
   312  		sig.PreferredCompression = make([]byte, len(subpacket))
   313  		copy(sig.PreferredCompression, subpacket)
   314  	case primaryUserIdSubpacket:
   315  		// Primary User ID, section 5.2.3.19
   316  		if !isHashed {
   317  			return
   318  		}
   319  		if len(subpacket) != 1 {
   320  			err = errors.StructuralError("primary user id subpacket with bad length")
   321  			return
   322  		}
   323  		sig.IsPrimaryId = new(bool)
   324  		if subpacket[0] > 0 {
   325  			*sig.IsPrimaryId = true
   326  		}
   327  	case keyFlagsSubpacket:
   328  		// Key flags, section 5.2.3.21
   329  		if !isHashed {
   330  			return
   331  		}
   332  		if len(subpacket) == 0 {
   333  			err = errors.StructuralError("empty key flags subpacket")
   334  			return
   335  		}
   336  		sig.FlagsValid = true
   337  		if subpacket[0]&KeyFlagCertify != 0 {
   338  			sig.FlagCertify = true
   339  		}
   340  		if subpacket[0]&KeyFlagSign != 0 {
   341  			sig.FlagSign = true
   342  		}
   343  		if subpacket[0]&KeyFlagEncryptCommunications != 0 {
   344  			sig.FlagEncryptCommunications = true
   345  		}
   346  		if subpacket[0]&KeyFlagEncryptStorage != 0 {
   347  			sig.FlagEncryptStorage = true
   348  		}
   349  	case reasonForRevocationSubpacket:
   350  		// Reason For Revocation, section 5.2.3.23
   351  		if !isHashed {
   352  			return
   353  		}
   354  		if len(subpacket) == 0 {
   355  			err = errors.StructuralError("empty revocation reason subpacket")
   356  			return
   357  		}
   358  		sig.RevocationReason = new(uint8)
   359  		*sig.RevocationReason = subpacket[0]
   360  		sig.RevocationReasonText = string(subpacket[1:])
   361  	case featuresSubpacket:
   362  		// Features subpacket, section 5.2.3.24 specifies a very general
   363  		// mechanism for OpenPGP implementations to signal support for new
   364  		// features. In practice, the subpacket is used exclusively to
   365  		// indicate support for MDC-protected encryption.
   366  		sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1
   367  	case embeddedSignatureSubpacket:
   368  		// Only usage is in signatures that cross-certify
   369  		// signing subkeys. section 5.2.3.26 describes the
   370  		// format, with its usage described in section 11.1
   371  		if sig.EmbeddedSignature != nil {
   372  			err = errors.StructuralError("Cannot have multiple embedded signatures")
   373  			return
   374  		}
   375  		sig.EmbeddedSignature = new(Signature)
   376  		// Embedded signatures are required to be v4 signatures see
   377  		// section 12.1. However, we only parse v4 signatures in this
   378  		// file anyway.
   379  		if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil {
   380  			return nil, err
   381  		}
   382  		if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
   383  			return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
   384  		}
   385  	default:
   386  		if isCritical {
   387  			err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
   388  			return
   389  		}
   390  	}
   391  	return
   392  
   393  Truncated:
   394  	err = errors.StructuralError("signature subpacket truncated")
   395  	return
   396  }
   397  
   398  // subpacketLengthLength returns the length, in bytes, of an encoded length value.
   399  func subpacketLengthLength(length int) int {
   400  	if length < 192 {
   401  		return 1
   402  	}
   403  	if length < 16320 {
   404  		return 2
   405  	}
   406  	return 5
   407  }
   408  
   409  // serializeSubpacketLength marshals the given length into to.
   410  func serializeSubpacketLength(to []byte, length int) int {
   411  	// RFC 4880, Section 4.2.2.
   412  	if length < 192 {
   413  		to[0] = byte(length)
   414  		return 1
   415  	}
   416  	if length < 16320 {
   417  		length -= 192
   418  		to[0] = byte((length >> 8) + 192)
   419  		to[1] = byte(length)
   420  		return 2
   421  	}
   422  	to[0] = 255
   423  	to[1] = byte(length >> 24)
   424  	to[2] = byte(length >> 16)
   425  	to[3] = byte(length >> 8)
   426  	to[4] = byte(length)
   427  	return 5
   428  }
   429  
   430  // subpacketsLength returns the serialized length, in bytes, of the given
   431  // subpackets.
   432  func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
   433  	for _, subpacket := range subpackets {
   434  		if subpacket.hashed == hashed {
   435  			length += subpacketLengthLength(len(subpacket.contents) + 1)
   436  			length += 1 // type byte
   437  			length += len(subpacket.contents)
   438  		}
   439  	}
   440  	return
   441  }
   442  
   443  // serializeSubpackets marshals the given subpackets into to.
   444  func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
   445  	for _, subpacket := range subpackets {
   446  		if subpacket.hashed == hashed {
   447  			n := serializeSubpacketLength(to, len(subpacket.contents)+1)
   448  			to[n] = byte(subpacket.subpacketType)
   449  			to = to[1+n:]
   450  			n = copy(to, subpacket.contents)
   451  			to = to[n:]
   452  		}
   453  	}
   454  	return
   455  }
   456  
   457  // KeyExpired returns whether sig is a self-signature of a key that has
   458  // expired.
   459  func (sig *Signature) KeyExpired(currentTime time.Time) bool {
   460  	if sig.KeyLifetimeSecs == nil {
   461  		return false
   462  	}
   463  	expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
   464  	return currentTime.After(expiry)
   465  }
   466  
   467  // buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
   468  func (sig *Signature) buildHashSuffix() (err error) {
   469  	hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
   470  
   471  	var ok bool
   472  	l := 6 + hashedSubpacketsLen
   473  	sig.HashSuffix = make([]byte, l+6)
   474  	sig.HashSuffix[0] = 4
   475  	sig.HashSuffix[1] = uint8(sig.SigType)
   476  	sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
   477  	sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
   478  	if !ok {
   479  		sig.HashSuffix = nil
   480  		return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
   481  	}
   482  	sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
   483  	sig.HashSuffix[5] = byte(hashedSubpacketsLen)
   484  	serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
   485  	trailer := sig.HashSuffix[l:]
   486  	trailer[0] = 4
   487  	trailer[1] = 0xff
   488  	trailer[2] = byte(l >> 24)
   489  	trailer[3] = byte(l >> 16)
   490  	trailer[4] = byte(l >> 8)
   491  	trailer[5] = byte(l)
   492  	return
   493  }
   494  
   495  func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
   496  	err = sig.buildHashSuffix()
   497  	if err != nil {
   498  		return
   499  	}
   500  
   501  	h.Write(sig.HashSuffix)
   502  	digest = h.Sum(nil)
   503  	copy(sig.HashTag[:], digest)
   504  	return
   505  }
   506  
   507  // Sign signs a message with a private key. The hash, h, must contain
   508  // the hash of the message to be signed and will be mutated by this function.
   509  // On success, the signature is stored in sig. Call Serialize to write it out.
   510  // If config is nil, sensible defaults will be used.
   511  func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
   512  	sig.outSubpackets = sig.buildSubpackets()
   513  	digest, err := sig.signPrepareHash(h)
   514  	if err != nil {
   515  		return
   516  	}
   517  
   518  	switch priv.PubKeyAlgo {
   519  	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
   520  		// supports both *rsa.PrivateKey and crypto.Signer
   521  		sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
   522  		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
   523  	case PubKeyAlgoDSA:
   524  		dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
   525  
   526  		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
   527  		subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
   528  		if len(digest) > subgroupSize {
   529  			digest = digest[:subgroupSize]
   530  		}
   531  		r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
   532  		if err == nil {
   533  			sig.DSASigR.bytes = r.Bytes()
   534  			sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
   535  			sig.DSASigS.bytes = s.Bytes()
   536  			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
   537  		}
   538  	case PubKeyAlgoECDSA:
   539  		var r, s *big.Int
   540  		if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
   541  			// direct support, avoid asn1 wrapping/unwrapping
   542  			r, s, err = ecdsa.Sign(config.Random(), pk, digest)
   543  		} else {
   544  			var b []byte
   545  			b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
   546  			if err == nil {
   547  				r, s, err = unwrapECDSASig(b)
   548  			}
   549  		}
   550  		if err == nil {
   551  			sig.ECDSASigR = fromBig(r)
   552  			sig.ECDSASigS = fromBig(s)
   553  		}
   554  	default:
   555  		err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
   556  	}
   557  
   558  	return
   559  }
   560  
   561  // unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA
   562  // signature.
   563  func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
   564  	var ecsdaSig struct {
   565  		R, S *big.Int
   566  	}
   567  	_, err = asn1.Unmarshal(b, &ecsdaSig)
   568  	if err != nil {
   569  		return
   570  	}
   571  	return ecsdaSig.R, ecsdaSig.S, nil
   572  }
   573  
   574  // SignUserId computes a signature from priv, asserting that pub is a valid
   575  // key for the identity id.  On success, the signature is stored in sig. Call
   576  // Serialize to write it out.
   577  // If config is nil, sensible defaults will be used.
   578  func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
   579  	h, err := userIdSignatureHash(id, pub, sig.Hash)
   580  	if err != nil {
   581  		return err
   582  	}
   583  	return sig.Sign(h, priv, config)
   584  }
   585  
   586  // SignKey computes a signature from priv, asserting that pub is a subkey. On
   587  // success, the signature is stored in sig. Call Serialize to write it out.
   588  // If config is nil, sensible defaults will be used.
   589  func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
   590  	h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash)
   591  	if err != nil {
   592  		return err
   593  	}
   594  	return sig.Sign(h, priv, config)
   595  }
   596  
   597  // Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
   598  // called first.
   599  func (sig *Signature) Serialize(w io.Writer) (err error) {
   600  	if len(sig.outSubpackets) == 0 {
   601  		sig.outSubpackets = sig.rawSubpackets
   602  	}
   603  	if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil {
   604  		return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
   605  	}
   606  
   607  	sigLength := 0
   608  	switch sig.PubKeyAlgo {
   609  	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
   610  		sigLength = 2 + len(sig.RSASignature.bytes)
   611  	case PubKeyAlgoDSA:
   612  		sigLength = 2 + len(sig.DSASigR.bytes)
   613  		sigLength += 2 + len(sig.DSASigS.bytes)
   614  	case PubKeyAlgoECDSA:
   615  		sigLength = 2 + len(sig.ECDSASigR.bytes)
   616  		sigLength += 2 + len(sig.ECDSASigS.bytes)
   617  	default:
   618  		panic("impossible")
   619  	}
   620  
   621  	unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
   622  	length := len(sig.HashSuffix) - 6 /* trailer not included */ +
   623  		2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
   624  		2 /* hash tag */ + sigLength
   625  	err = serializeHeader(w, packetTypeSignature, length)
   626  	if err != nil {
   627  		return
   628  	}
   629  
   630  	_, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
   631  	if err != nil {
   632  		return
   633  	}
   634  
   635  	unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
   636  	unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
   637  	unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
   638  	serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
   639  
   640  	_, err = w.Write(unhashedSubpackets)
   641  	if err != nil {
   642  		return
   643  	}
   644  	_, err = w.Write(sig.HashTag[:])
   645  	if err != nil {
   646  		return
   647  	}
   648  
   649  	switch sig.PubKeyAlgo {
   650  	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
   651  		err = writeMPIs(w, sig.RSASignature)
   652  	case PubKeyAlgoDSA:
   653  		err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
   654  	case PubKeyAlgoECDSA:
   655  		err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
   656  	default:
   657  		panic("impossible")
   658  	}
   659  	return
   660  }
   661  
   662  // outputSubpacket represents a subpacket to be marshaled.
   663  type outputSubpacket struct {
   664  	hashed        bool // true if this subpacket is in the hashed area.
   665  	subpacketType signatureSubpacketType
   666  	isCritical    bool
   667  	contents      []byte
   668  }
   669  
   670  func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
   671  	creationTime := make([]byte, 4)
   672  	binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
   673  	subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
   674  
   675  	if sig.IssuerKeyId != nil {
   676  		keyId := make([]byte, 8)
   677  		binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
   678  		subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
   679  	}
   680  
   681  	if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
   682  		sigLifetime := make([]byte, 4)
   683  		binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
   684  		subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
   685  	}
   686  
   687  	// Key flags may only appear in self-signatures or certification signatures.
   688  
   689  	if sig.FlagsValid {
   690  		var flags byte
   691  		if sig.FlagCertify {
   692  			flags |= KeyFlagCertify
   693  		}
   694  		if sig.FlagSign {
   695  			flags |= KeyFlagSign
   696  		}
   697  		if sig.FlagEncryptCommunications {
   698  			flags |= KeyFlagEncryptCommunications
   699  		}
   700  		if sig.FlagEncryptStorage {
   701  			flags |= KeyFlagEncryptStorage
   702  		}
   703  		subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
   704  	}
   705  
   706  	// The following subpackets may only appear in self-signatures
   707  
   708  	if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
   709  		keyLifetime := make([]byte, 4)
   710  		binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
   711  		subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
   712  	}
   713  
   714  	if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
   715  		subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
   716  	}
   717  
   718  	if len(sig.PreferredSymmetric) > 0 {
   719  		subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
   720  	}
   721  
   722  	if len(sig.PreferredHash) > 0 {
   723  		subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
   724  	}
   725  
   726  	if len(sig.PreferredCompression) > 0 {
   727  		subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
   728  	}
   729  
   730  	return
   731  }
   732  

View as plain text