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 (
	
	
	
	
	
	
	
	_ 
	_ 
	
	
	
	
	
	
	

	
	
)

NIST curve P-256
NIST curve P-384
NIST curve P-521
	oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
)

const maxOIDLength = 8
ecdsaKey stores the algorithm-specific fields for ECDSA keys. as defined in RFC 6637, Section 9.
oid contains the OID byte sequence identifying the elliptic curve used
p contains the elliptic curve point that represents the public key
parseOID reads the OID for the curve as defined in RFC 6637, Section 9.
func ( io.Reader) ( []byte,  error) {
	 := make([]byte, maxOIDLength)
	if _,  = readFull(, [:1]);  != nil {
		return
	}
	 := [0]
	if int() > len() {
		 = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int()))
		return
	}
	 = [:]
	_,  = readFull(, )
	return
}

func ( *ecdsaKey) ( io.Reader) ( error) {
	if .oid,  = parseOID();  != nil {
		return 
	}
	.p.bytes, .p.bitLength,  = readMPI()
	return
}

func ( *ecdsaKey) ( io.Writer) ( error) {
	 := make([]byte, maxOIDLength+1)
	[0] = byte(len(.oid))
	copy([1:], .oid)
	if _,  = .Write([:len(.oid)+1]);  != nil {
		return
	}
	return writeMPIs(, .p)
}

func ( *ecdsaKey) () (*ecdsa.PublicKey, error) {
	var  elliptic.Curve
	if bytes.Equal(.oid, oidCurveP256) {
		 = elliptic.P256()
	} else if bytes.Equal(.oid, oidCurveP384) {
		 = elliptic.P384()
	} else if bytes.Equal(.oid, oidCurveP521) {
		 = elliptic.P521()
	} else {
		return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", .oid))
	}
	,  := elliptic.Unmarshal(, .p.bytes)
	if  == nil {
		return nil, errors.UnsupportedError("failed to parse EC point")
	}
	return &ecdsa.PublicKey{Curve: , X: , Y: }, nil
}

func ( *ecdsaKey) () int {
	return 1 + len(.oid) + 2 + len(.p.bytes)
}

type kdfHashFunction byte
type kdfAlgorithm byte
ecdhKdf stores key derivation function parameters used for ECDH encryption. See RFC 6637, Section 9.
type ecdhKdf struct {
	KdfHash kdfHashFunction
	KdfAlgo kdfAlgorithm
}

func ( *ecdhKdf) ( io.Reader) ( error) {
	 := make([]byte, 1)
	if _,  = readFull(, );  != nil {
		return
	}
	 := int([0])
	if  < 3 {
		return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa())
	}
	 = make([]byte, )
	if _,  = readFull(, );  != nil {
		return
	}
	 := int([0])
	.KdfHash = kdfHashFunction([1])
	.KdfAlgo = kdfAlgorithm([2])
	if  != 0x01 {
		return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa())
	}
	return
}

func ( *ecdhKdf) ( io.Writer) ( error) {
See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys.
	[0] = byte(0x03) // Length of the following fields
	[1] = byte(0x01) // Reserved for future extensions, must be 1 for now
	[2] = byte(.KdfHash)
	[3] = byte(.KdfAlgo)
	_,  = .Write([:])
	return
}

