diff --git a/paillier.go b/paillier.go index 9eca2ab..557ceab 100644 --- a/paillier.go +++ b/paillier.go @@ -14,6 +14,31 @@ func (pk *PublicKey) GetNSquare() *big.Int { return new(big.Int).Mul(pk.N, pk.N) } +// EncryptWithR encrypts a plaintext into a cypher one with random `r` specified +// in the argument. The plain text must be smaller that N and bigger or equal +// than zero. `r` is the randomness used to encrypt the plaintext. `r` must be +// a random element from a multiplicative group of integers modulo N. +// +// If you don't need to use the specific `r`, you should use the `Encrypt` +// function instead. +// +// m - plaintext to encrypt +// r - randomness used for encryption +// E(m, r) = [(1 + N) r^N] mod N^2 +// +// See [KL 08] construction 11.32, page 414. +func (pk *PublicKey) EncryptWithR(m *big.Int, r *big.Int) (*Cypher, error) { + nSquare := pk.GetNSquare() + + // g is _always_ equal n+1 + // Threshold encryption is safe only for g=n+1 choice. + // See [DJN 10], section 5.1 + g := new(big.Int).Add(pk.N, big.NewInt(1)) + gm := new(big.Int).Exp(g, m, nSquare) + rn := new(big.Int).Exp(r, pk.N, nSquare) + return &Cypher{new(big.Int).Mod(new(big.Int).Mul(rn, gm), nSquare)}, nil +} + // Encrypt a plaintext into a cypher one. The plain text must be smaller that // N and bigger or equal than zero. random is usually rand.Reader from the // package crypto/rand. @@ -29,15 +54,8 @@ func (pk *PublicKey) Encrypt(m *big.Int, random io.Reader) (*Cypher, error) { if err != nil { return nil, err } - nSquare := pk.GetNSquare() - // g is _always_ equal n+1 - // Threshold encryption is safe only for g=n+1 choice. - // See [DJN 10], section 5.1 - g := new(big.Int).Add(pk.N, big.NewInt(1)) - gm := new(big.Int).Exp(g, m, nSquare) - rn := new(big.Int).Exp(r, pk.N, nSquare) - return &Cypher{new(big.Int).Mod(new(big.Int).Mul(rn, gm), nSquare)}, nil + return pk.EncryptWithR(m, r) } // Add takes an arbitrary number of cyphertexts and returns one that encodes