mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 05:25:15 +01:00 
			
		
		
		
	* Switch to keybase go-crypto (for some elliptic curve key) + test
* Use assert.NoError 
and add a little more context to failing test description
* Use assert.(No)Error everywhere 🌈
and assert.Error in place of .Nil/.NotNil
		
	
			
		
			
				
	
	
		
			903 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			903 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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 openpgp
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto/hmac"
 | 
						|
	"encoding/binary"
 | 
						|
	"io"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/keybase/go-crypto/openpgp/armor"
 | 
						|
	"github.com/keybase/go-crypto/openpgp/errors"
 | 
						|
	"github.com/keybase/go-crypto/openpgp/packet"
 | 
						|
	"github.com/keybase/go-crypto/rsa"
 | 
						|
)
 | 
						|
 | 
						|
// PublicKeyType is the armor type for a PGP public key.
 | 
						|
var PublicKeyType = "PGP PUBLIC KEY BLOCK"
 | 
						|
 | 
						|
// PrivateKeyType is the armor type for a PGP private key.
 | 
						|
var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
 | 
						|
 | 
						|
// An Entity represents the components of an OpenPGP key: a primary public key
 | 
						|
// (which must be a signing key), one or more identities claimed by that key,
 | 
						|
// and zero or more subkeys, which may be encryption keys.
 | 
						|
type Entity struct {
 | 
						|
	PrimaryKey  *packet.PublicKey
 | 
						|
	PrivateKey  *packet.PrivateKey
 | 
						|
	Identities  map[string]*Identity // indexed by Identity.Name
 | 
						|
	Revocations []*packet.Signature
 | 
						|
	// Revocations that are signed by designated revokers. Reading keys
 | 
						|
	// will not verify these revocations, because it won't have access to
 | 
						|
	// issuers' public keys, API consumers should do this instead (or
 | 
						|
	// not, and just assume that the key is probably revoked).
 | 
						|
	UnverifiedRevocations []*packet.Signature
 | 
						|
	Subkeys               []Subkey
 | 
						|
	BadSubkeys            []BadSubkey
 | 
						|
}
 | 
						|
 | 
						|
// An Identity represents an identity claimed by an Entity and zero or more
 | 
						|
// assertions by other entities about that claim.
 | 
						|
type Identity struct {
 | 
						|
	Name          string // by convention, has the form "Full Name (comment) <email@example.com>"
 | 
						|
	UserId        *packet.UserId
 | 
						|
	SelfSignature *packet.Signature
 | 
						|
	Signatures    []*packet.Signature
 | 
						|
	Revocation    *packet.Signature
 | 
						|
}
 | 
						|
 | 
						|
// A Subkey is an additional public key in an Entity. Subkeys can be used for
 | 
						|
// encryption.
 | 
						|
type Subkey struct {
 | 
						|
	PublicKey  *packet.PublicKey
 | 
						|
	PrivateKey *packet.PrivateKey
 | 
						|
	Sig        *packet.Signature
 | 
						|
	Revocation *packet.Signature
 | 
						|
}
 | 
						|
 | 
						|
// BadSubkey is one that failed reconstruction, but we'll keep it around for
 | 
						|
// informational purposes.
 | 
						|
type BadSubkey struct {
 | 
						|
	Subkey
 | 
						|
	Err error
 | 
						|
}
 | 
						|
 | 
						|
// A Key identifies a specific public key in an Entity. This is either the
 | 
						|
// Entity's primary key or a subkey.
 | 
						|
type Key struct {
 | 
						|
	Entity        *Entity
 | 
						|
	PublicKey     *packet.PublicKey
 | 
						|
	PrivateKey    *packet.PrivateKey
 | 
						|
	SelfSignature *packet.Signature
 | 
						|
	KeyFlags      packet.KeyFlagBits
 | 
						|
}
 | 
						|
 | 
						|
// A KeyRing provides access to public and private keys.
 | 
						|
type KeyRing interface {
 | 
						|
 | 
						|
	// KeysById returns the set of keys that have the given key id.
 | 
						|
	// fp can be optionally supplied, which is the full key fingerprint.
 | 
						|
	// If it's provided, then it must match. This comes up in the case
 | 
						|
	// of GPG subpacket 33.
 | 
						|
	KeysById(id uint64, fp []byte) []Key
 | 
						|
 | 
						|
	// KeysByIdAndUsage returns the set of keys with the given id
 | 
						|
	// that also meet the key usage given by requiredUsage.
 | 
						|
	// The requiredUsage is expressed as the bitwise-OR of
 | 
						|
	// packet.KeyFlag* values.
 | 
						|
	// fp can be optionally supplied, which is the full key fingerprint.
 | 
						|
	// If it's provided, then it must match. This comes up in the case
 | 
						|
	// of GPG subpacket 33.
 | 
						|
	KeysByIdUsage(id uint64, fp []byte, requiredUsage byte) []Key
 | 
						|
 | 
						|
	// DecryptionKeys returns all private keys that are valid for
 | 
						|
	// decryption.
 | 
						|
	DecryptionKeys() []Key
 | 
						|
}
 | 
						|
 | 
						|
