crypto/openpgp: select newest valid encryption subkey
Change-Id: I5ae662e95d9f0f0cbcbf0b15b6c7c52c51521cca
Reviewed-on: https://go-review.googlesource.com/8726
Reviewed-by: Adam Langley <agl@golang.org>
diff --git a/openpgp/keys.go b/openpgp/keys.go
index c4a6640..fe12cfa 100644
--- a/openpgp/keys.go
+++ b/openpgp/keys.go
@@ -6,11 +6,12 @@
import (
"crypto/rsa"
+ "io"
+ "time"
+
"golang.org/x/crypto/openpgp/armor"
"golang.org/x/crypto/openpgp/errors"
"golang.org/x/crypto/openpgp/packet"
- "io"
- "time"
)
// PublicKeyType is the armor type for a PGP public key.
@@ -90,13 +91,16 @@
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 {
if subkey.Sig.FlagsValid &&
subkey.Sig.FlagEncryptCommunications &&
subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
- !subkey.Sig.KeyExpired(now) {
+ !subkey.Sig.KeyExpired(now) &&
+ (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
candidateSubkey = i
- break
+ maxTime = subkey.Sig.CreationTime
}
}
diff --git a/openpgp/keys_test.go b/openpgp/keys_test.go
index e0625cb..32c78f2 100644
--- a/openpgp/keys_test.go
+++ b/openpgp/keys_test.go
@@ -13,15 +13,16 @@
const timeFormat = "2006-01-02"
time1, _ := time.Parse(timeFormat, "2013-07-01")
+
// The expiringKeyHex key is structured as:
//
- // pub 1024R/5E237D8C created: 2013-07-01 expires: 2013-07-31 usage: SC
- // sub 1024R/1ABB25A0 created: 2013-07-01 expires: 2013-07-08 usage: E
- // sub 1024R/96A672F5 created: 2013-07-01 expires: 2013-07-31 usage: E
+ // pub 1024R/5E237D8C created: 2013-07-01 expires: 2013-07-31 usage: SC
+ // sub 1024R/1ABB25A0 created: 2013-07-01 23:11:07 +0200 CEST expires: 2013-07-08 usage: E
+ // sub 1024R/96A672F5 created: 2013-07-01 23:11:23 +0200 CEST expires: 2013-07-31 usage: E
//
- // So this should select the first, non-expired encryption key.
+ // So this should select the newest, non-expired encryption key.
key, _ := entity.encryptionKey(time1)
- if id := key.PublicKey.KeyIdShortString(); id != "1ABB25A0" {
+ if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" {
t.Errorf("Expected key 1ABB25A0 at time %s, but got key %s", time1.Format(timeFormat), id)
}