From 175ef4df7f84fa58eff5d1a2b01b50e8af885d67 Mon Sep 17 00:00:00 2001 From: Dj Gilcrease Date: Wed, 7 Apr 2021 09:39:45 -0700 Subject: [PATCH] feat: Allow setting the SigningKeyId to use --- openpgp/keys.go | 11 ++++++++--- openpgp/packet/config.go | 9 +++++++++ openpgp/write.go | 6 +++--- openpgp/write_test.go | 6 +++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/openpgp/keys.go b/openpgp/keys.go index b30315c447..8581db8a2c 100644 --- a/openpgp/keys.go +++ b/openpgp/keys.go @@ -170,7 +170,12 @@ func (e *Entity) encryptionKey(now time.Time) (Key, bool) { // signingKey return the best candidate Key for signing a message with this // Entity. -func (e *Entity) signingKey(now time.Time) (Key, bool) { +func (e *Entity) signingKey(now time.Time, id uint64) (Key, bool) { + i := e.primaryIdentity() + // If the id specified is the Entity.PrivateKey.KeyID lets skip looking at the subkeys + if e.PrivateKey != nil && e.PrivateKey.KeyId == id { + return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, i.SelfSignature.GetKeyFlags()}, true + } candidateSubkey := -1 // Iterate the keys to find the newest, non-revoked key that can @@ -182,7 +187,8 @@ func (e *Entity) signingKey(now time.Time) (Key, bool) { subkey.PublicKey.PubKeyAlgo.CanSign() && !subkey.Sig.KeyExpired(now) && subkey.Revocation == nil && - (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { + (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) && + (id == 0 || subkey.PrivateKey.KeyId == id) { candidateSubkey = i maxTime = subkey.Sig.CreationTime break @@ -196,7 +202,6 @@ func (e *Entity) signingKey(now time.Time) (Key, bool) { // 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) && diff --git a/openpgp/packet/config.go b/openpgp/packet/config.go index f4125e189d..c5c5cffba0 100644 --- a/openpgp/packet/config.go +++ b/openpgp/packet/config.go @@ -49,6 +49,8 @@ type Config struct { // ReuseSignatures tells us to reuse existing Signatures // on serialized output. ReuseSignaturesOnSerialize bool + // SigningKeyId specify signing key id to use, if not set defaults to best guess on subkeys. + SigningKeyId uint64 } func (c *Config) Random() io.Reader { @@ -96,3 +98,10 @@ func (c *Config) PasswordHashIterations() int { func (c *Config) ReuseSignatures() bool { return c != nil && c.ReuseSignaturesOnSerialize } + +func (c *Config) SigningKey() uint64 { + if c == nil { + return 0 + } + return c.SigningKeyId +} \ No newline at end of file diff --git a/openpgp/write.go b/openpgp/write.go index 14b2f757e9..29df69ee0c 100644 --- a/openpgp/write.go +++ b/openpgp/write.go @@ -92,7 +92,7 @@ func SignWithSigner(s packet.Signer, w io.Writer, message io.Reader, sigType pac } func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { - signerSubkey, ok := signer.signingKey(config.Now()) + signerSubkey, ok := signer.signingKey(config.Now(), config.SigningKey()) if !ok { err = errors.InvalidArgumentError("no valid signing keys") return @@ -209,7 +209,7 @@ func hashToHashId(h crypto.Hash) uint8 { func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { var signer *packet.PrivateKey if signed != nil { - signKey, ok := signed.signingKey(config.Now()) + signKey, ok := signed.signingKey(config.Now(), config.SigningKey()) if !ok { return nil, errors.InvalidArgumentError("no valid signing keys") } @@ -443,7 +443,7 @@ func AttachedSign(out io.WriteCloser, signed Entity, hints *FileHints, var signer *packet.PrivateKey - signKey, ok := signed.signingKey(config.Now()) + signKey, ok := signed.signingKey(config.Now(), config.SigningKey()) if !ok { err = errors.InvalidArgumentError("no valid signing keys") return diff --git a/openpgp/write_test.go b/openpgp/write_test.go index 05f4e2ae30..10a9cd9cc5 100644 --- a/openpgp/write_test.go +++ b/openpgp/write_test.go @@ -89,7 +89,7 @@ func TestSignWithSigner(t *testing.T) { t.Error(err) } - signerSubkey, ok := kring[0].signingKey(time.Now()) + signerSubkey, ok := kring[0].signingKey(time.Now(), 0) if !ok { t.Error("couldn't get signer subkey") } @@ -133,7 +133,7 @@ func TestSignerCanReturnErrors(t *testing.T) { t.Error(err) } - signerSubkey, ok := kring[0].signingKey(time.Now()) + signerSubkey, ok := kring[0].signingKey(time.Now(), 0) if !ok { t.Error("couldn't get signer subkey") } @@ -333,7 +333,7 @@ func TestEncryption(t *testing.T) { testTime, _ := time.Parse("2006-01-02", "2013-07-01") if test.isSigned { - signKey, _ := kring[0].signingKey(testTime) + signKey, _ := kring[0].signingKey(testTime, 0) expectedKeyId := signKey.PublicKey.KeyId if md.SignedByKeyId != expectedKeyId { t.Errorf("#%d: message signed by wrong key id, got: %d, want: %d", i, md.SignedByKeyId, expectedKeyId)