diff --git a/crypto/interop_test.go b/crypto/interop_test.go index 1e7f36c3..906a37c8 100644 --- a/crypto/interop_test.go +++ b/crypto/interop_test.go @@ -2,6 +2,9 @@ package crypto import ( "bytes" + "encoding/hex" + "errors" + "io" "testing" "github.com/ProtonMail/gopenpgp/v3/internal" @@ -567,3 +570,41 @@ V6Zkmvzj3h9CucLSJw1Bo6ZJTDbkBQ== t.Error("Should have signature error", err) } } + +func TestVerificationReaderEOFBehaviour(t *testing.T) { + // Rust code translation into Go equivalent + + sessionKeyHex := "b399a07cb400e5a3dcf4e5ae2ba9beb05b1144b729df4abe486fcdb8e95277c5" + sessionKeyBytes, err := hex.DecodeString(sessionKeyHex) + if err != nil { + t.Fatalf("failed to decode session key hex: %v", err) + } + sessionKey := NewSessionKeyFromToken(sessionKeyBytes, "aes256") + + message := `-----BEGIN PGP MESSAGE----- + +wV4DJ7OpFgpxLJYSAQdAII/74N5Q0EOBuLJ2We6+Hv+TfZg8DF3TYiwAPSFwQkYw +eYK2eKI17tlam9OxT1LvlKz7f5pH+FwNbGGc4At3zgQ4Gr+Z9i+DIjqvZhTcopdF +0kEBRT4owwJHSFIYST1PFH3qibR1lOxepjJCNk0rLjeDvf72Q2TkS2usZyYmLpTp +9RsNnMXgzflSajabRXiTYFunag== +=CTgA +-----END PGP MESSAGE-----` + pgp := PGP() + decryptor, err := pgp.Decryption().SessionKey(sessionKey).New() + if err != nil { + t.Fatalf("failed to create decryptor: %v", err) + } + reader, err := decryptor.DecryptingReader(bytes.NewReader([]byte(message)), Armor) + if err != nil { + t.Fatalf("failed to create decryptor: %v", err) + } + _, err = reader.ReadAll() + if err != nil { + t.Fatalf("failed to read plaintext: %v", err) + } + + _, err = reader.Read(make([]byte, 16)) + if !errors.Is(err, io.EOF) { + t.Fatalf("expected EOF, got %v", err) + } +} diff --git a/crypto/verify_reader.go b/crypto/verify_reader.go index 9ec2a955..f1f28ee9 100644 --- a/crypto/verify_reader.go +++ b/crypto/verify_reader.go @@ -38,6 +38,9 @@ func (msg *VerifyDataReader) GetMetadata() *LiteralMetadata { // Read is used read data from the pgp message. // Makes VerifyDataReader implement the Reader interface. func (msg *VerifyDataReader) Read(b []byte) (n int, err error) { + if msg.readAll { + return 0, io.EOF + } n, err = msg.internalReader.Read(b) if errors.Is(err, io.EOF) { msg.readAll = true