From 34f69633bfdcf9db92f698f8487115767eebef81 Mon Sep 17 00:00:00 2001 From: Scott Ragan Date: Wed, 2 Oct 2019 19:15:13 +0000 Subject: [PATCH] openpgp/packet: support crypto.Decrypter in EncryptedKey.Decrypt Fixes golang/go#33301 Change-Id: I74a389367d34d4718d70349794027ed9f1eca370 GitHub-Last-Rev: 6d95cdf63248a54b134027ed49641c204187f188 GitHub-Pull-Request: golang/crypto#94 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/189497 Reviewed-by: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Gobot Gobot --- openpgp/packet/encrypted_key.go | 6 ++- openpgp/packet/encrypted_key_test.go | 69 ++++++++++++++++++++++++++++ openpgp/packet/private_key.go | 2 +- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/openpgp/packet/encrypted_key.go b/openpgp/packet/encrypted_key.go index 02b372c..6d76397 100644 --- a/openpgp/packet/encrypted_key.go +++ b/openpgp/packet/encrypted_key.go @@ -5,6 +5,7 @@ package packet import ( + "crypto" "crypto/rsa" "encoding/binary" "io" @@ -78,8 +79,9 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { // padding oracle attacks. switch priv.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - k := priv.PrivateKey.(*rsa.PrivateKey) - b, err = rsa.DecryptPKCS1v15(config.Random(), k, padToKeySize(&k.PublicKey, e.encryptedMPI1.bytes)) + // Supports both *rsa.PrivateKey and crypto.Decrypter + k := priv.PrivateKey.(crypto.Decrypter) + b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil) case PubKeyAlgoElGamal: c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) diff --git a/openpgp/packet/encrypted_key_test.go b/openpgp/packet/encrypted_key_test.go index f2fcf4d..ecb22bc 100644 --- a/openpgp/packet/encrypted_key_test.go +++ b/openpgp/packet/encrypted_key_test.go @@ -6,9 +6,11 @@ package packet import ( "bytes" + "crypto" "crypto/rsa" "encoding/hex" "fmt" + "io" "math/big" "testing" ) @@ -80,6 +82,73 @@ func TestDecryptingEncryptedKey(t *testing.T) { } } +type rsaDecrypter struct { + rsaPrivateKey *rsa.PrivateKey + decryptCount int +} + +func (r *rsaDecrypter) Public() crypto.PublicKey { + return &r.rsaPrivateKey.PublicKey +} + +func (r *rsaDecrypter) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) { + r.decryptCount++ + return r.rsaPrivateKey.Decrypt(rand, msg, opts) +} + +func TestRSADecrypter(t *testing.T) { + const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" + + const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" + + p, err := Read(readerFromHex(encryptedKeyHex)) + if err != nil { + t.Errorf("error from Read: %s", err) + return + } + ek, ok := p.(*EncryptedKey) + if !ok { + t.Errorf("didn't parse an EncryptedKey, got %#v", p) + return + } + + if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + customDecrypter := &rsaDecrypter{ + rsaPrivateKey: encryptedKeyRSAPriv, + } + + customKeyPriv := &PrivateKey{ + PublicKey: PublicKey{ + PubKeyAlgo: PubKeyAlgoRSA, + }, + PrivateKey: customDecrypter, + } + + err = ek.Decrypt(customKeyPriv, nil) + if err != nil { + t.Errorf("error from Decrypt: %s", err) + return + } + + if ek.CipherFunc != CipherAES256 { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + keyHex := fmt.Sprintf("%x", ek.Key) + if keyHex != expectedKeyHex { + t.Errorf("bad key, got %s want %s", keyHex, expectedKeyHex) + } + + if customDecrypter.decryptCount != 1 { + t.Errorf("Expected customDecrypter.Decrypt() to be called 1 time, but was called %d times", customDecrypter.decryptCount) + } +} + func TestEncryptingEncryptedKey(t *testing.T) { key := []byte{1, 2, 3, 4} const expectedKeyHex = "01020304" diff --git a/openpgp/packet/private_key.go b/openpgp/packet/private_key.go index 6f8ec09..81abb7c 100644 --- a/openpgp/packet/private_key.go +++ b/openpgp/packet/private_key.go @@ -31,7 +31,7 @@ type PrivateKey struct { encryptedData []byte cipher CipherFunction s2k func(out, in []byte) - PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer. + PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or crypto.Signer/crypto.Decrypter (Decryptor RSA only). sha1Checksum bool iv []byte }