mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 00:27:41 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			379 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			379 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//
 | 
						||
// Copyright Coinbase, Inc. All Rights Reserved.
 | 
						||
//
 | 
						||
// SPDX-License-Identifier: Apache-2.0
 | 
						||
//
 | 
						||
 | 
						||
// Package paillier contains Paillier's cryptosystem (1999) [P99].
 | 
						||
// Public-Key Cryptosystems Based on Composite Degree Residuosity Class.
 | 
						||
// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.112.4035&rep=rep1&type=pdf
 | 
						||
// All routines here from pseudocode §2.5. Fig 1: The Paillier Cryptosystem.
 | 
						||
//
 | 
						||
// This module provides APIs for:
 | 
						||
//
 | 
						||
//  - generating a safe keypair,
 | 
						||
//  - encryption and decryption,
 | 
						||
//  - adding two encrypted values, Enc(a) and Enc(b), and obtaining Enc(a + b), and
 | 
						||
//  - multiplying a plain value, a, and an encrypted value Enc(b), and obtaining Enc(a * b).
 | 
						||
//
 | 
						||
// The encrypted values are represented as big.Int and are serializable. This module also provides
 | 
						||
// JSON serialization for the PublicKey and the SecretKey.
 | 
						||
package paillier
 | 
						||
 | 
						||
import (
 | 
						||
	"encoding/json"
 | 
						||
	"fmt"
 | 
						||
	"math/big"
 | 
						||
 | 
						||
	"github.com/pkg/errors"
 | 
						||
 | 
						||
	"source.quilibrium.com/quilibrium/monorepo/nekryptology/internal"
 | 
						||
	"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core"
 | 
						||
)
 | 
						||
 | 
						||
// PaillierPrimeBits is the number of bits used to generate Paillier Safe Primes.
 | 
						||
const PaillierPrimeBits = 1024
 | 
						||
 | 
						||
type (
 | 
						||
	// PublicKey is a Paillier public key: N = P*Q; for safe primes P,Q.
 | 
						||
	PublicKey struct {
 | 
						||
		N  *big.Int // N = PQ
 | 
						||
		N2 *big.Int // N² computed and cached to prevent re-computation.
 | 
						||
	}
 | 
						||
 | 
						||
	// PublicKeyJson encapsulates the data that is serialized to JSON.
 | 
						||
	// It is used internally and not for external use. Public so other pieces
 | 
						||
	// can use for serialization.
 | 
						||
	PublicKeyJson struct {
 | 
						||
		N *big.Int
 | 
						||
	}
 | 
						||
 | 
						||
	// SecretKey is a Paillier secret key.
 | 
						||
	SecretKey struct {
 | 
						||
		PublicKey
 | 
						||
		Lambda  *big.Int // lcm(P - 1, Q - 1)
 | 
						||
		Totient *big.Int // Euler's totient: (P - 1) * (Q - 1)
 | 
						||
		U       *big.Int // L((N + 1)^λ(N) mod N²)−1 mod N
 | 
						||
	}
 | 
						||
 | 
						||
	// SecretKeyJson encapsulates the data that is serialized to JSON.
 | 
						||
	// It is used internally and not for external use. Public so other pieces
 | 
						||
	// can use for serialization.
 | 
						||
	SecretKeyJson struct {
 | 
						||
		N, Lambda, Totient, U *big.Int
 | 
						||
	}
 | 
						||
 | 
						||
	// Ciphertext in Pailler's cryptosystem: a value $c \in Z_{N²}$ .
 | 
						||
	Ciphertext *big.Int
 | 
						||
)
 | 
						||
 | 
						||
var (
 | 
						||
	two = big.NewInt(2) // The odd prime
 | 
						||
)
 | 
						||
 | 
						||
// NewKeys generates Paillier keys with `bits` sized safe primes.
 | 
						||
func NewKeys() (*PublicKey, *SecretKey, error) {
 | 
						||
	return keyGenerator(core.GenerateSafePrime, PaillierPrimeBits)
 | 
						||
}
 | 
						||
 | 
						||
// keyGenerator generates Paillier keys with `bits` sized safe primes using function
 | 
						||
// `genSafePrime` to generate the safe primes.
 | 
						||