// primaryIdentity returns the Identity marked as primary or the first identity
 | 
						|
// if none are so marked.
 | 
						|
func (e *Entity) primaryIdentity() *Identity {
 | 
						|
	var firstIdentity *Identity
 | 
						|
	for _, ident := range e.Identities {
 | 
						|
		if firstIdentity == nil {
 | 
						|
			firstIdentity = ident
 | 
						|
		}
 | 
						|
		if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
 | 
						|
			return ident
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return firstIdentity
 | 
						|
}
 | 
						|
 | 
						|
// encryptionKey returns the best candidate Key for encrypting a message to the
 | 
						|
// given Entity.
 | 
						|
func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
 | 
						|
	candidateSubkey := -1
 | 
						|
 | 
						|
	// Iterate the keys to find the newest key
 | 
						|
	var maxTime time.Time
 | 
						|
	for i, subkey := range e.Subkeys {
 | 
						|
 | 
						|
		// NOTE(maxtaco)
 | 
						|
		// If there is a Flags subpacket, then we have to follow it, and only
 | 
						|
		// use keys that are marked for Encryption of Communication.  If there
 | 
						|
		// isn't a Flags subpacket, and this is an Encrypt-Only key (right now only ElGamal
 | 
						|
		// suffices), then we implicitly use it. The check for primary below is a little
 | 
						|
		// more open-ended, but for now, let's be strict and potentially open up
 | 
						|
		// if we see bugs in the wild.
 | 
						|
		//
 | 
						|
		// One more note: old DSA/ElGamal keys tend not to have the Flags subpacket,
 | 
						|
		// so this sort of thing is pretty important for encrypting to older keys.
 | 
						|
		//
 | 
						|
		if ((subkey.Sig.FlagsValid && subkey.Sig.FlagEncryptCommunications) ||
 | 
						|
			(!subkey.Sig.FlagsValid && subkey.PublicKey.PubKeyAlgo == packet.PubKeyAlgoElGamal)) &&
 | 
						|
			subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
 | 
						|
			!subkey.Sig.KeyExpired(now) &&
 | 
						|
			subkey.Revocation == nil &&
 | 
						|
			(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
 | 
						|
			candidateSubkey = i
 | 
						|
			maxTime = subkey.Sig.CreationTime
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if candidateSubkey != -1 {
 | 
						|
		subkey := e.Subkeys[candidateSubkey]
 | 
						|
		return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Sig.GetKeyFlags()}, true
 | 
						|
	}
 | 
						|
 | 
						|
	// If we don't have any candidate subkeys for encryption and
 | 
						|
	// the primary key doesn't have any usage metadata then we
 | 
						|
	// assume that the primary key is ok. Or, if the primary key is
 | 
						|
	// marked as ok to encrypt to, then we can obviously use it.
 | 
						|
	//
 | 
						|
	// NOTE(maxtaco) - see note above, how this policy is a little too open-ended
 | 
						|
	// for my liking, but leave it for now.
 | 
						|
	i := e.primaryIdentity()
 | 
						|
	if (!i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications) &&
 | 
						|
		e.PrimaryKey.PubKeyAlgo.CanEncrypt() &&
 | 
						|
		!i.SelfSignature.KeyExpired(now) {
 | 
						|
		return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, i.SelfSignature.GetKeyFlags()}, true
 | 
						|
	}
 | 
						|
 | 
						|
	// This Entity appears to be signing only.
 | 
						|
	return Key{}, false
 | 
						|
}
 | 
						|
 | 
						|
// signingKey return the best candidate Key for signing a message with this
 | 
						|
// Entity.
 | 
						|
func (e *Entity) signingKey(now time.Time) (Key, bool) {
 | 
						|
	candidateSubkey := -1
 | 
						|
 | 
						|
	for i, subkey := range e.Subkeys {
 | 
						|
		if (!subkey.Sig.FlagsValid || subkey.Sig.FlagSign) &&
 | 
						|
			subkey.PrivateKey.PrivateKey != nil &&
 | 
						|
			subkey.PublicKey.PubKeyAlgo.CanSign() &&
 | 
						|
			subkey.Revocation == nil &&
 | 
						|
			!subkey.Sig.KeyExpired(now) {
 | 
						|
			candidateSubkey = i
 | 
						|
			break
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if candidateSubkey != -1 {
 | 
						|
		subkey := e.Subkeys[candidateSubkey]
 | 
						|
		return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Sig.GetKeyFlags()}, true
 | 
						|
	}
 | 
						|
 | 
						|
	// If we have no candidate subkey then we assume that it's ok to sign
 | 
						|
	// with the primary key.
 | 
						|
	i := e.primaryIdentity()
 | 
						|
	if (!i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign) &&
 | 
						|
		e.PrimaryKey.PubKeyAlgo.CanSign() &&
 | 
						|
		!i.SelfSignature.KeyExpired(now) &&
 | 
						|
		e.PrivateKey.PrivateKey != nil {
 | 
						|
		return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, i.SelfSignature.GetKeyFlags()}, true
 | 
						|
	}
 | 
						|
 | 
						|
	return Key{}, false
 | 
						|
}
 | 
						|
 | 
						|
