diff --git a/CHANGELOG.md b/CHANGELOG.md index aaa2143..e1f5b2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Changed +- Session key decryption now considers multiple key packets + + ## [2.1.0] 2020-11-04 ### Security - Updated underlying crypto library diff --git a/crypto/keyring_session.go b/crypto/keyring_session.go index 1f0a2b4..0a61dbb 100644 --- a/crypto/keyring_session.go +++ b/crypto/keyring_session.go @@ -9,28 +9,53 @@ import ( "golang.org/x/crypto/openpgp/packet" ) -// DecryptSessionKey returns the decrypted session key from a binary encrypted session key packet. +// DecryptSessionKey returns the decrypted session key from one or multiple binary encrypted session key packets. func (keyRing *KeyRing) DecryptSessionKey(keyPacket []byte) (*SessionKey, error) { + var p packet.Packet + var ek *packet.EncryptedKey + + var err error + var hasPacket = false + var decryptErr error + keyReader := bytes.NewReader(keyPacket) packets := packet.NewReader(keyReader) - var p packet.Packet - var err error - if p, err = packets.Next(); err != nil { - return nil, errors.Wrap(err, "gopenpgp: error in reading packets") - } - - ek := p.(*packet.EncryptedKey) - var decryptErr error - for _, key := range keyRing.entities.DecryptionKeys() { - priv := key.PrivateKey - if priv.Encrypted { - continue - } - - if decryptErr = ek.Decrypt(priv, nil); decryptErr == nil { +Loop: + for { + if p, err = packets.Next(); err != nil { break } + + switch p := p.(type) { + case *packet.EncryptedKey: + hasPacket = true + ek = p + + for _, key := range keyRing.entities.DecryptionKeys() { + priv := key.PrivateKey + if priv.Encrypted { + continue + } + + if decryptErr = ek.Decrypt(priv, nil); decryptErr == nil { + break Loop + } + } + + case *packet.SymmetricallyEncrypted, + *packet.AEADEncrypted, + *packet.Compressed, + *packet.LiteralData: + break Loop + + default: + continue Loop + } + } + + if !hasPacket { + return nil, errors.Wrap(err, "gopenpgp: couldn't find a session key packet that could be decrypted") } if decryptErr != nil { diff --git a/crypto/sessionkey_test.go b/crypto/sessionkey_test.go index 2c4aaa8..90ea9bf 100644 --- a/crypto/sessionkey_test.go +++ b/crypto/sessionkey_test.go @@ -51,7 +51,7 @@ func TestMultipleAsymmetricKeyPacket(t *testing.T) { } // Password defined in keyring_test - outputSymmetricKey, err := keyRingTestMultiple.DecryptSessionKey(keyPacket) + outputSymmetricKey, err := keyRingTestPrivate.DecryptSessionKey(keyPacket) if err != nil { t.Fatal("Expected no error while decrypting key packet, got:", err) }