func ( *ecdhKdf) () int {
	return 4
}
PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
type PublicKey struct {
	CreationTime time.Time
	PubKeyAlgo   PublicKeyAlgorithm
	PublicKey    interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey
	Fingerprint  [20]byte
	KeyId        uint64
	IsSubkey     bool

	n, e, p, q, g, y parsedMPI
RFC 6637 fields
signingKey provides a convenient abstraction over signature verification for v3 and v4 public keys.
type signingKey interface {
	SerializeSignaturePrefix(io.Writer)
	serializeWithoutHeaders(io.Writer) error
}

func ( *big.Int) parsedMPI {
	return parsedMPI{
		bytes:     .Bytes(),
		bitLength: uint16(.BitLen()),
	}
}
NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
func ( time.Time,  *rsa.PublicKey) *PublicKey {
	 := &PublicKey{
		CreationTime: ,
		PubKeyAlgo:   PubKeyAlgoRSA,
		PublicKey:    ,
		n:            fromBig(.N),
		e:            fromBig(big.NewInt(int64(.E))),
	}

	.setFingerPrintAndKeyId()
	return 
}
NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey.
func ( time.Time,  *dsa.PublicKey) *PublicKey {
	 := &PublicKey{
		CreationTime: ,
		PubKeyAlgo:   PubKeyAlgoDSA,
		PublicKey:    ,
		p:            fromBig(.P),
		q:            fromBig(.Q),
		g:            fromBig(.G),
		y:            fromBig(.Y),
	}

	.setFingerPrintAndKeyId()
	return 
}
NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
func ( time.Time,  *elgamal.PublicKey) *PublicKey {
	 := &PublicKey{
		CreationTime: ,
		PubKeyAlgo:   PubKeyAlgoElGamal,
		PublicKey:    ,
		p:            fromBig(.P),
		g:            fromBig(.G),
		y:            fromBig(.Y),
	}

	.setFingerPrintAndKeyId()
	return 
}

func ( time.Time,  *ecdsa.PublicKey) *PublicKey {
	 := &PublicKey{
		CreationTime: ,
		PubKeyAlgo:   PubKeyAlgoECDSA,
		PublicKey:    ,
		ec:           new(ecdsaKey),
	}

	switch .Curve {
	case elliptic.P256():
		.ec.oid = oidCurveP256
	case elliptic.P384():
		.ec.oid = oidCurveP384
	case elliptic.P521():
		.ec.oid = oidCurveP521
	default:
		panic("unknown elliptic curve")
	}

	.ec.p.bytes = elliptic.Marshal(.Curve, .X, .Y)
The bit length is 3 (for the 0x04 specifying an uncompressed key) plus two field elements (for x and y), which are rounded up to the nearest byte. See https://tools.ietf.org/html/rfc6637#section-6
	 := (.Curve.Params().BitSize + 7) & ^7
	.ec.p.bitLength = uint16(3 +  + )

	.setFingerPrintAndKeyId()
	return 
}

RFC 4880, section 5.5.2
	var  [6]byte
	_,  = readFull(, [:])
	if  != nil {
		return
	}
	if [0] != 4 {
		return errors.UnsupportedError("public key version")
	}
	.CreationTime = time.Unix(int64(uint32([1])<<24|uint32([2])<<16|uint32([3])<<8|uint32([4])), 0)
	.PubKeyAlgo = PublicKeyAlgorithm([5])
	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
		 = .parseRSA()
	case PubKeyAlgoDSA:
		 = .parseDSA()
	case PubKeyAlgoElGamal:
		 = .parseElGamal()
	case PubKeyAlgoECDSA:
		.ec = new(ecdsaKey)
		if  = .ec.parse();  != nil {
			return 
		}
		.PublicKey,  = .ec.newECDSA()
	case PubKeyAlgoECDH:
		.ec = new(ecdsaKey)
		if  = .ec.parse();  != nil {
			return
		}
		.ecdh = new(ecdhKdf)
		if  = .ecdh.parse();  != nil {
			return
The ECDH key is stored in an ecdsa.PublicKey for convenience.
		.PublicKey,  = .ec.newECDSA()
	default:
		 = errors.UnsupportedError("public key type: " + strconv.Itoa(int(.PubKeyAlgo)))
	}
	if  != nil {
		return
	}

	.setFingerPrintAndKeyId()
	return
}

