From 7550fb715419e2d1ceac0539571ab3c75720f560 Mon Sep 17 00:00:00 2001 From: Paul M Furley Date: Tue, 4 Sep 2018 14:12:16 +0100 Subject: [PATCH 1/3] Write out reason for revocation subpacket When building subpackets for a Signature, ensure a "reason for revocation" subpacket is added if the Signature is a SigTypeKeyRevocation. See https://tools.ietf.org/html/rfc4880#section-5.2.3.23 --- openpgp/packet/signature.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/openpgp/packet/signature.go b/openpgp/packet/signature.go index 82760aa55a..aed7b83df6 100644 --- a/openpgp/packet/signature.go +++ b/openpgp/packet/signature.go @@ -727,5 +727,21 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) } + if sig.SigType == SigTypeKeyRevocation { + reasonForRevData := bytes.NewBuffer(nil) + reasonForRevData.Write([]byte{*sig.RevocationReason}) + reasonForRevData.Write([]byte(sig.RevocationReasonText)) + + subpackets = append( + subpackets, + outputSubpacket{ + hashed: true, + subpacketType: reasonForRevocationSubpacket, + isCritical: false, + contents: reasonForRevData.Bytes(), + }, + ) + } + return } From 891bd1d051bedd34c5af0f014288345ca4d19fe4 Mon Sep 17 00:00:00 2001 From: Paul M Furley Date: Thu, 13 Sep 2018 18:29:43 +0100 Subject: [PATCH 2/3] openpgp: use latest subkey binding signature Rather than using the *first* subkey binding signature encountered, use the one with the most recent creation data, as per the recommendation from RFC 4880: > An implementation that encounters multiple self-signatures on the > same object may resolve the ambiguity in any way it sees fit, but it > is RECOMMENDED that priority be given to the most recent self- > signature. This allows subkeys to approach expiry then be re-signed with a new expiry. --- openpgp/keys.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/openpgp/keys.go b/openpgp/keys.go index f9ece14408..3bb05ea4d5 100644 --- a/openpgp/keys.go +++ b/openpgp/keys.go @@ -457,7 +457,8 @@ func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *p case packet.SigTypeSubkeyRevocation: subKey.Sig = sig case packet.SigTypeSubkeyBinding: - if subKey.Sig == nil { + + if shouldReplaceSubkeySig(subKey.Sig, sig) { subKey.Sig = sig } } @@ -472,6 +473,22 @@ func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *p return nil } +func shouldReplaceSubkeySig(existingSig, potentialNewSig *packet.Signature) bool { + if potentialNewSig == nil { + return false + } + + if existingSig == nil { + return true + } + + if existingSig.SigType == packet.SigTypeSubkeyRevocation { + return false // never override a revocation signature + } + + return potentialNewSig.CreationTime.After(existingSig.CreationTime) +} + const defaultRSAKeyBits = 2048 // NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a From 896d0cfbdb359f2626629cec48285cc75ad7df13 Mon Sep 17 00:00:00 2001 From: Ian Drysdale Date: Wed, 19 Dec 2018 09:42:42 +0000 Subject: [PATCH 3/3] make stringToKeySpecifier a real type rather than type alias. --- openpgp/s2k/s2k.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpgp/s2k/s2k.go b/openpgp/s2k/s2k.go index bc78639ddf..8ab79bb7e0 100644 --- a/openpgp/s2k/s2k.go +++ b/openpgp/s2k/s2k.go @@ -15,7 +15,7 @@ import ( "github.com/fluidkeys/crypto/openpgp/errors" ) -type stringToKeySpecifier = uint8 +type stringToKeySpecifier uint8 const ( S2KCountMin = 1024 @@ -192,7 +192,7 @@ func Parse(r io.Reader) (f func(out, in []byte), err error) { } h := hash.New() - switch buf[0] { + switch stringToKeySpecifier(buf[0]) { case SimpleS2K: f := func(out, in []byte) { Simple(out, h, in) @@ -228,7 +228,7 @@ func Parse(r io.Reader) (f func(out, in []byte), err error) { // nil. In that case, sensible defaults will be used. func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { var buf [11]byte - buf[0] = IteratedAndSaltedS2K + buf[0] = byte(IteratedAndSaltedS2K) buf[1], _ = HashToHashId(c.hash()) salt := buf[2:10] if _, err := io.ReadFull(rand, salt); err != nil {