Copyright 2011 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package packet

import (
	
	
	
	
	
	
	
	
	
	
	

	
	
)

See RFC 4880, section 5.2.3.21 for details.
Signature represents a signature. See RFC 4880, section 5.2.
HashSuffix is extra data that is hashed in after the signed data.
HashTag contains the first two bytes of the hash for fast rejection of bad signed data.
rawSubpackets contains the unparsed subpackets, in order.
The following are optional so are nil when not included in the signature.
FlagsValid is set if any flags were given. See RFC 4880, section 5.2.3.21 for details.
RevocationReason is set if this signature has been revoked. See RFC 4880, section 5.2.3.23 for details.
MDC is set if this signature has a feature packet that indicates support for MDC subpackets.
EmbeddedSignature, if non-nil, is a signature of the parent key, by this key. This prevents an attacker from claiming another's signing subkey as their own.
RFC 4880, section 5.2.3
	var  [5]byte
	_,  = readFull(, [:1])
	if  != nil {
		return
	}
	if [0] != 4 {
		 = errors.UnsupportedError("signature packet version " + strconv.Itoa(int([0])))
		return
	}

	_,  = readFull(, [:5])
	if  != nil {
		return
	}
	.SigType = SignatureType([0])
	.PubKeyAlgo = PublicKeyAlgorithm([1])
	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
	default:
		 = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(.PubKeyAlgo)))
		return
	}

	var  bool
	.Hash,  = s2k.HashIdToHash([2])
	if ! {
		return errors.UnsupportedError("hash function " + strconv.Itoa(int([2])))
	}

	 := int([3])<<8 | int([4])
	 := 6 + 
	.HashSuffix = make([]byte, +6)
	.HashSuffix[0] = 4
	copy(.HashSuffix[1:], [:5])
	 := .HashSuffix[6:]
	_,  = readFull(, )
	if  != nil {
		return
See RFC 4880, section 5.2.4
	 := .HashSuffix[:]
	[0] = 4
	[1] = 0xff
	[2] = uint8( >> 24)
	[3] = uint8( >> 16)
	[4] = uint8( >> 8)
	[5] = uint8()

	 = parseSignatureSubpackets(, , true)
	if  != nil {
		return
	}

	_,  = readFull(, [:2])
	if  != nil {
		return
	}
	 := int([0])<<8 | int([1])
	 := make([]byte, )
	_,  = readFull(, )
	if  != nil {
		return
	}
	 = parseSignatureSubpackets(, , false)
	if  != nil {
		return
	}

	_,  = readFull(, .HashTag[:2])
	if  != nil {
		return
	}

	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		.RSASignature.bytes, .RSASignature.bitLength,  = readMPI()
	case PubKeyAlgoDSA:
		.DSASigR.bytes, .DSASigR.bitLength,  = readMPI()
		if  == nil {
			.DSASigS.bytes, .DSASigS.bitLength,  = readMPI()
		}
	case PubKeyAlgoECDSA:
		.ECDSASigR.bytes, .ECDSASigR.bitLength,  = readMPI()
		if  == nil {
			.ECDSASigS.bytes, .ECDSASigS.bitLength,  = readMPI()
		}
	default:
		panic("unreachable")
	}
	return
}
parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
RFC 4880, section 5.2.3.1
	var (
		     uint32
		 signatureSubpacketType
		 bool
	)
	switch {
	case [0] < 192:
		 = uint32([0])
		 = [1:]
	case [0] < 255:
		if len() < 2 {
			goto 
		}
		 = uint32([0]-192)<<8 + uint32([1]) + 192
		 = [2:]
	default:
		if len() < 5 {
			goto 
		}
		 = uint32([1])<<24 |
			uint32([2])<<16 |
			uint32([3])<<8 |
			uint32([4])
		 = [5:]
	}
	if  > uint32(len()) {
		goto 
	}
	 = [:]
	 = [:]
	if len() == 0 {
		 = errors.StructuralError("zero length signature subpacket")
		return
	}
	 = signatureSubpacketType([0] & 0x7f)
	 = [0]&0x80 == 0x80
	 = [1:]
	.rawSubpackets = append(.rawSubpackets, outputSubpacket{, , , })
	switch  {
	case creationTimeSubpacket:
		if ! {
			 = errors.StructuralError("signature creation time in non-hashed area")
			return
		}
		if len() != 4 {
			 = errors.StructuralError("signature creation time not four bytes")
			return
		}
		 := binary.BigEndian.Uint32()
		.CreationTime = time.Unix(int64(), 0)
Signature expiration time, section 5.2.3.10
		if ! {
			return
		}
		if len() != 4 {
			 = errors.StructuralError("expiration subpacket with bad length")
			return
		}
		.SigLifetimeSecs = new(uint32)
		*.SigLifetimeSecs = binary.BigEndian.Uint32()
Key expiration time, section 5.2.3.6
		if ! {
			return
		}
		if len() != 4 {
			 = errors.StructuralError("key expiration subpacket with bad length")
			return
		}
		.KeyLifetimeSecs = new(uint32)
		*.KeyLifetimeSecs = binary.BigEndian.Uint32()
Preferred symmetric algorithms, section 5.2.3.7
		if ! {
			return
		}
		.PreferredSymmetric = make([]byte, len())
		copy(.PreferredSymmetric, )
Issuer, section 5.2.3.5
		if len() != 8 {
			 = errors.StructuralError("issuer subpacket with bad length")
			return
		}
		.IssuerKeyId = new(uint64)
		*.IssuerKeyId = binary.BigEndian.Uint64()
Preferred hash algorithms, section 5.2.3.8
		if ! {
			return
		}
		.PreferredHash = make([]byte, len())
		copy(.PreferredHash, )
Preferred compression algorithms, section 5.2.3.9
		if ! {
			return
		}
		.PreferredCompression = make([]byte, len())
		copy(.PreferredCompression, )
Primary User ID, section 5.2.3.19
		if ! {
			return
		}
		if len() != 1 {
			 = errors.StructuralError("primary user id subpacket with bad length")
			return
		}
		.IsPrimaryId = new(bool)
		if [0] > 0 {
			*.IsPrimaryId = true
		}
Key flags, section 5.2.3.21
		if ! {
			return
		}
		if len() == 0 {
			 = errors.StructuralError("empty key flags subpacket")
			return
		}
		.FlagsValid = true
		if [0]&KeyFlagCertify != 0 {
			.FlagCertify = true
		}
		if [0]&KeyFlagSign != 0 {
			.FlagSign = true
		}
		if [0]&KeyFlagEncryptCommunications != 0 {
			.FlagEncryptCommunications = true
		}
		if [0]&KeyFlagEncryptStorage != 0 {
			.FlagEncryptStorage = true
		}
Reason For Revocation, section 5.2.3.23
		if ! {
			return
		}
		if len() == 0 {
			 = errors.StructuralError("empty revocation reason subpacket")
			return
		}
		.RevocationReason = new(uint8)
		*.RevocationReason = [0]
		.RevocationReasonText = string([1:])
Features subpacket, section 5.2.3.24 specifies a very general mechanism for OpenPGP implementations to signal support for new features. In practice, the subpacket is used exclusively to indicate support for MDC-protected encryption.
		.MDC = len() >= 1 && [0]&1 == 1
Only usage is in signatures that cross-certify signing subkeys. section 5.2.3.26 describes the format, with its usage described in section 11.1
		if .EmbeddedSignature != nil {
			 = errors.StructuralError("Cannot have multiple embedded signatures")
			return
		}
Embedded signatures are required to be v4 signatures see section 12.1. However, we only parse v4 signatures in this file anyway.
		if  := .EmbeddedSignature.parse(bytes.NewBuffer());  != nil {
			return nil, 
		}
		if  := .EmbeddedSignature.SigType;  != SigTypePrimaryKeyBinding {
			return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int()))
		}
	default:
		if  {
			 = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int()))
			return
		}
	}
	return