RFC 4880, section 12.2
	 := sha1.New()
	.SerializeSignaturePrefix()
	.serializeWithoutHeaders()
	copy(.Fingerprint[:], .Sum(nil))
	.KeyId = binary.BigEndian.Uint64(.Fingerprint[12:20])
}
parseRSA parses RSA public key material from the given Reader. See RFC 4880, section 5.5.2.
func ( *PublicKey) ( io.Reader) ( error) {
	.n.bytes, .n.bitLength,  = readMPI()
	if  != nil {
		return
	}
	.e.bytes, .e.bitLength,  = readMPI()
	if  != nil {
		return
	}

	if len(.e.bytes) > 3 {
		 = errors.UnsupportedError("large public exponent")
		return
	}
	 := &rsa.PublicKey{
		N: new(big.Int).SetBytes(.n.bytes),
		E: 0,
	}
	for  := 0;  < len(.e.bytes); ++ {
		.E <<= 8
		.E |= int(.e.bytes[])
	}
	.PublicKey = 
	return
}
parseDSA parses DSA public key material from the given Reader. See RFC 4880, section 5.5.2.
func ( *PublicKey) ( io.Reader) ( error) {
	.p.bytes, .p.bitLength,  = readMPI()
	if  != nil {
		return
	}
	.q.bytes, .q.bitLength,  = readMPI()
	if  != nil {
		return
	}
	.g.bytes, .g.bitLength,  = readMPI()
	if  != nil {
		return
	}
	.y.bytes, .y.bitLength,  = readMPI()
	if  != nil {
		return
	}

	 := new(dsa.PublicKey)
	.P = new(big.Int).SetBytes(.p.bytes)
	.Q = new(big.Int).SetBytes(.q.bytes)
	.G = new(big.Int).SetBytes(.g.bytes)
	.Y = new(big.Int).SetBytes(.y.bytes)
	.PublicKey = 
	return
}
parseElGamal parses ElGamal public key material from the given Reader. See RFC 4880, section 5.5.2.
func ( *PublicKey) ( io.Reader) ( error) {
	.p.bytes, .p.bitLength,  = readMPI()
	if  != nil {
		return
	}
	.g.bytes, .g.bitLength,  = readMPI()
	if  != nil {
		return
	}
	.y.bytes, .y.bitLength,  = readMPI()
	if  != nil {
		return
	}

	 := new(elgamal.PublicKey)
	.P = new(big.Int).SetBytes(.p.bytes)
	.G = new(big.Int).SetBytes(.g.bytes)
	.Y = new(big.Int).SetBytes(.y.bytes)
	.PublicKey = 
	return
}
SerializeSignaturePrefix writes the prefix for this public key to the given Writer. The prefix is used when calculating a signature over this public key. See RFC 4880, section 5.2.4.
func ( *PublicKey) ( io.Writer) {
	var  uint16
	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
		 += 2 + uint16(len(.n.bytes))
		 += 2 + uint16(len(.e.bytes))
	case PubKeyAlgoDSA:
		 += 2 + uint16(len(.p.bytes))
		 += 2 + uint16(len(.q.bytes))
		 += 2 + uint16(len(.g.bytes))
		 += 2 + uint16(len(.y.bytes))
	case PubKeyAlgoElGamal:
		 += 2 + uint16(len(.p.bytes))
		 += 2 + uint16(len(.g.bytes))
		 += 2 + uint16(len(.y.bytes))
	case PubKeyAlgoECDSA:
		 += uint16(.ec.byteLen())
	case PubKeyAlgoECDH:
		 += uint16(.ec.byteLen())
		 += uint16(.ecdh.byteLen())
	default:
		panic("unknown public key algorithm")
	}
	 += 6
	.Write([]byte{0x99, byte( >> 8), byte()})
	return
}

