From fdb936ee95d09b1b98418735a813deba6770ad5a Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 9 Feb 2016 20:05:49 +0100 Subject: [PATCH] crypto/ecies: make authenticated shared data work The s2 parameter was not actually written to the MAC. --- crypto/ecies/ecies.go | 12 ++++++------ crypto/ecies/ecies_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/crypto/ecies/ecies.go b/crypto/ecies/ecies.go index 65dc5b38ba..ee42856173 100644 --- a/crypto/ecies/ecies.go +++ b/crypto/ecies/ecies.go @@ -192,11 +192,9 @@ func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) { // messageTag computes the MAC of a message (called the tag) as per // SEC 1, 3.5. func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte { - if shared == nil { - shared = make([]byte, 0) - } mac := hmac.New(hash, km) mac.Write(msg) + mac.Write(shared) tag := mac.Sum(nil) return tag } @@ -243,9 +241,11 @@ func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte, return } -// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If -// the shared information parameters aren't being used, they should be -// nil. +// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. +// +// s1 and s2 contain shared information that is not part of the resulting +// ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the +// shared information parameters aren't being used, they should be nil. func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) { params := pub.Params if params == nil { diff --git a/crypto/ecies/ecies_test.go b/crypto/ecies/ecies_test.go index 6a0ea3f022..cb09061ced 100644 --- a/crypto/ecies/ecies_test.go +++ b/crypto/ecies/ecies_test.go @@ -408,6 +408,36 @@ func TestEncryptDecrypt(t *testing.T) { } } +func TestDecryptShared2(t *testing.T) { + prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) + if err != nil { + t.Fatal(err) + } + message := []byte("Hello, world.") + shared2 := []byte("shared data 2") + ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, shared2) + if err != nil { + t.Fatal(err) + } + + // Check that decrypting with correct shared data works. + pt, err := prv.Decrypt(rand.Reader, ct, nil, shared2) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(pt, message) { + t.Fatal("ecies: plaintext doesn't match message") + } + + // Decrypting without shared data or incorrect shared data fails. + if _, err = prv.Decrypt(rand.Reader, ct, nil, nil); err == nil { + t.Fatal("ecies: decrypting without shared data didn't fail") + } + if _, err = prv.Decrypt(rand.Reader, ct, nil, []byte("garbage")); err == nil { + t.Fatal("ecies: decrypting with incorrect shared data didn't fail") + } +} + // TestMarshalEncryption validates the encode/decode produces a valid // ECIES encryption key. func TestMarshalEncryption(t *testing.T) {