:
	 = errors.StructuralError("signature subpacket truncated")
	return
}
subpacketLengthLength returns the length, in bytes, of an encoded length value.
func ( int) int {
	if  < 192 {
		return 1
	}
	if  < 16320 {
		return 2
	}
	return 5
}
serializeSubpacketLength marshals the given length into to.
RFC 4880, Section 4.2.2.
	if  < 192 {
		[0] = byte()
		return 1
	}
	if  < 16320 {
		 -= 192
		[0] = byte(( >> 8) + 192)
		[1] = byte()
		return 2
	}
	[0] = 255
	[1] = byte( >> 24)
	[2] = byte( >> 16)
	[3] = byte( >> 8)
	[4] = byte()
	return 5
}
subpacketsLength returns the serialized length, in bytes, of the given subpackets.
func ( []outputSubpacket,  bool) ( int) {
	for ,  := range  {
		if .hashed ==  {
			 += subpacketLengthLength(len(.contents) + 1)
			 += 1 // type byte
			 += len(.contents)
		}
	}
	return
}
serializeSubpackets marshals the given subpackets into to.
func ( []byte,  []outputSubpacket,  bool) {
	for ,  := range  {
		if .hashed ==  {
			 := serializeSubpacketLength(, len(.contents)+1)
			[] = byte(.subpacketType)
			 = [1+:]
			 = copy(, .contents)
			 = [:]
		}
	}
	return
}
KeyExpired returns whether sig is a self-signature of a key that has expired.
func ( *Signature) ( time.Time) bool {
	if .KeyLifetimeSecs == nil {
		return false
	}
	 := .CreationTime.Add(time.Duration(*.KeyLifetimeSecs) * time.Second)
	return .After()
}
buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
func ( *Signature) () ( error) {
	 := subpacketsLength(.outSubpackets, true)

	var  bool
	 := 6 + 
	.HashSuffix = make([]byte, +6)
	.HashSuffix[0] = 4
	.HashSuffix[1] = uint8(.SigType)
	.HashSuffix[2] = uint8(.PubKeyAlgo)
	.HashSuffix[3],  = s2k.HashToHashId(.Hash)
	if ! {
		.HashSuffix = nil
		return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(.Hash)))
	}
	.HashSuffix[4] = byte( >> 8)
	.HashSuffix[5] = byte()
	serializeSubpackets(.HashSuffix[6:], .outSubpackets, true)
	 := .HashSuffix[:]
	[0] = 4
	[1] = 0xff
	[2] = byte( >> 24)
	[3] = byte( >> 16)
	[4] = byte( >> 8)
	[5] = byte()
	return
}

