github.com/maenmax/kairep@v0.0.0-20210218001208-55bf3df36788/src/golang.org/x/crypto/openpgp/packet/signature.go (about)

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