func ( *PublicKey) ( io.Writer) ( error) {
	 := 6 // 6 byte header

	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
		 += 2 + len(.n.bytes)
		 += 2 + len(.e.bytes)
	case PubKeyAlgoDSA:
		 += 2 + len(.p.bytes)
		 += 2 + len(.q.bytes)
		 += 2 + len(.g.bytes)
		 += 2 + len(.y.bytes)
	case PubKeyAlgoElGamal:
		 += 2 + len(.p.bytes)
		 += 2 + len(.g.bytes)
		 += 2 + len(.y.bytes)
	case PubKeyAlgoECDSA:
		 += .ec.byteLen()
	case PubKeyAlgoECDH:
		 += .ec.byteLen()
		 += .ecdh.byteLen()
	default:
		panic("unknown public key algorithm")
	}

	 := packetTypePublicKey
	if .IsSubkey {
		 = packetTypePublicSubkey
	}
	 = serializeHeader(, , )
	if  != nil {
		return
	}
	return .serializeWithoutHeaders()
}
serializeWithoutHeaders marshals the PublicKey to w in the form of an OpenPGP public key packet, not including the packet header.
func ( *PublicKey) ( io.Writer) ( error) {
	var  [6]byte
	[0] = 4
	 := uint32(.CreationTime.Unix())
	[1] = byte( >> 24)
	[2] = byte( >> 16)
	[3] = byte( >> 8)
	[4] = byte()
	[5] = byte(.PubKeyAlgo)

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

	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
		return writeMPIs(, .n, .e)
	case PubKeyAlgoDSA:
		return writeMPIs(, .p, .q, .g, .y)
	case PubKeyAlgoElGamal:
		return writeMPIs(, .p, .g, .y)
	case PubKeyAlgoECDSA:
		return .ec.serialize()
	case PubKeyAlgoECDH:
		if  = .ec.serialize();  != nil {
			return
		}
		return .ecdh.serialize()
	}
	return errors.InvalidArgumentError("bad public-key algorithm")
}
CanSign returns true iff this public key can generate signatures
VerifySignature returns nil iff sig is a valid signature, made by this public key, of the data hashed into signed. signed is mutated by this call.
func ( *PublicKey) ( hash.Hash,  *Signature) ( error) {
	if !.CanSign() {
		return errors.InvalidArgumentError("public key cannot generate signatures")
	}

	.Write(.HashSuffix)
	 := .Sum(nil)

	if [0] != .HashTag[0] || [1] != .HashTag[1] {
		return errors.SignatureError("hash tag doesn't match")
	}

	if .PubKeyAlgo != .PubKeyAlgo {
		return errors.InvalidArgumentError("public key and signature use different algorithms")
	}

	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		,  := .PublicKey.(*rsa.PublicKey)
		 = rsa.VerifyPKCS1v15(, .Hash, , padToKeySize(, .RSASignature.bytes))
		if  != nil {
			return errors.SignatureError("RSA verification failure")
		}
		return nil
	case PubKeyAlgoDSA:
Need to truncate hashBytes to match FIPS 186-3 section 4.6.
		 := (.Q.BitLen() + 7) / 8
		if len() >  {
			 = [:]
		}
		if !dsa.Verify(, , new(big.Int).SetBytes(.DSASigR.bytes), new(big.Int).SetBytes(.DSASigS.bytes)) {
			return errors.SignatureError("DSA verification failure")
		}
		return nil
	case PubKeyAlgoECDSA:
		 := .PublicKey.(*ecdsa.PublicKey)
		if !ecdsa.Verify(, , new(big.Int).SetBytes(.ECDSASigR.bytes), new(big.Int).SetBytes(.ECDSASigS.bytes)) {
			return errors.SignatureError("ECDSA verification failure")
		}
		return nil
	default:
		return errors.SignatureError("Unsupported public key algorithm used in signature")
	}
}
VerifySignatureV3 returns nil iff sig is a valid signature, made by this public key, of the data hashed into signed. signed is mutated by this call.
func ( *PublicKey) ( hash.Hash,  *SignatureV3) ( error) {
	if !.CanSign() {
		return errors.InvalidArgumentError("public key cannot generate signatures")
	}

	 := make([]byte, 5)
	[0] = byte(.SigType)
	binary.BigEndian.PutUint32([1:], uint32(.CreationTime.Unix()))
	.Write()
	 := .Sum(nil)

	if [0] != .HashTag[0] || [1] != .HashTag[1] {
		return errors.SignatureError("hash tag doesn't match")
	}

	if .PubKeyAlgo != .PubKeyAlgo {
		return errors.InvalidArgumentError("public key and signature use different algorithms")
	}

	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		 := .PublicKey.(*rsa.PublicKey)
		if  = rsa.VerifyPKCS1v15(, .Hash, , padToKeySize(, .RSASignature.bytes));  != nil {
			return errors.SignatureError("RSA verification failure")
		}
		return
	case PubKeyAlgoDSA:
Need to truncate hashBytes to match FIPS 186-3 section 4.6.
		 := (.Q.BitLen() + 7) / 8
		if len() >  {
			 = [:]
		}
		if !dsa.Verify(, , new(big.Int).SetBytes(.DSASigR.bytes), new(big.Int).SetBytes(.DSASigS.bytes)) {
			return errors.SignatureError("DSA verification failure")
		}
		return nil
	default:
		panic("shouldn't happen")
	}
}
keySignatureHash returns a Hash of the message that needs to be signed for pk to assert a subkey relationship to signed.
func (,  signingKey,  crypto.Hash) ( hash.Hash,  error) {
	if !.Available() {
		return nil, errors.UnsupportedError("hash function")
	}
	 = .New()
RFC 4880, section 5.2.4
VerifyKeySignature returns nil iff sig is a valid signature, made by this public key, of signed.
func ( *PublicKey) ( *PublicKey,  *Signature) error {
	,  := keySignatureHash(, , .Hash)
	if  != nil {
		return 
	}
	if  = .VerifySignature(, );  != nil {
		return 
	}

Signing subkeys must be cross-signed. See https://www.gnupg.org/faq/subkey-cross-certify.html.
		if .EmbeddedSignature == nil {
			return errors.StructuralError("signing subkey is missing cross-signature")
Verify the cross-signature. This is calculated over the same data as the main signature, so we cannot just recursively call signed.VerifyKeySignature(...)
		if ,  = keySignatureHash(, , .EmbeddedSignature.Hash);  != nil {
			return errors.StructuralError("error while hashing for cross-signature: " + .Error())
		}
		if  := .VerifySignature(, .EmbeddedSignature);  != nil {
			return errors.StructuralError("error while verifying cross-signature: " + .Error())
		}
	}

	return nil
}

func ( signingKey,  crypto.Hash) ( hash.Hash,  error) {
	if !.Available() {
		return nil, errors.UnsupportedError("hash function")
	}
	 = .New()
RFC 4880, section 5.2.4
VerifyRevocationSignature returns nil iff sig is a valid signature, made by this public key.
func ( *PublicKey) ( *Signature) ( error) {
	,  := keyRevocationHash(, .Hash)
	if  != nil {
		return 
	}
	return .VerifySignature(, )
}
userIdSignatureHash returns a Hash of the message that needs to be signed to assert that pk is a valid key for id.
func ( string,  *PublicKey,  crypto.Hash) ( hash.Hash,  error) {
	if !.Available() {
		return nil, errors.UnsupportedError("hash function")
	}
	 = .New()
RFC 4880, section 5.2.4
	.SerializeSignaturePrefix()
	.serializeWithoutHeaders()

	var  [5]byte
	[0] = 0xb4
	[1] = byte(len() >> 24)
	[2] = byte(len() >> 16)
	[3] = byte(len() >> 8)
	[4] = byte(len())
	.Write([:])
	.Write([]byte())

	return
}
VerifyUserIdSignature returns nil iff sig is a valid signature, made by this public key, that id is the identity of pub.
func ( *PublicKey) ( string,  *PublicKey,  *Signature) ( error) {
	,  := userIdSignatureHash(, , .Hash)
	if  != nil {
		return 
	}
	return .VerifySignature(, )
}
VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this public key, that id is the identity of pub.
func ( *PublicKey) ( string,  *PublicKey,  *SignatureV3) ( error) {
	,  := userIdSignatureV3Hash(, , .Hash)
	if  != nil {
		return 
	}
	return .VerifySignatureV3(, )
}
KeyIdString returns the public key's fingerprint in capital hex (e.g. "6C7EE1B8621CC013").
func ( *PublicKey) () string {
	return fmt.Sprintf("%X", .Fingerprint[12:20])
}
KeyIdShortString returns the short form of public key's fingerprint in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
func ( *PublicKey) () string {
	return fmt.Sprintf("%X", .Fingerprint[16:20])
}
A parsedMPI is used to store the contents of a big integer, along with the bit length that was specified in the original input. This allows the MPI to be reserialized exactly.
type parsedMPI struct {
	bytes     []byte
	bitLength uint16
}
writeMPIs is a utility function for serializing several big integers to the given Writer.
func ( io.Writer,  ...parsedMPI) ( error) {
	for ,  := range  {
		 = writeMPI(, .bitLength, .bytes)
		if  != nil {
			return
		}
	}
	return
}
BitLength returns the bit length for the given public key.
func ( *PublicKey) () ( uint16,  error) {
	switch .PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
		 = .n.bitLength
	case PubKeyAlgoDSA:
		 = .p.bitLength
	case PubKeyAlgoElGamal:
		 = .p.bitLength
	default:
		 = errors.InvalidArgumentError("bad public-key algorithm")
	}
	return