func keyGenerator(genSafePrime func(uint) (*big.Int, error), bits uint) (*PublicKey, *SecretKey, error) {
 | 
						||
	values := make(chan *big.Int, 2)
 | 
						||
	errors := make(chan error, 2)
 | 
						||
 | 
						||
	var p, q *big.Int
 | 
						||
 | 
						||
	for p == q {
 | 
						||
		for range []int{1, 2} {
 | 
						||
			go func() {
 | 
						||
				value, err := genSafePrime(bits)
 | 
						||
				values <- value
 | 
						||
				errors <- err
 | 
						||
			}()
 | 
						||
		}
 | 
						||
 | 
						||
		for _, err := range []error{<-errors, <-errors} {
 | 
						||
			if err != nil {
 | 
						||
				return nil, nil, err
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
		p, q = <-values, <-values
 | 
						||
	}
 | 
						||
 | 
						||
	// Assemble the secret/public key pair.
 | 
						||
	sk, err := NewSecretKey(p, q)
 | 
						||
	if err != nil {
 | 
						||
		return nil, nil, err
 | 
						||
	}
 | 
						||
	return &sk.PublicKey, sk, nil
 | 
						||
}
 | 
						||
 | 
						||
// NewSecretKey computes intermediate values based on safe primes p, q.
 | 
						||
func NewSecretKey(p, q *big.Int) (*SecretKey, error) {
 | 
						||
	if p == nil || q == nil {
 | 
						||
		return nil, internal.ErrNilArguments
 | 
						||
	}
 | 
						||
	// Pre-compute necessary values.
 | 
						||
	pm1 := new(big.Int).Sub(p, core.One) // P - 1
 | 
						||
	qm1 := new(big.Int).Sub(q, core.One) // Q - 1
 | 
						||
	n := new(big.Int).Mul(p, q)          // N = PQ
 | 
						||
	nn := new(big.Int).Mul(n, n)         // N²
 | 
						||
	lambda, err := lcm(pm1, qm1)         // λ(N) = lcm(P-1, Q-1)
 | 
						||
	if err != nil {
 | 
						||
		// Code coverage note: lcm returns error only if the inputs are nil, which can never happen here.
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
	totient := new(big.Int).Mul(pm1, qm1) // 𝝋(N) = (P-1)(Q-1)
 | 
						||
	pk := PublicKey{
 | 
						||
		N:  n,
 | 
						||
		N2: nn,
 | 
						||
	}
 | 
						||
 | 
						||
	// (N+1)^λ(N) mod N²
 | 
						||
	t := new(big.Int).Add(n, core.One)
 | 
						||
	t.Exp(t, lambda, nn)
 | 
						||
 | 
						||
	// L((N+1)^λ(N) mod N²)
 | 
						||
	u, err := pk.l(t)
 | 
						||
	if err != nil {
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
	// L((N+1)^λ(N) mod N²)^-1 mod N
 | 
						||
	u.ModInverse(u, n)
 | 
						||
 | 
						||
	return &SecretKey{pk, lambda, totient, u}, nil
 | 
						||
}
 | 
						||
 | 
						||
// MarshalJSON converts the public key into json format.
 | 
						||
func (pk PublicKey) MarshalJSON() ([]byte, error) {
 | 
						||
	data := PublicKeyJson{pk.N}
 | 
						||
	return json.Marshal(data)
 | 
						||
}
 | 
						||
 | 
						||
// UnmarshalJSON converts the json data into this public key.
 | 
						||
func (pk *PublicKey) UnmarshalJSON(bytes []byte) error {
 | 
						||
	data := new(PublicKeyJson)
 | 
						||
	if err := json.Unmarshal(bytes, data); err != nil {
 | 
						||
		return err
 | 
						||
	}
 | 
						||
	if data.N == nil {
 | 
						||
		return nil
 | 
						||
	}
 | 
						||
	pk.N = data.N
 | 
						||
	pk.N2 = new(big.Int).Mul(data.N, data.N)
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
// lcm calculates the least common multiple.
 | 
						||
func lcm(x, y *big.Int) (*big.Int, error) {
 | 
						||
	if x == nil || y == nil {
 | 
						||
		return nil, internal.ErrNilArguments
 | 
						||
	}
 | 
						||
	gcd := new(big.Int).GCD(nil, nil, x, y)
 | 
						||
	if core.ConstantTimeEq(gcd, core.Zero) {
 | 
						||
		return core.Zero, nil
 | 
						||
	}
 | 
						||
	// Compute least common multiple: https://en.wikipedia.org/wiki/Least_common_multiple#Calculation .
 | 
						||
	b := new(big.Int)
 | 
						||
	return b.Abs(b.Mul(b.Div(x, gcd), y)), nil
 | 
						||
}
 | 
						||
 | 
						||
// l computes a residuosity class of n^2: (x - 1) / n.
 | 
						||
// Where it is the quotient x - 1 divided by n not modular multiplication of x - 1 times
 | 
						||
// the modular multiplicative inverse of n. The function name comes from [P99].
 | 
						||
func (pk *PublicKey) l(x *big.Int) (*big.Int, error) {
 | 
						||
	if x == nil {
 | 
						||
		return nil, internal.ErrNilArguments
 | 
						||
	}
 | 
						||
 | 
						||
	if core.ConstantTimeEq(pk.N, core.Zero) {
 | 
						||
		return nil, internal.ErrNCannotBeZero
 | 
						||
	}
 | 
						||
 | 
						||
	// Ensure x = 1 mod N
 | 
						||
	if !core.ConstantTimeEq(new(big.Int).Mod(x, pk.N), core.One) {
 | 
						||
		return nil, internal.ErrResidueOne
 | 
						||
	}
 | 
						||
 | 
						||
	// Ensure x ∈ Z_N²
 | 
						||
	if err := core.In(x, pk.N2); err != nil {
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
 | 
						||
	// (x - 1) / n
 | 
						||
	b := new(big.Int).Sub(x, core.One)
 | 
						||
	return b.Div(b, pk.N), nil
 | 
						||
}
 | 
						||
 | 
						||
// NewPubkey initializes a Paillier public key with a given n.
 | 
						||
func NewPubkey(n *big.Int) (*PublicKey, error) {
 | 
						||
	if n == nil {
 | 
						||
		return nil, errors.New("n cannot be nil")
 | 
						||
	}
 | 
						||
	return &PublicKey{
 | 
						||
		N:  n,
 | 
						||
		N2: new(big.Int).Mul(n, n), // Compute and cache N²
 | 
						||
	}, nil
 | 
						||
}
 | 
						||
 | 
						||
// Add combines two Paillier ciphertexts.
 | 
						||
func (pk *PublicKey) Add(c, d Ciphertext) (Ciphertext, error) {
 | 
						||
	if c == nil || d == nil {
 | 
						||
		return nil, internal.ErrNilArguments
 | 
						||
	}
 | 
						||
	// Ensure c,d ∈ Z_N²
 | 
						||
	cErr := core.In(c, pk.N2)
 | 
						||
	dErr := core.In(d, pk.N2)
 | 
						||
	// Constant time error check
 | 
						||
	var err error
 | 
						||
	if cErr != nil {
 | 
						||
		err = cErr
 | 
						||
	}
 | 
						||
	if dErr != nil {
 | 
						||
		err = dErr
 | 
						||
	}
 | 
						||
	if err != nil {
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
 | 
						||
	ctxt, err := core.Mul(c, d, pk.N2)
 | 
						||
	if err != nil {
 | 
						||
		// Code coverage note: core.Mul returns error only if the inputs are nil, which can never happen here.
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
	return ctxt, nil
 | 
						||
}
 | 
						||
 | 
						||
// Mul is equivalent to adding two Paillier exponents.
 | 
						||
func (pk *PublicKey) Mul(a *big.Int, c Ciphertext) (Ciphertext, error) {
 | 
						||
	if a == nil || c == nil {
 | 
						||
		return nil, internal.ErrNilArguments
 | 
						||
	}
 | 
						||
 | 
						||
	// Ensure a ∈ Z_N
 | 
						||
	aErr := core.In(a, pk.N)
 | 
						||
	// Ensure c ∈ Z_N²
 | 
						||
	cErr := core.In(c, pk.N2)
 | 
						||
 | 
						||
	var err error
 | 
						||
 | 
						||
	// Constant time error check
 | 
						||
	if aErr != nil {
 | 
						||
		err = aErr
 | 
						||
	}
 | 
						||
	if cErr != nil {
 | 
						||
		err = cErr
 | 
						||
	}
 | 
						||
	if err != nil {
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
	return new(big.Int).Exp(c, a, pk.N2), nil
 | 
						||
}
 | 
						||
 | 
						||
// Encrypt produces a ciphertext on input message.
 | 
						||
func (pk *PublicKey) Encrypt(msg *big.Int) (Ciphertext, *big.Int, error) {
 | 
						||
	// generate a nonce: r \in Z**_N
 | 
						||
	r, err := core.Rand(pk.N)
 | 
						||
	if err != nil {
 | 
						||
		return nil, nil, err
 | 
						||
	}
 | 
						||
 | 
						||
	// Generate and return the ciphertext
 | 
						||
	ct, err := pk.encrypt(msg, r)
 | 
						||
	return ct, r, err
 | 
						||
}
 | 
						||
 | 
						||
// encrypt produces a ciphertext on input a message and nonce.
 | 
						||
func (pk *PublicKey) encrypt(msg, r *big.Int) (Ciphertext, error) {
 | 
						||
	if msg == nil || r == nil {
 | 
						||
		return nil, internal.ErrNilArguments
 | 
						||
	}
 | 
						||
 | 
						||
	// Ensure msg ∈ Z_N
 | 
						||
	if err := core.In(msg, pk.N); err != nil {
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
 | 
						||
	// Ensure r ∈ Z^*_N: we use the method proved in docs/[EL20]
 | 
						||
	// ensure r ∈ Z^_N-{0}
 | 
						||
	if err := core.In(r, pk.N); err != nil {
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
	if core.ConstantTimeEq(r, core.Zero) {
 | 
						||
		return nil, fmt.Errorf("r cannot be 0")
 | 
						||
	}
 | 
						||
 | 
						||
	// Compute the ciphertext components: ɑ, β
 | 
						||
	// ɑ = (N+1)^m (mod N²)
 | 
						||
	ɑ := new(big.Int).Add(pk.N, core.One)
 | 
						||
	ɑ.Exp(ɑ, msg, pk.N2)
 | 
						||
	β := new(big.Int).Exp(r, pk.N, pk.N2) // β = r^N (mod N²)
 | 
						||
 | 
						||
	// ciphertext = ɑ*β = (N+1)^m * r^N  (mod N²)
 | 
						||
	c, err := core.Mul(ɑ, β, pk.N2)
 | 
						||
	if err != nil {
 | 
						||
		// Code coverage note: core.Mul returns error only if the inputs are nil, which can never happen here.
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
	return c, nil
 | 
						||
}
 | 
						||
 | 
						||
// Decrypt is the reverse operation of Encrypt.
 | 
						||
func (sk *SecretKey) Decrypt(c Ciphertext) (*big.Int, error) {
 | 
						||
	if c == nil {
 | 
						||
		return nil, internal.ErrNilArguments
 | 
						||
	}
 | 
						||
 | 
						||
	// Ensure C ∈ Z_N²
 | 
						||
	if err := core.In(c, sk.N2); err != nil {
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
 | 
						||
	// Compute the msg in components
 | 
						||
	// ɑ ≡ c^{λ(N)}		mod N²
 | 
						||
	ɑ := new(big.Int).Exp(c, sk.Lambda, sk.N2)
 | 
						||
 | 
						||
	// l = L(ɑ, N)
 | 
						||
	ell, err := sk.l(ɑ)
 | 
						||
	if err != nil {
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
 | 
						||
	// Compute the msg
 | 
						||
	// m ≡ lu = L(ɑ)*u = L(c^{λ(N)})*u	mod N
 | 
						||
	m, err := core.Mul(ell, sk.U, sk.N)
 | 
						||
	if err != nil {
 | 
						||
		return nil, err
 | 
						||
	}
 | 
						||
	return m, nil
 | 
						||
}
 | 
						||
 | 
						||
// MarshalJSON converts the secret key into json format.
 | 
						||
func (sk SecretKey) MarshalJSON() ([]byte, error) {
 | 
						||
	data := SecretKeyJson{
 | 
						||
		sk.N,
 | 
						||
		sk.Lambda,
 | 
						||
		sk.Totient,
 | 
						||
		sk.U,
 | 
						||
	}
 | 
						||
	return json.Marshal(data)
 | 
						||
}
 | 
						||
 | 
						||
// UnmarshalJSON converts the json data into this secret key.
 | 
						||
func (sk *SecretKey) UnmarshalJSON(bytes []byte) error {
 | 
						||
	data := new(SecretKeyJson)
 | 
						||
	if err := json.Unmarshal(bytes, data); err != nil {
 | 
						||
		return err
 | 
						||
	}
 | 
						||
	if data.N != nil {
 | 
						||
		sk.N = data.N
 | 
						||
		sk.N2 = new(big.Int).Mul(data.N, data.N)
 | 
						||
	}
 | 
						||
	sk.U = data.U
 | 
						||
	sk.Totient = data.Totient
 | 
						||
	sk.Lambda = data.Lambda
 | 
						||
	return nil
 | 
						||
}
 |