func ( *Signature) ( hash.Hash) ( []byte,  error) {
	 = .buildHashSuffix()
	if  != nil {
		return
	}

	.Write(.HashSuffix)
	 = .Sum(nil)
	copy(.HashTag[:], )
	return
}
Sign signs a message with a private key. The hash, h, must contain the hash of the message to be signed and will be mutated by this function. On success, the signature is stored in sig. Call Serialize to write it out. If config is nil, sensible defaults will be used.
func ( *Signature) ( hash.Hash,  *PrivateKey,  *Config) ( error) {
	.outSubpackets = .buildSubpackets()
	,  := .signPrepareHash()
	if  != nil {
		return
	}

	switch .PubKeyAlgo {
supports both *rsa.PrivateKey and crypto.Signer
		.RSASignature.bytes,  = .PrivateKey.(crypto.Signer).Sign(.Random(), , .Hash)
		.RSASignature.bitLength = uint16(8 * len(.RSASignature.bytes))
	case PubKeyAlgoDSA:
		 := .PrivateKey.(*dsa.PrivateKey)
Need to truncate hashBytes to match FIPS 186-3 section 4.6.
		 := (.Q.BitLen() + 7) / 8
		if len() >  {
			 = [:]
		}
		, ,  := dsa.Sign(.Random(), , )
		if  == nil {
			.DSASigR.bytes = .Bytes()
			.DSASigR.bitLength = uint16(8 * len(.DSASigR.bytes))
			.DSASigS.bytes = .Bytes()
			.DSASigS.bitLength = uint16(8 * len(.DSASigS.bytes))
		}
	case PubKeyAlgoECDSA:
		var ,  *big.Int
direct support, avoid asn1 wrapping/unwrapping
			, ,  = ecdsa.Sign(.Random(), , )
		} else {
			var  []byte
			,  = .PrivateKey.(crypto.Signer).Sign(.Random(), , .Hash)
			if  == nil {
				, ,  = unwrapECDSASig()
			}
		}
		if  == nil {
			.ECDSASigR = fromBig()
			.ECDSASigS = fromBig()
		}
	default:
		 = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(.PubKeyAlgo)))
	}

	return
}
unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA signature.
func ( []byte) (,  *big.Int,  error) {
	var  struct {
		,  *big.Int
	}
	_,  = asn1.Unmarshal(, &)
	if  != nil {
		return
	}
	return ., ., nil
}
SignUserId computes a signature from priv, asserting that pub is a valid key for the identity id. On success, the signature is stored in sig. Call Serialize to write it out. If config is nil, sensible defaults will be used.
func ( *Signature) ( string,  *PublicKey,  *PrivateKey,  *Config) error {
	,  := userIdSignatureHash(, , .Hash)
	if  != nil {
		return 
	}
	return .Sign(, , )
}
SignKey computes a signature from priv, asserting that pub is a subkey. On success, the signature is stored in sig. Call Serialize to write it out. If config is nil, sensible defaults will be used.
func ( *Signature) ( *PublicKey,  *PrivateKey,  *Config) error {
	,  := keySignatureHash(&.PublicKey, , .Hash)
	if  != nil {
		return 
	}
	return .Sign(, , )
}
Serialize marshals sig to w. Sign, SignUserId or SignKey must have been called first.
func ( *Signature) ( io.Writer) ( error) {
	if len(.outSubpackets) == 0 {
		.outSubpackets = .rawSubpackets
	}
	if .RSASignature.bytes == nil && .DSASigR.bytes == nil && .ECDSASigR.bytes == nil {
		return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
	}

	 := 0
	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		 = 2 + len(.RSASignature.bytes)
	case PubKeyAlgoDSA:
		 = 2 + len(.DSASigR.bytes)
		 += 2 + len(.DSASigS.bytes)
	case PubKeyAlgoECDSA:
		 = 2 + len(.ECDSASigR.bytes)
		 += 2 + len(.ECDSASigS.bytes)
	default:
		panic("impossible")
	}

	 := subpacketsLength(.outSubpackets, false)
	 := len(.HashSuffix) - 6 /* trailer not included */ +
		2 /* length of unhashed subpackets */ +  +
		2 /* hash tag */ + 
	 = serializeHeader(, packetTypeSignature, )
	if  != nil {
		return
	}

	_,  = .Write(.HashSuffix[:len(.HashSuffix)-6])
	if  != nil {
		return
	}

	 := make([]byte, 2+)
	[0] = byte( >> 8)
	[1] = byte()
	serializeSubpackets([2:], .outSubpackets, false)

	_,  = .Write()
	if  != nil {
		return
	}
	_,  = .Write(.HashTag[:])
	if  != nil {
		return
	}

	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		 = writeMPIs(, .RSASignature)
	case PubKeyAlgoDSA:
		 = writeMPIs(, .DSASigR, .DSASigS)
	case PubKeyAlgoECDSA:
		 = writeMPIs(, .ECDSASigR, .ECDSASigS)
	default:
		panic("impossible")
	}
	return
}
outputSubpacket represents a subpacket to be marshaled.
type outputSubpacket struct {
	hashed        bool // true if this subpacket is in the hashed area.
	subpacketType signatureSubpacketType
	isCritical    bool
	contents      []byte
}