// An EntityList contains one or more Entities.
 | 
						|
type EntityList []*Entity
 | 
						|
 | 
						|
func keyMatchesIdAndFingerprint(key *packet.PublicKey, id uint64, fp []byte) bool {
 | 
						|
	if key.KeyId != id {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	if fp == nil {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	return hmac.Equal(fp, key.Fingerprint[:])
 | 
						|
}
 | 
						|
 | 
						|
// KeysById returns the set of keys that have the given key id.
 | 
						|
// fp can be optionally supplied, which is the full key fingerprint.
 | 
						|
// If it's provided, then it must match. This comes up in the case
 | 
						|
// of GPG subpacket 33.
 | 
						|
func (el EntityList) KeysById(id uint64, fp []byte) (keys []Key) {
 | 
						|
	for _, e := range el {
 | 
						|
		if keyMatchesIdAndFingerprint(e.PrimaryKey, id, fp) {
 | 
						|
			var selfSig *packet.Signature
 | 
						|
			for _, ident := range e.Identities {
 | 
						|
				if selfSig == nil {
 | 
						|
					selfSig = ident.SelfSignature
 | 
						|
				} else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
 | 
						|
					selfSig = ident.SelfSignature
 | 
						|
					break
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			var keyFlags packet.KeyFlagBits
 | 
						|
			for _, ident := range e.Identities {
 | 
						|
				keyFlags.Merge(ident.SelfSignature.GetKeyFlags())
 | 
						|
			}
 | 
						|
 | 
						|
			keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig, keyFlags})
 | 
						|
		}
 | 
						|
 | 
						|
		for _, subKey := range e.Subkeys {
 | 
						|
			if keyMatchesIdAndFingerprint(subKey.PublicKey, id, fp) {
 | 
						|
 | 
						|
				// If there's both a a revocation and a sig, then take the
 | 
						|
				// revocation. Otherwise, we can proceed with the sig.
 | 
						|
				sig := subKey.Revocation
 | 
						|
				if sig == nil {
 | 
						|
					sig = subKey.Sig
 | 
						|
				}
 | 
						|
 | 
						|
				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, sig, sig.GetKeyFlags()})
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// KeysByIdAndUsage returns the set of keys with the given id that also meet
 | 
						|
// the key usage given by requiredUsage.  The requiredUsage is expressed as
 | 
						|
// the bitwise-OR of packet.KeyFlag* values.
 | 
						|
// fp can be optionally supplied, which is the full key fingerprint.
 | 
						|
// If it's provided, then it must match. This comes up in the case
 | 
						|
// of GPG subpacket 33.
 | 
						|
func (el EntityList) KeysByIdUsage(id uint64, fp []byte, requiredUsage byte) (keys []Key) {
 | 
						|
	for _, key := range el.KeysById(id, fp) {
 | 
						|
		if len(key.Entity.Revocations) > 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		if key.SelfSignature.RevocationReason != nil {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		if requiredUsage != 0 {
 | 
						|
			var usage byte
 | 
						|
 | 
						|
			switch {
 | 
						|
			case key.KeyFlags.Valid:
 | 
						|
				usage = key.KeyFlags.BitField
 | 
						|
 | 
						|
			case key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoElGamal:
 | 
						|
				// We also need to handle the case where, although the sig's
 | 
						|
				// flags aren't valid, the key can is implicitly usable for
 | 
						|
				// encryption by virtue of being ElGamal. See also the comment
 | 
						|
				// in encryptionKey() above.
 | 
						|
				usage |= packet.KeyFlagEncryptCommunications
 | 
						|
				usage |= packet.KeyFlagEncryptStorage
 | 
						|
 | 
						|
			case key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoDSA ||
 | 
						|
				key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoECDSA ||
 | 
						|
				key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoEdDSA:
 | 
						|
				usage |= packet.KeyFlagSign
 | 
						|
 | 
						|
			// For a primary RSA key without any key flags, be as permissiable
 | 
						|
			// as possible.
 | 
						|
			case key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoRSA &&
 | 
						|
				keyMatchesIdAndFingerprint(key.Entity.PrimaryKey, id, fp):
 | 
						|
				usage = (packet.KeyFlagCertify | packet.KeyFlagSign |
 | 
						|
					packet.KeyFlagEncryptCommunications | packet.KeyFlagEncryptStorage)
 | 
						|
			}
 | 
						|
 | 
						|
			if usage&requiredUsage != requiredUsage {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		keys = append(keys, key)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// DecryptionKeys returns all private keys that are valid for decryption.
 | 
						|
func (el EntityList) DecryptionKeys() (keys []Key) {
 | 
						|
	for _, e := range el {
 | 
						|
		for _, subKey := range e.Subkeys {
 | 
						|
			if subKey.PrivateKey != nil && subKey.PrivateKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
 | 
						|
				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Sig.GetKeyFlags()})
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
 | 
						|
func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
 | 
						|
	block, err := armor.Decode(r)
 | 
						|
	if err == io.EOF {
 | 
						|
		return nil, errors.InvalidArgumentError("no armored data found")
 | 
						|
	}
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if block.Type != PublicKeyType && block.Type != PrivateKeyType {
 | 
						|
		return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
 | 
						|
	}
 | 
						|
 | 
						|
	return ReadKeyRing(block.Body)
 | 
						|
}
 | 
						|
 | 
						|
// ReadKeyRing reads one or more public/private keys. Unsupported keys are
 | 
						|
// ignored as long as at least a single valid key is found.
 | 
						|
func ReadKeyRing(r io.Reader) (el EntityList, err error) {
 | 
						|
	packets := packet.NewReader(r)
 | 
						|
	var lastUnsupportedError error
 | 
						|
 | 
						|
	for {
 | 
						|
		var e *Entity
 | 
						|
		e, err = ReadEntity(packets)
 | 
						|
		if err != nil {
 | 
						|
			// TODO: warn about skipped unsupported/unreadable keys
 | 
						|
			if _, ok := err.(errors.UnsupportedError); ok {
 | 
						|
				lastUnsupportedError = err
 | 
						|
				err = readToNextPublicKey(packets)
 | 
						|
			} else if _, ok := err.(errors.StructuralError); ok {
 | 
						|
				// Skip unreadable, badly-formatted keys
 | 
						|
				lastUnsupportedError = err
 | 
						|
				err = readToNextPublicKey(packets)
 | 
						|
			}
 | 
						|
			if err == io.EOF {
 | 
						|
				err = nil
 | 
						|
				break
 | 
						|
			}
 | 
						|
			if err != nil {
 | 
						|
				el = nil
 | 
						|
				break
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			el = append(el, e)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if len(el) == 0 && err == nil {
 | 
						|
		err = lastUnsupportedError
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// readToNextPublicKey reads packets until the start of the entity and leaves
 | 
						|
// the first packet of the new entity in the Reader.
 | 
						|
func readToNextPublicKey(packets *packet.Reader) (err error) {
 | 
						|
	var p packet.Packet
 | 
						|
	for {
 | 
						|
		p, err = packets.Next()
 | 
						|
		if err == io.EOF {
 | 
						|
			return
 | 
						|
		} else if err != nil {
 | 
						|
			if _, ok := err.(errors.UnsupportedError); ok {
 | 
						|
				err = nil
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
 | 
						|
			packets.Unread(p)
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	panic("unreachable")
 | 
						|
}
 | 
						|
 | 
						|
// ReadEntity reads an entity (public key, identities, subkeys etc) from the
 | 
						|
// given Reader.
 | 
						|
func ReadEntity(packets *packet.Reader) (*Entity, error) {
 | 
						|
	e := new(Entity)
 | 
						|
	e.Identities = make(map[string]*Identity)
 | 
						|
 | 
						|
	p, err := packets.Next()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	var ok bool
 | 
						|
	if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
 | 
						|
		if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
 | 
						|
			packets.Unread(p)
 | 
						|
			return nil, errors.StructuralError("first packet was not a public/private key")
 | 
						|
		} else {
 | 
						|
			e.PrimaryKey = &e.PrivateKey.PublicKey
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if !e.PrimaryKey.PubKeyAlgo.CanSign() {
 | 
						|
		return nil, errors.StructuralError("primary key cannot be used for signatures")
 | 
						|
	}
 | 
						|
 | 
						|
	var current *Identity
 | 
						|
	var revocations []*packet.Signature
 | 
						|
 | 
						|
	designatedRevokers := make(map[uint64]bool)
 | 
						|
EachPacket:
 | 
						|
	for {
 | 
						|
		p, err := packets.Next()
 | 
						|
		if err == io.EOF {
 | 
						|
			break
 | 
						|
		} else if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		switch pkt := p.(type) {
 | 
						|
		case *packet.UserId:
 | 
						|
 | 
						|
			// Make a new Identity object, that we might wind up throwing away.
 | 
						|
			// We'll only add it if we get a valid self-signature over this
 | 
						|
			// userID.
 | 
						|
			current = new(Identity)
 | 
						|
			current.Name = pkt.Id
 | 
						|
			current.UserId = pkt
 | 
						|
		case *packet.Signature:
 | 
						|
			if pkt.SigType == packet.SigTypeKeyRevocation {
 | 
						|
				// These revocations won't revoke UIDs (see
 | 
						|
				// SigTypeIdentityRevocation). Handle these first,
 | 
						|
				// because key might have revocation coming from
 | 
						|
				// another key (designated revoke).
 | 
						|
				revocations = append(revocations, pkt)
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			// These are signatures by other people on this key. Let's just ignore them
 | 
						|
			// from the beginning, since they shouldn't affect our key decoding one way
 | 
						|
			// or the other.
 | 
						|
			if pkt.IssuerKeyId != nil && *pkt.IssuerKeyId != e.PrimaryKey.KeyId {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			// If this is a signature made by the keyholder, and the signature has stubbed out
 | 
						|
			// critical packets, then *now* we need to bail out.
 | 
						|
			if e := pkt.StubbedOutCriticalError; e != nil {
 | 
						|
				return nil, e
 | 
						|
			}
 | 
						|
 | 
						|
			// Next handle the case of a self-signature. According to RFC8440,
 | 
						|
			// Section 5.2.3.3, if there are several self-signatures,
 | 
						|
			// we should take the newer one.  If they were both created
 | 
						|
			// at the same time, but one of them has keyflags specified and the
 | 
						|
			// other doesn't, keep the one with the keyflags. We have actually
 | 
						|
			// seen this in the wild (see the 'Yield' test in read_test.go).
 | 
						|
			// If there is a tie, and both have the same value for FlagsValid,
 | 
						|
			// then "last writer wins."
 | 
						|
			//
 | 
						|
			// HOWEVER! We have seen yet more keys in the wild (see the 'Spiros'
 | 
						|
			// test in read_test.go), in which the later self-signature is a bunch
 | 
						|
			// of junk, and doesn't even specify key flags. Does it really make
 | 
						|
			// sense to overwrite reasonable key flags with the empty set? I'm not
 | 
						|
			// sure what that would be trying to achieve, and plus GPG seems to be
 | 
						|
			// ok with this situation, and ignores the later (empty) keyflag set.
 | 
						|
			// So further tighten our overwrite rules, and only allow the later
 | 
						|
			// signature to overwrite the earlier signature if so doing won't
 | 
						|
			// trash the key flags.
 | 
						|
			if current != nil &&
 | 
						|
				(current.SelfSignature == nil ||
 | 
						|
					(!pkt.CreationTime.Before(current.SelfSignature.CreationTime) &&
 | 
						|
						(pkt.FlagsValid || !current.SelfSignature.FlagsValid))) &&
 | 
						|
				(pkt.SigType == packet.SigTypePositiveCert || pkt.SigType == packet.SigTypeGenericCert) &&
 | 
						|
				pkt.IssuerKeyId != nil &&
 | 
						|
				*pkt.IssuerKeyId == e.PrimaryKey.KeyId {
 | 
						|
 | 
						|
				if err = e.PrimaryKey.VerifyUserIdSignature(current.Name, e.PrimaryKey, pkt); err == nil {
 | 
						|
 | 
						|
					current.SelfSignature = pkt
 | 
						|
 | 
						|
					// NOTE(maxtaco) 2016.01.11
 | 
						|
					// Only register an identity once we've gotten a valid self-signature.
 | 
						|
					// It's possible therefore for us to throw away `current` in the case
 | 
						|
					// no valid self-signatures were found. That's OK as long as there are
 | 
						|
					// other identies that make sense.
 | 
						|
					//
 | 
						|
					// NOTE! We might later see a revocation for this very same UID, and it
 | 
						|
					// won't be undone. We've preserved this feature from the original
 | 
						|
					// Google OpenPGP we forked from.
 | 
						|
					e.Identities[current.Name] = current
 | 
						|
				} else {
 | 
						|
					// We really should warn that there was a failure here. Not raise an error
 | 
						|
					// since this really shouldn't be a fail-stop error.
 | 
						|
				}
 | 
						|
			} else if current != nil && pkt.SigType == packet.SigTypeIdentityRevocation {
 | 
						|
				if err = e.PrimaryKey.VerifyUserIdSignature(current.Name, e.PrimaryKey, pkt); err == nil {
 | 
						|
					// Note: we are not removing the identity from
 | 
						|
					// e.Identities. Caller can always filter by Revocation
 | 
						|
					// field to ignore revoked identities.
 | 
						|
					current.Revocation = pkt
 | 
						|
				}
 | 
						|
			} else if pkt.SigType == packet.SigTypeDirectSignature {
 | 
						|
				if err = e.PrimaryKey.VerifyRevocationSignature(e.PrimaryKey, pkt); err == nil {
 | 
						|
					if desig := pkt.DesignatedRevoker; desig != nil {
 | 
						|
						// If it's a designated revoker signature, take last 8 octects
 | 
						|
						// of fingerprint as Key ID and save it to designatedRevokers
 | 
						|
						// map. We consult this map later to see if a foreign
 | 
						|
						// revocation should be added to UnverifiedRevocations.
 | 
						|
						keyID := binary.BigEndian.Uint64(desig.Fingerprint[len(desig.Fingerprint)-8:])
 | 
						|
						designatedRevokers[keyID] = true
 | 
						|
					}
 | 
						|
				}
 | 
						|
			} else if current == nil {
 | 
						|
				// NOTE(maxtaco)
 | 
						|
				//
 | 
						|
				// See https://github.com/keybase/client/issues/2666
 | 
						|
				//
 | 
						|
				// There might have been a user attribute picture before this signature,
 | 
						|
				// in which case this is still a valid PGP key. In the future we might
 | 
						|
				// not ignore user attributes (like picture). But either way, it doesn't
 | 
						|
				// make sense to bail out here. Keep looking for other valid signatures.
 | 
						|
				//
 | 
						|
				// Used to be:
 | 
						|
				//    return nil, errors.StructuralError("signature packet found before user id packet")
 | 
						|
			} else {
 | 
						|
				current.Signatures = append(current.Signatures, pkt)
 | 
						|
			}
 | 
						|
		case *packet.PrivateKey:
 | 
						|
			if pkt.IsSubkey == false {
 | 
						|
				packets.Unread(p)
 | 
						|
				break EachPacket
 | 
						|
			}
 | 
						|
			err = addSubkey(e, packets, &pkt.PublicKey, pkt)
 | 
						|
			if err != nil {
 | 
						|
				return nil, err
 | 
						|
			}
 | 
						|
		case *packet.PublicKey:
 | 
						|
			if pkt.IsSubkey == false {
 | 
						|
				packets.Unread(p)
 | 
						|
				break EachPacket
 | 
						|
			}
 | 
						|
			err = addSubkey(e, packets, pkt, nil)
 | 
						|
			if err != nil {
 | 
						|
				return nil, err
 | 
						|
			}
 | 
						|
		default:
 | 
						|
			// we ignore unknown packets
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if len(e.Identities) == 0 {
 | 
						|
		return nil, errors.StructuralError("entity without any identities")
 | 
						|
	}
 | 
						|
 | 
						|
	for _, revocation := range revocations {
 | 
						|
		if revocation.IssuerKeyId == nil || *revocation.IssuerKeyId == e.PrimaryKey.KeyId {
 | 
						|
			// Key revokes itself, something that we can verify.
 | 
						|
			err = e.PrimaryKey.VerifyRevocationSignature(e.PrimaryKey, revocation)
 | 
						|
			if err == nil {
 | 
						|
				e.Revocations = append(e.Revocations, revocation)
 | 
						|
			} else {
 | 
						|
				return nil, errors.StructuralError("revocation signature signed by alternate key")
 | 
						|
			}
 | 
						|
		} else if revocation.IssuerKeyId != nil {
 | 
						|
			if _, ok := designatedRevokers[*revocation.IssuerKeyId]; ok {
 | 
						|
				// Revocation is done by certified designated revoker,
 | 
						|
				// but we can't verify the revocation.
 | 
						|
				e.UnverifiedRevocations = append(e.UnverifiedRevocations, revocation)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return e, nil
 | 
						|
}
 | 
						|
 | 
						|
func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
 | 
						|
	var subKey Subkey
 | 
						|
	subKey.PublicKey = pub
 | 
						|
	subKey.PrivateKey = priv
 | 
						|
	var lastErr error
 | 
						|
	for {
 | 
						|
		p, err := packets.Next()
 | 
						|
		if err == io.EOF {
 | 
						|
			break
 | 
						|
		}
 | 
						|
		if err != nil {
 | 
						|
			return errors.StructuralError("subkey signature invalid: " + err.Error())
 | 
						|
		}
 | 
						|
		sig, ok := p.(*packet.Signature)
 | 
						|
		if !ok {
 | 
						|
			// Hit a non-signature packet, so assume we're up to the next key
 | 
						|
			packets.Unread(p)
 | 
						|
			break
 | 
						|
		}
 | 
						|
		if st := sig.SigType; st != packet.SigTypeSubkeyBinding && st != packet.SigTypeSubkeyRevocation {
 | 
						|
 | 
						|
			// Note(maxtaco):
 | 
						|
			// We used to error out here, but instead, let's fast-forward past
 | 
						|
			// packets that are in the wrong place (like misplaced 0x13 signatures)
 | 
						|
			// until we get to one that works.  For a test case,
 | 
						|
			// see TestWithBadSubkeySignaturePackets.
 | 
						|
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig)
 | 
						|
		if err != nil {
 | 
						|
			// Non valid signature, so again, no need to abandon all hope, just continue;
 | 
						|
			// make a note of the error we hit.
 | 
						|
			lastErr = errors.StructuralError("subkey signature invalid: " + err.Error())
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		switch sig.SigType {
 | 
						|
		case packet.SigTypeSubkeyBinding:
 | 
						|
			// Does the "new" sig set expiration to later date than
 | 
						|
			// "previous" sig?
 | 
						|
			if subKey.Sig == nil || subKey.Sig.ExpiresBeforeOther(sig) {
 | 
						|
				subKey.Sig = sig
 | 
						|
			}
 | 
						|
		case packet.SigTypeSubkeyRevocation:
 | 
						|
			// First writer wins
 | 
						|
			if subKey.Revocation == nil {
 | 
						|
				subKey.Revocation = sig
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if subKey.Sig != nil {
 | 
						|
		e.Subkeys = append(e.Subkeys, subKey)
 | 
						|
	} else {
 | 
						|
		if lastErr == nil {
 | 
						|
			lastErr = errors.StructuralError("Subkey wasn't signed; expected a 'binding' signature")
 | 
						|
		}
 | 
						|
		e.BadSubkeys = append(e.BadSubkeys, BadSubkey{Subkey: subKey, Err: lastErr})
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
const defaultRSAKeyBits = 2048
 | 
						|
 | 
						|
// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
 | 
						|
// single identity composed of the given full name, comment and email, any of
 | 
						|
// which may be empty but must not contain any of "()<>\x00".
 | 
						|
// If config is nil, sensible defaults will be used.
 | 
						|
func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
 | 
						|
	currentTime := config.Now()
 | 
						|
 | 
						|
	bits := defaultRSAKeyBits
 | 
						|
	if config != nil && config.RSABits != 0 {
 | 
						|
		bits = config.RSABits
 | 
						|
	}
 | 
						|
 | 
						|
	uid := packet.NewUserId(name, comment, email)
 | 
						|
	if uid == nil {
 | 
						|
		return nil, errors.InvalidArgumentError("user id field contained invalid characters")
 | 
						|
	}
 | 
						|
	signingPriv, err := rsa.GenerateKey(config.Random(), bits)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	encryptingPriv, err := rsa.GenerateKey(config.Random(), bits)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	e := &Entity{
 | 
						|
		PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
 | 
						|
		PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
 | 
						|
		Identities: make(map[string]*Identity),
 | 
						|
	}
 | 
						|
	isPrimaryId := true
 | 
						|
	e.Identities[uid.Id] = &Identity{
 | 
						|
		Name:   uid.Name,
 | 
						|
		UserId: uid,
 | 
						|
		SelfSignature: &packet.Signature{
 | 
						|
			CreationTime: currentTime,
 | 
						|
			SigType:      packet.SigTypePositiveCert,
 | 
						|
			PubKeyAlgo:   packet.PubKeyAlgoRSA,
 | 
						|
			Hash:         config.Hash(),
 | 
						|
			IsPrimaryId:  &isPrimaryId,
 | 
						|
			FlagsValid:   true,
 | 
						|
			FlagSign:     true,
 | 
						|
			FlagCertify:  true,
 | 
						|
			IssuerKeyId:  &e.PrimaryKey.KeyId,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	e.Subkeys = make([]Subkey, 1)
 | 
						|
	e.Subkeys[0] = Subkey{
 | 
						|
		PublicKey:  packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
 | 
						|
		PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
 | 
						|
		Sig: &packet.Signature{
 | 
						|
			CreationTime:              currentTime,
 | 
						|
			SigType:                   packet.SigTypeSubkeyBinding,
 | 
						|
			PubKeyAlgo:                packet.PubKeyAlgoRSA,
 | 
						|
			Hash:                      config.Hash(),
 | 
						|
			FlagsValid:                true,
 | 
						|
			FlagEncryptStorage:        true,
 | 
						|
			FlagEncryptCommunications: true,
 | 
						|
			IssuerKeyId:               &e.PrimaryKey.KeyId,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	e.Subkeys[0].PublicKey.IsSubkey = true
 | 
						|
	e.Subkeys[0].PrivateKey.IsSubkey = true
 | 
						|
 | 
						|
	return e, nil
 | 
						|
}
 | 
						|
 | 
						|
// SerializePrivate serializes an Entity, including private key material, to
 | 
						|
// the given Writer. For now, it must only be used on an Entity returned from
 | 
						|
// NewEntity.
 | 
						|
// If config is nil, sensible defaults will be used.
 | 
						|
func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
 | 
						|
	err = e.PrivateKey.Serialize(w)
 | 
						|
	if err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	for _, ident := range e.Identities {
 | 
						|
		err = ident.UserId.Serialize(w)
 | 
						|
		if err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		if e.PrivateKey.PrivateKey != nil {
 | 
						|
			err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
 | 
						|
			if err != nil {
 | 
						|
				return
 | 
						|
			}
 | 
						|
		}
 | 
						|
		err = ident.SelfSignature.Serialize(w)
 | 
						|
		if err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
	for _, subkey := range e.Subkeys {
 | 
						|
		err = subkey.PrivateKey.Serialize(w)
 | 
						|
		if err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		// Workaround shortcoming of SignKey(), which doesn't work to reverse-sign
 | 
						|
		// sub-signing keys. So if requested, just reuse the signatures already
 | 
						|
		// available to us (if we read this key from a keyring).
 | 
						|
		if e.PrivateKey.PrivateKey != nil && !config.ReuseSignatures() {
 | 
						|
			err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
 | 
						|
			if err != nil {
 | 
						|
				return
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if subkey.Revocation != nil {
 | 
						|
			err = subkey.Revocation.Serialize(w)
 | 
						|
			if err != nil {
 | 
						|
				return
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		err = subkey.Sig.Serialize(w)
 | 
						|
		if err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Serialize writes the public part of the given Entity to w. (No private
 | 
						|
// key material will be output).
 | 
						|
func (e *Entity) Serialize(w io.Writer) error {
 | 
						|
	err := e.PrimaryKey.Serialize(w)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	for _, ident := range e.Identities {
 | 
						|
		err = ident.UserId.Serialize(w)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		err = ident.SelfSignature.Serialize(w)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		for _, sig := range ident.Signatures {
 | 
						|
			err = sig.Serialize(w)
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	for _, subkey := range e.Subkeys {
 | 
						|
		err = subkey.PublicKey.Serialize(w)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		if subkey.Revocation != nil {
 | 
						|
			err = subkey.Revocation.Serialize(w)
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
		}
 | 
						|
		err = subkey.Sig.Serialize(w)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// SignIdentity adds a signature to e, from signer, attesting that identity is
 | 
						|
// associated with e. The provided identity must already be an element of
 | 
						|
// e.Identities and the private key of signer must have been decrypted if
 | 
						|
// necessary.
 | 
						|
// If config is nil, sensible defaults will be used.
 | 
						|
func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
 | 
						|
	if signer.PrivateKey == nil {
 | 
						|
		return errors.InvalidArgumentError("signing Entity must have a private key")
 | 
						|
	}
 | 
						|
	if signer.PrivateKey.Encrypted {
 | 
						|
		return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
 | 
						|
	}
 | 
						|
	ident, ok := e.Identities[identity]
 | 
						|
	if !ok {
 | 
						|
		return errors.InvalidArgumentError("given identity string not found in Entity")
 | 
						|
	}
 | 
						|
 | 
						|
	sig := &packet.Signature{
 | 
						|
		SigType:      packet.SigTypeGenericCert,
 | 
						|
		PubKeyAlgo:   signer.PrivateKey.PubKeyAlgo,
 | 
						|
		Hash:         config.Hash(),
 | 
						|
		CreationTime: config.Now(),
 | 
						|
		IssuerKeyId:  &signer.PrivateKey.KeyId,
 | 
						|
	}
 | 
						|
	if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	ident.Signatures = append(ident.Signatures, sig)
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// CopySubkeyRevocations copies subkey revocations from the src Entity over
 | 
						|
// to the receiver entity. We need this because `gpg --export-secret-key` does
 | 
						|
// not appear to output subkey revocations.  In this case we need to manually
 | 
						|
// merge with the output of `gpg --export`.
 | 
						|
func (e *Entity) CopySubkeyRevocations(src *Entity) {
 | 
						|
	m := make(map[[20]byte]*packet.Signature)
 | 
						|
	for _, subkey := range src.Subkeys {
 | 
						|
		if subkey.Revocation != nil {
 | 
						|
			m[subkey.PublicKey.Fingerprint] = subkey.Revocation
 | 
						|
		}
 | 
						|
	}
 | 
						|
	for i, subkey := range e.Subkeys {
 | 
						|
		if r := m[subkey.PublicKey.Fingerprint]; r != nil {
 | 
						|
			e.Subkeys[i].Revocation = r
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// CheckDesignatedRevokers will try to confirm any of designated
 | 
						|
// revocation of entity. For this function to work, revocation
 | 
						|
// issuer's key should be found in keyring. First successfully
 | 
						|
// verified designated revocation is returned along with the key that
 | 
						|
// verified it.
 | 
						|
func FindVerifiedDesignatedRevoke(keyring KeyRing, entity *Entity) (*packet.Signature, *Key) {
 | 
						|
	for _, sig := range entity.UnverifiedRevocations {
 | 
						|
		if sig.IssuerKeyId == nil {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		issuerKeyId := *sig.IssuerKeyId
 | 
						|
		issuerFingerprint := sig.IssuerFingerprint
 | 
						|
		keys := keyring.KeysByIdUsage(issuerKeyId, issuerFingerprint, packet.KeyFlagSign)
 | 
						|
		if len(keys) == 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		for _, key := range keys {
 | 
						|
			err := key.PublicKey.VerifyRevocationSignature(entity.PrimaryKey, sig)
 | 
						|
			if err == nil {
 | 
						|
				return sig, &key
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil, nil
 | 
						|
}
 |