mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-14 23:17:15 +00:00
961c878e0d
Switch to using Go modules. This migrates our vendor.json to use Go 1.11's modules system, and replaces the vendor folder with the output of go mod vendor. The vendored code should remain basically the same; I believe some tree shaking of packages and support scripts/licenses/READMEs/etc. happened. This also fixes Travis and our Makefile to no longer use govendor.
935 lines
29 KiB
Go
935 lines
29 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, non-revoked key that can
|
|
// encrypt.
|
|
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
|
|
|
|
// Iterate the keys to find the newest, non-revoked key that can
|
|
// sign.
|
|
var maxTime time.Time
|
|
for i, subkey := range e.Subkeys {
|
|
if (!subkey.Sig.FlagsValid || subkey.Sig.FlagSign) &&
|
|
subkey.PrivateKey.PrivateKey != nil &&
|
|
subkey.PublicKey.PubKeyAlgo.CanSign() &&
|
|
!subkey.Sig.KeyExpired(now) &&
|
|
subkey.Revocation == nil &&
|
|
(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
|
|
candidateSubkey = i
|
|
maxTime = subkey.Sig.CreationTime
|
|
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 identities 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 {
|
|
if err := subKey.PublicKey.ErrorIfDeprecated(); err != nil {
|
|
// Key passed signature check but is deprecated.
|
|
subKey.Sig = nil
|
|
lastErr = err
|
|
}
|
|
}
|
|
|
|
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.Id,
|
|
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,
|
|
},
|
|
}
|
|
|
|
// If the user passes in a DefaultHash via packet.Config, set the
|
|
// PreferredHash for the SelfSignature.
|
|
if config != nil && config.DefaultHash != 0 {
|
|
e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)}
|
|
}
|
|
|
|
// Likewise for DefaultCipher.
|
|
if config != nil && config.DefaultCipher != 0 {
|
|
e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)}
|
|
}
|
|
|
|
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
|
|
}
|
|
if e.PrivateKey.PrivateKey != nil && !config.ReuseSignatures() {
|
|
// If not reusing existing signatures, sign subkey using private key
|
|
// (subkey binding), but also sign primary key using subkey (primary
|
|
// key binding) if subkey is used for signing.
|
|
if subkey.Sig.FlagSign {
|
|
err = subkey.Sig.CrossSignKey(e.PrimaryKey, subkey.PrivateKey, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
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
|
|
}
|