func ( *Signature) () ( []outputSubpacket) {
	 := make([]byte, 4)
	binary.BigEndian.PutUint32(, uint32(.CreationTime.Unix()))
	 = append(, outputSubpacket{true, creationTimeSubpacket, false, })

	if .IssuerKeyId != nil {
		 := make([]byte, 8)
		binary.BigEndian.PutUint64(, *.IssuerKeyId)
		 = append(, outputSubpacket{true, issuerSubpacket, false, })
	}

	if .SigLifetimeSecs != nil && *.SigLifetimeSecs != 0 {
		 := make([]byte, 4)
		binary.BigEndian.PutUint32(, *.SigLifetimeSecs)
		 = append(, outputSubpacket{true, signatureExpirationSubpacket, true, })
	}
Key flags may only appear in self-signatures or certification signatures.

	if .FlagsValid {
		var  byte
		if .FlagCertify {
			 |= KeyFlagCertify
		}
		if .FlagSign {
			 |= KeyFlagSign
		}
		if .FlagEncryptCommunications {
			 |= KeyFlagEncryptCommunications
		}
		if .FlagEncryptStorage {
			 |= KeyFlagEncryptStorage
		}
		 = append(, outputSubpacket{true, keyFlagsSubpacket, false, []byte{}})
	}
The following subpackets may only appear in self-signatures

	if .KeyLifetimeSecs != nil && *.KeyLifetimeSecs != 0 {
		 := make([]byte, 4)
		binary.BigEndian.PutUint32(, *.KeyLifetimeSecs)
		 = append(, outputSubpacket{true, keyExpirationSubpacket, true, })
	}

	if .IsPrimaryId != nil && *.IsPrimaryId {
		 = append(, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
	}

	if len(.PreferredSymmetric) > 0 {
		 = append(, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, .PreferredSymmetric})
	}

	if len(.PreferredHash) > 0 {
		 = append(, outputSubpacket{true, prefHashAlgosSubpacket, false, .PreferredHash})
	}

	if len(.PreferredCompression) > 0 {
		 = append(, outputSubpacket{true, prefCompressionSubpacket, false, .PreferredCompression})
	}

	return