From f5a4d188896d0ef82268f6aff8d56caed543e456 Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Tue, 17 Jul 2018 15:05:59 +0200 Subject: [PATCH 1/2] 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) + } +} From c685186ca3bcf589bd9064ecdfa1ede993d1dd86 Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Tue, 17 Jul 2018 15:20:17 +0200 Subject: [PATCH 2/2] Use Cmp to compare Ints, reflections is just to heavy --- paillier_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/paillier_test.go b/paillier_test.go index 75a759d..bc0af06 100644 --- a/paillier_test.go +++ b/paillier_test.go @@ -3,7 +3,6 @@ package paillier import ( "crypto/rand" "math/big" - "reflect" "testing" ) @@ -14,7 +13,7 @@ func TestComputeL(t *testing.T) { expected := big.NewInt(6) actual := L(u, n) - if !reflect.DeepEqual(expected, actual) { + if expected.Cmp(actual) != 0 { t.Errorf("Unexpected L function result [%v]", actual) } } @@ -26,7 +25,7 @@ func TestComputePhi(t *testing.T) { expected := big.NewInt(24) actual := computePhi(a, b) - if !reflect.DeepEqual(expected, actual) { + if expected.Cmp(actual) != 0 { t.Errorf("Unexpected phi value [%v]", actual) } } @@ -37,11 +36,11 @@ func TestCreatePrivateKey(t *testing.T) { privateKey := CreatePrivateKey(p, q) - if !reflect.DeepEqual(privateKey.N, big.NewInt(292153)) { + if privateKey.N.Cmp(big.NewInt(292153)) != 0 { t.Errorf("Unexpected N PublicKey value [%v]", privateKey.N) } - if !reflect.DeepEqual(privateKey.Lambda, big.NewInt(291060)) { + if privateKey.Lambda.Cmp(big.NewInt(291060)) != 0 { t.Errorf("Unexpected Lambda Public key value [%v]", privateKey.Lambda) } } @@ -52,14 +51,14 @@ func TestEncryptDecryptSmall(t *testing.T) { for i := 1; i < 10; i++ { privateKey := CreatePrivateKey(p, q) - inicialValue := big.NewInt(100) - cypher, err := privateKey.Encrypt(inicialValue, rand.Reader) + initialValue := big.NewInt(100) + cypher, err := privateKey.Encrypt(initialValue, rand.Reader) if err != nil { t.Error(err) } returnedValue := privateKey.Decrypt(cypher) - if !reflect.DeepEqual(inicialValue, returnedValue) { - t.Error("wrong decryption ", returnedValue, " is not ", inicialValue) + if initialValue.Cmp(returnedValue) != 0 { + t.Error("wrong decryption ", returnedValue, " is not ", initialValue) } } } @@ -74,7 +73,7 @@ func TestAddCyphers(t *testing.T) { cypher5 := privateKey.Add(cypher1, cypher2, cypher3, cypher4) m := privateKey.Decrypt(cypher5) - if !reflect.DeepEqual(m, big.NewInt(26)) { + if m.Cmp(big.NewInt(26)) != 0 { t.Errorf("Unexpected decrypted value [%v]", m) } } @@ -88,7 +87,7 @@ func TestAddCypherWithSmallKeyModulus(t *testing.T) { cypher4 := privateKey.Add(cypher1, cypher2, cypher3) m := privateKey.Decrypt(cypher4) - if !reflect.DeepEqual(m, big.NewInt(34)) { + if m.Cmp(big.NewInt(34)) != 0 { t.Errorf("Unexpected decrypted value [%v]", m) } } @@ -104,7 +103,8 @@ func TestMulCypher(t *testing.T) { cypherMultiple := privateKey.Mul(cypher, big.NewInt(7)) multiple := privateKey.Decrypt(cypherMultiple) - if !reflect.DeepEqual(multiple, big.NewInt(21)) { + // 3 * 7 = 21 + if multiple.Cmp(big.NewInt(21)) != 0 { t.Errorf("Unexpected decrypted value [%v]", multiple) } } @@ -121,7 +121,7 @@ func TestMulCypherWithSmallKeyModulus(t *testing.T) { multiple := privateKey.Decrypt(cypherMultiple) // (30*93) mod (7*5) = 25 - if !reflect.DeepEqual(multiple, big.NewInt(25)) { + if multiple.Cmp(big.NewInt(25)) != 0 { t.Errorf("Unexpected decrypted value [%v]", multiple) } }