From f5a4d188896d0ef82268f6aff8d56caed543e456 Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Tue, 17 Jul 2018 15:05:59 +0200 Subject: [PATCH] Added support for a Cypher multiplication It's now possible to multiply Cypher by an integer. Paillier is a homomorphic encryption scheme, where an encrypted plaintext `m` raised to an integer `k` will decrypt to the product of the plaintext `m` and `k`. --- paillier.go | 13 +++++++++++++ paillier_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/paillier.go b/paillier.go index 9eca2ab..0e32b23 100644 --- a/paillier.go +++ b/paillier.go @@ -63,6 +63,19 @@ func (pk *PublicKey) Add(cypher ...*Cypher) *Cypher { } } +// Mul returns a product of `cypher` and `scalar` without decrypting `cypher`. +// +// It's possible because Paillier is a homomorphic encryption scheme, where +// an encrypted plaintext `m` raised to an integer `k` will decrypt to the +// product of the plaintext `m` and `k`: +// +// D( E(m)^k mod N^2 ) = km mod N +func (pk *PublicKey) Mul(cypher *Cypher, scalar *big.Int) *Cypher { + return &Cypher{ + C: new(big.Int).Exp(cypher.C, scalar, pk.GetNSquare()), + } +} + type PrivateKey struct { PublicKey Lambda *big.Int diff --git a/paillier_test.go b/paillier_test.go index e157ec2..75a759d 100644 --- a/paillier_test.go +++ b/paillier_test.go @@ -92,3 +92,36 @@ func TestAddCypherWithSmallKeyModulus(t *testing.T) { t.Errorf("Unexpected decrypted value [%v]", m) } } + +func TestMulCypher(t *testing.T) { + privateKey := CreatePrivateKey(big.NewInt(17), big.NewInt(13)) + + cypher, err := privateKey.Encrypt(big.NewInt(3), rand.Reader) + if err != nil { + t.Fatal(err) + } + + cypherMultiple := privateKey.Mul(cypher, big.NewInt(7)) + multiple := privateKey.Decrypt(cypherMultiple) + + if !reflect.DeepEqual(multiple, big.NewInt(21)) { + t.Errorf("Unexpected decrypted value [%v]", multiple) + } +} + +func TestMulCypherWithSmallKeyModulus(t *testing.T) { + privateKey := CreatePrivateKey(big.NewInt(7), big.NewInt(5)) + + cypher, err := privateKey.Encrypt(big.NewInt(30), rand.Reader) + if err != nil { + t.Fatal(err) + } + + cypherMultiple := privateKey.Mul(cypher, big.NewInt(93)) + multiple := privateKey.Decrypt(cypherMultiple) + + // (30*93) mod (7*5) = 25 + if !reflect.DeepEqual(multiple, big.NewInt(25)) { + t.Errorf("Unexpected decrypted value [%v]", multiple) + } +}