mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-14 12:15:18 +00:00
1086 lines
42 KiB
Go
1086 lines
42 KiB
Go
|
//
|
|||
|
// Copyright Coinbase, Inc. All Rights Reserved.
|
|||
|
//
|
|||
|
// SPDX-License-Identifier: Apache-2.0
|
|||
|
//
|
|||
|
|
|||
|
package paillier
|
|||
|
|
|||
|
import (
|
|||
|
"encoding/hex"
|
|||
|
"errors"
|
|||
|
"fmt"
|
|||
|
"log"
|
|||
|
"math/big"
|
|||
|
"testing"
|
|||
|
|
|||
|
"github.com/stretchr/testify/require"
|
|||
|
|
|||
|
tt "source.quilibrium.com/quilibrium/monorepo/nekryptology/internal"
|
|||
|
crypto "source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core"
|
|||
|
)
|
|||
|
|
|||
|
var (
|
|||
|
x = tt.B10("7146643783615963513942641287213372249533955323510461217840179896547799100626220786140425637990097431")
|
|||
|
y = tt.B10("1747698065194620177681258504464368264357359841192790848951902311522815739310792522712583635858354245")
|
|||
|
N = tt.B10("85832751158419329546684678412285185885848111422509523329716452068504806021136687603399722116388773253")
|
|||
|
NminusOne = new(big.Int).Sub(N, crypto.One)
|
|||
|
NplusOne = new(big.Int).Add(N, crypto.One)
|
|||
|
hundoN = new(big.Int).Mul(N, big.NewInt(100))
|
|||
|
|
|||
|
NN = new(big.Int).Mul(N, N)
|
|||
|
NNminusOne = new(big.Int).Sub(NN, crypto.One)
|
|||
|
NNplusOne = new(big.Int).Add(NN, crypto.One)
|
|||
|
)
|
|||
|
|
|||
|
func Example_encryptDecrypt() {
|
|||
|
// Skip this example if -short parameter is passed.
|
|||
|
if testing.Short() {
|
|||
|
// Printing the expected output so that the test succeeds.
|
|||
|
fmt.Println("Succeeded in encrypting and decrypting the input message: Hello World!")
|
|||
|
return
|
|||
|
}
|
|||
|
hexMessage := hex.EncodeToString([]byte("Hello World!"))
|
|||
|
mappedMessage, ok := new(big.Int).SetString(hexMessage, 16)
|
|||
|
if !ok {
|
|||
|
panic("Error mapping message to scalar point.")
|
|||
|
}
|
|||
|
pub, sec, err := NewKeys()
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in generating keypair: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
// Ignoring the random value that was generated internally by `Encrypt`.
|
|||
|
cipher, _, err := pub.Encrypt(mappedMessage)
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in Encrypting the message: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
// Now decrypt using the secret key.
|
|||
|
decrypted, err := sec.Decrypt(cipher)
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in Decrypting the ciphertext: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
decoded := string(decrypted.Bytes())
|
|||
|
fmt.Println("Succeeded in encrypting and decrypting the input message:", decoded)
|
|||
|
|
|||
|
// Output:
|
|||
|
// Succeeded in encrypting and decrypting the input message: Hello World!
|
|||
|
}
|
|||
|
|
|||
|
func Example_homomorphicAddition() {
|
|||
|
// Skip this example if -short parameter is passed.
|
|||
|
if testing.Short() {
|
|||
|
// Printing the expected output so that the test succeeds.
|
|||
|
fmt.Println("Encrypting 123 and 456 separately.")
|
|||
|
fmt.Println("Adding their encrypted versions together.")
|
|||
|
fmt.Println("Succeeded in decrypting 579")
|
|||
|
return
|
|||
|
}
|
|||
|
pub, sec, err := NewKeys()
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in generating keypair: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
msg1 := tt.B10("123")
|
|||
|
msg2 := tt.B10("456")
|
|||
|
fmt.Printf("Encrypting %s and %s separately.\n", msg1, msg2)
|
|||
|
|
|||
|
cipher1, _, err := pub.Encrypt(msg1)
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in Encrypting the message: %v", err)
|
|||
|
}
|
|||
|
cipher2, _, err := pub.Encrypt(msg2)
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in Encrypting the message: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
fmt.Println("Adding their encrypted versions together.")
|
|||
|
cipher3, err := pub.Add(cipher1, cipher2)
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in adding the two ciphertexts: %v", err)
|
|||
|
}
|
|||
|
decrypted3, err := sec.Decrypt(cipher3)
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in Decrypting the ciphertext: %v", err)
|
|||
|
}
|
|||
|
fmt.Println("Succeeded in decrypting", decrypted3)
|
|||
|
|
|||
|
// Output:
|
|||
|
// Encrypting 123 and 456 separately.
|
|||
|
// Adding their encrypted versions together.
|
|||
|
// Succeeded in decrypting 579
|
|||
|
}
|
|||
|
|
|||
|
func Example_homomorphicMultiplication() {
|
|||
|
// Skip this example if -short parameter is passed.
|
|||
|
if testing.Short() {
|
|||
|
// Printing the expected output so that the test succeeds.
|
|||
|
fmt.Println("Encrypting 10.")
|
|||
|
fmt.Println("Multiplying plain 5 with the encrypted 10.")
|
|||
|
fmt.Println("Succeeded in decrypting 50.")
|
|||
|
return
|
|||
|
}
|
|||
|
pub, sec, err := NewKeys()
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in generating keypair: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
msg1 := tt.B10("10")
|
|||
|
msg2 := tt.B10("5")
|
|||
|
fmt.Printf("Encrypting %s.\n", msg1)
|
|||
|
|
|||
|
cipher1, _, err := pub.Encrypt(msg1)
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in Encrypting the message: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
fmt.Printf("Multiplying plain %s with the encrypted %s.\n", msg2, msg1)
|
|||
|
cipher3, err := pub.Mul(msg2, cipher1)
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in adding the two ciphertexts: %v", err)
|
|||
|
}
|
|||
|
decrypted3, err := sec.Decrypt(cipher3)
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Error in Decrypting the ciphertext: %v", err)
|
|||
|
}
|
|||
|
fmt.Printf("Succeeded in decrypting %s.\n", decrypted3)
|
|||
|
|
|||
|
// Output:
|
|||
|
// Encrypting 10.
|
|||
|
// Multiplying plain 5 with the encrypted 10.
|
|||
|
// Succeeded in decrypting 50.
|
|||
|
}
|
|||
|
|
|||
|
func TestGenerateSafePrimes(t *testing.T) {
|
|||
|
if testing.Short() {
|
|||
|
t.Skip("Skipping TestGenerateSafePrimes")
|
|||
|
}
|
|||
|
p, err := crypto.GenerateSafePrime(32)
|
|||
|
if err != nil {
|
|||
|
t.Errorf("GenerateSafePrime failed: %v", err)
|
|||
|
}
|
|||
|
if !p.ProbablyPrime(8) {
|
|||
|
t.Errorf("GenerateSafePrime didn't return a prime number: %v", p)
|
|||
|
}
|
|||
|
p, err = crypto.GenerateSafePrime(3)
|
|||
|
if err != nil {
|
|||
|
t.Errorf("GenerateSafePrime failed: %v", err)
|
|||
|
}
|
|||
|
if !p.ProbablyPrime(8) {
|
|||
|
t.Errorf("GenerateSafePrime didn't return a prime number: %v", p)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestGenerateSafePrimesLong(t *testing.T) {
|
|||
|
if testing.Short() {
|
|||
|
t.Skip("Skipping TestGenerateSafePrimesLong")
|
|||
|
}
|
|||
|
p, err := crypto.GenerateSafePrime(1024)
|
|||
|
if err != nil {
|
|||
|
t.Errorf("GenerateSafePrime failed: %v", err)
|
|||
|
}
|
|||
|
if !p.ProbablyPrime(8) {
|
|||
|
t.Errorf("GenerateSafePrime didn't return a prime number: %v", p)
|
|||
|
}
|
|||
|
if p.BitLen() != 1024 {
|
|||
|
t.Errorf("GenerateSafePrime didn't return a prime number with the exact bits")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestGenerateSafePrimesTooLow(t *testing.T) {
|
|||
|
_, err := crypto.GenerateSafePrime(2)
|
|||
|
require.Error(t, err)
|
|||
|
}
|
|||
|
|
|||
|
type lcmTest struct {
|
|||
|
x *big.Int
|
|||
|
y *big.Int
|
|||
|
err error
|
|||
|
expected *big.Int
|
|||
|
}
|
|||
|
|
|||
|
func runTestLcm(t *testing.T, testArgs []lcmTest) {
|
|||
|
for _, arg := range testArgs {
|
|||
|
a, err := lcm(arg.x, arg.y)
|
|||
|
if err != nil && arg.err == nil {
|
|||
|
t.Errorf("lcm failed: %v", err)
|
|||
|
}
|
|||
|
if a == nil && arg.expected != nil || a.Cmp(arg.expected) != 0 {
|
|||
|
t.Errorf("lcm failed. Expected %v, found: %v", arg.expected, a)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestLcm(t *testing.T) {
|
|||
|
testArgs := []lcmTest{
|
|||
|
{
|
|||
|
x: big.NewInt(4),
|
|||
|
y: big.NewInt(6),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(12),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(10),
|
|||
|
y: big.NewInt(22),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(110),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(1),
|
|||
|
y: big.NewInt(3),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(3),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(5),
|
|||
|
y: big.NewInt(7),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(35),
|
|||
|
},
|
|||
|
}
|
|||
|
runTestLcm(t, testArgs)
|
|||
|
}
|
|||
|
|
|||
|
func TestLcmCommutative(t *testing.T) {
|
|||
|
testArgs := []lcmTest{
|
|||
|
{
|
|||
|
x: big.NewInt(11),
|
|||
|
y: big.NewInt(7),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(77),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(7),
|
|||
|
y: big.NewInt(11),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(77),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(13),
|
|||
|
y: big.NewInt(23),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(299),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(23),
|
|||
|
y: big.NewInt(13),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(299),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(-23),
|
|||
|
y: big.NewInt(17),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(391),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(23),
|
|||
|
y: big.NewInt(-17),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(391),
|
|||
|
},
|
|||
|
}
|
|||
|
runTestLcm(t, testArgs)
|
|||
|
}
|
|||
|
|
|||
|
func TestLcmNegNums(t *testing.T) {
|
|||
|
testArgs := []lcmTest{
|
|||
|
{
|
|||
|
x: big.NewInt(-5),
|
|||
|
y: big.NewInt(-7),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(35),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(-5),
|
|||
|
y: big.NewInt(7),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(35),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(3),
|
|||
|
y: big.NewInt(-11),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(33),
|
|||
|
},
|
|||
|
}
|
|||
|
runTestLcm(t, testArgs)
|
|||
|
}
|
|||
|
|
|||
|
func TestLcmNil(t *testing.T) {
|
|||
|
testArgs := []lcmTest{
|
|||
|
{
|
|||
|
x: nil,
|
|||
|
y: big.NewInt(1),
|
|||
|
err: errors.New("arguments cannot be nil"),
|
|||
|
expected: nil,
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(1),
|
|||
|
y: nil,
|
|||
|
err: errors.New("arguments cannot be nil"),
|
|||
|
expected: nil,
|
|||
|
},
|
|||
|
{
|
|||
|
x: nil,
|
|||
|
y: nil,
|
|||
|
err: errors.New("arguments cannot be nil"),
|
|||
|
expected: nil,
|
|||
|
},
|
|||
|
}
|
|||
|
runTestLcm(t, testArgs)
|
|||
|
}
|
|||
|
|
|||
|
func TestLcmZero(t *testing.T) {
|
|||
|
testArgs := []lcmTest{
|
|||
|
{
|
|||
|
x: big.NewInt(0),
|
|||
|
y: big.NewInt(1),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(0),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(0),
|
|||
|
y: big.NewInt(0),
|
|||
|
err: nil,
|
|||
|
expected: big.NewInt(0),
|
|||
|
},
|
|||
|
}
|
|||
|
runTestLcm(t, testArgs)
|
|||
|
}
|
|||
|
|
|||
|
func TestLcmBigPrimes(t *testing.T) {
|
|||
|
x := new(big.Int)
|
|||
|
y := new(big.Int)
|
|||
|
// Generated by OpenSSL
|
|||
|
x.SetString("133788347333574532510542341875219452703250094560184213896952738579939377079849213618116996737030817731544214409221015150233522821287955673536671953914660520267670984696713816508768479853621956967492030516224494353641551367310541202655075859386716364585825364092974073148178887544704793573033779774765431460367", 10)
|
|||
|
y.SetString("121400263190232595456200749546561304956161672968687911935494950378721768184159069938532869288284686583150658925255722159156454219960265942696166947144912738151554579878178746701374346180640493532962639632666540478486867810588884360492830920363713588684509182704981665082591486786717530494254613085570321507623", 10)
|
|||
|
expected := new(big.Int)
|
|||
|
expected.SetString("16241940578082201531943448855852277578391761356628379864603641922876623601321625229339135653813019543205064366507109899018615521640687222340376734033815591736764469510811142260074144789284382858541066390183237904579674336717818949214144339382239132186500111594251680147962383065732964214151653795512167674648653475620307856642151695559944756719719799945193072239010815330021803557074201060705849949820706127488164694762724694756011467249889383401729777382247223470577114290663770295230883950621358271613200219512401437571399087878832070221157976750549142719310423012055140771277730139053532825828483343855582012877641", 10)
|
|||
|
|
|||
|
x2 := new(big.Int)
|
|||
|
x2.SetString("133788347333574532510542341875219452703250094560184213896952738579939377079849213618116996737030817731544214409221015150233522821287955673536671953914660520267670984696713816508768479853621956967492030516224494353641551367310541202655075859386716364585825364092974073148178887544704793573033779774765431460367", 10)
|
|||
|
|
|||
|
x3 := new(big.Int)
|
|||
|
y3 := new(big.Int)
|
|||
|
x3.SetString("199624032515728289045241179631920514454939035695180729995055822158745789192452713406851424173447485774951354235728394322982696160719973464933778580097775959312681723073700577658531340015313241640799019163953248377211698591166024389845418771351325354733438115315318038016037617205770677410860231617155107859183", 10)
|
|||
|
y3.SetString("142249905617339142091532152811520246816977809135348639617427185924289265672711180486386239769195440660717504105473521478033326628103915862155595134226885191558983128407247227273401068113332266238311624168954823649558019882800072911119616964386221647824743035538953625688976296691147616508925455607033114354959", 10)
|
|||
|
expected2 := new(big.Int)
|
|||
|
expected2.SetString("28396499784314989096609919418127345447157066075586506422680304338142086939236798450800279134642308338458035596559017626154823247809313781525454242216477721507296693149109832139024597927259443182893280359146077724553052468871051438675286719817790943900280362711254811533504902741179161752948522341835287769530110541739921633871308290020066875307078092554117637608375242902999872137629980200197702760214658136789637368191031173973090138816890631056194895911511193868568337270184231814553242352572122713100022187023932306383784997785740075483768764231396924369937421906728046753885386778340930941242102624489916449738497", 10)
|
|||
|
testArgs := []lcmTest{
|
|||
|
{
|
|||
|
x, y, nil, expected,
|
|||
|
},
|
|||
|
{
|
|||
|
x: x2,
|
|||
|
y: big.NewInt(1),
|
|||
|
err: nil,
|
|||
|
expected: x2,
|
|||
|
},
|
|||
|
{
|
|||
|
x: x3,
|
|||
|
y: y3,
|
|||
|
err: nil,
|
|||
|
expected: expected2,
|
|||
|
},
|
|||
|
}
|
|||
|
runTestLcm(t, testArgs)
|
|||
|
}
|
|||
|
|
|||
|
func TestLKnownCases(t *testing.T) {
|
|||
|
// test multiples of 5 for L
|
|||
|
pk, err := NewPubkey(big.NewInt(5))
|
|||
|
require.NoError(t, err)
|
|||
|
tests := []struct {
|
|||
|
in, expected *big.Int
|
|||
|
}{
|
|||
|
{big.NewInt(6), big.NewInt(1)},
|
|||
|
{big.NewInt(11), big.NewInt(2)},
|
|||
|
{big.NewInt(16), big.NewInt(3)},
|
|||
|
{big.NewInt(21), big.NewInt(4)},
|
|||
|
}
|
|||
|
|
|||
|
for _, test := range tests {
|
|||
|
r, err := pk.l(test.in)
|
|||
|
require.NoError(t, err)
|
|||
|
require.Equal(t, r, test.expected)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestLFailureCases(t *testing.T) {
|
|||
|
pk, err := NewPubkey(big.NewInt(5))
|
|||
|
require.NoError(t, err)
|
|||
|
tests := []*big.Int{
|
|||
|
pk.N, // u = N should fail
|
|||
|
big.NewInt(25), // u = NN should fail
|
|||
|
big.NewInt(51), // u > NN should fail
|
|||
|
big.NewInt(9), // u ≢ 1 (mod 5) should fail
|
|||
|
big.NewInt(12), // u ≢ 1 (mod 5) should fail
|
|||
|
big.NewInt(22), // u ≢ 1 (mod 5) should fail
|
|||
|
big.NewInt(-1), // negative N should fail
|
|||
|
big.NewInt(-100000), // negative N should fail
|
|||
|
nil, // nil should fail
|
|||
|
}
|
|||
|
|
|||
|
for _, test := range tests {
|
|||
|
_, err := pk.l(test)
|
|||
|
require.Error(t, err)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
type keygenTest struct {
|
|||
|
bits uint
|
|||
|
p, q, n, lambda, totient, u *big.Int
|
|||
|
}
|
|||
|
|
|||
|
func TestKeyGen(t *testing.T) {
|
|||
|
testValues := []*keygenTest{
|
|||
|
// Small values
|
|||
|
{
|
|||
|
bits: 32,
|
|||
|
p: tt.B10("4294967387"),
|
|||
|
q: tt.B10("8589936203"),
|
|||
|
n: tt.B10("36893495848295611561"),
|
|||
|
lambda: tt.B10("18446747917705353986"),
|
|||
|
totient: tt.B10("36893495835410707972"),
|
|||
|
u: tt.B10("30227647593197281524"),
|
|||
|
},
|
|||
|
{
|
|||
|
bits: 32,
|
|||
|
p: tt.B10("2404778303"),
|
|||
|
q: tt.B10("2907092159"),
|
|||
|
n: tt.B10("6990912148784626177"),
|
|||
|
lambda: tt.B10("3495456071736377858"),
|
|||
|
totient: tt.B10("6990912143472755716"),
|
|||
|
u: tt.B10("3614931622846492468"),
|
|||
|
},
|
|||
|
// Moderate values
|
|||
|
{
|
|||
|
bits: 128,
|
|||
|
p: tt.B10("505119856506205319276795183398241487263"),
|
|||
|
q: tt.B10("205972782400928578615836152187141707579"),
|
|||
|
n: tt.B10("104040942290540895974307747626520134740467527950099359068592315888198399066277"),
|
|||
|
lambda: tt.B10("52020471145270447987153873813260067369878217655596112585349842276306507935718"),
|
|||
|
totient: tt.B10("104040942290540895974307747626520134739756435311192225170699684552613015871436"),
|
|||
|
u: tt.B10("95814396947082822381619843641016289162443592153179788942685091512428172029465"),
|
|||
|
},
|
|||
|
{
|
|||
|
bits: 128,
|
|||
|
p: tt.B10("335833617445150372903755348587631934583"),
|
|||
|
q: tt.B10("275426149345634030797050866270209482803"),
|
|||
|
n: tt.B10("92497360073732512809517386349687056338889420300408887876944500444198759476149"),
|
|||
|
lambda: tt.B10("46248680036866256404758693174843528169139080266809051736621847114670459029382"),
|
|||
|
totient: tt.B10("92497360073732512809517386349687056338278160533618103473243694229340918058764"),
|
|||
|
u: tt.B10("37541288371367874015853812738289992945377756025517882548300075720005348319216"),
|
|||
|
},
|
|||
|
{
|
|||
|
bits: 256,
|
|||
|
p: tt.B10("115645895734860215235155088728394909334688633450524492586690742412129345961183"),
|
|||
|
q: tt.B10("94298418052417649431120534110853375174108454456092458684756344618179781451887"),
|
|||
|
n: tt.B10("10905225022052151768592443014939079805820716955892154646109970627753805040740378163517568530133182652794506558827042053659527293884287341299235199284102321"),
|
|||
|
totient: tt.B10("10905225022052151768592443014939079805820716955892154646109970627753805040740168219203781252268516377171667310542533256571620676933015894212204890156689252"),
|
|||
|
lambda: tt.B10("5452612511026075884296221507469539902910358477946077323054985313876902520370084109601890626134258188585833655271266628285810338466507947106102445078344626"),
|
|||
|
u: tt.B10("169122108559803116345465577435019987080055058605295565203286696962456365170552011215103788832323625338104327792007096903690940420144823974727816140829004"),
|
|||
|
},
|
|||
|
{
|
|||
|
bits: 384,
|
|||
|
p: tt.B10("36006692832910486705531921197379033634897461505036495703751117530881437756504623602114452424392242359949564580091963"),
|
|||
|
q: tt.B10("36321876854655342367765793082986061200135195654801162378979445503936881469720608843798409137541849432902150243071007"),
|
|||
|
n: tt.B10("1307830663020375807860069772466605443871885822612939940958802361999351292929784401772312287232210036471265772358253561264090635848856642357599288411446282200143037556882504679979558002244844355483553171478292766242112114935599016741"),
|
|||
|
totient: tt.B10("1307830663020375807860069772466605443871885822612939940958802361999351292929784401772312287232210036471265772358253488935520948283027569059885008046351447167485877719224421949416523183925618130251107258616730832150319263220775853772"),
|
|||
|
lambda: tt.B10("653915331510187903930034886233302721935942911306469970479401180999675646464892200886156143616105018235632886179126744467760474141513784529942504023175723583742938859612210974708261591962809065125553629308365416075159631610387926886"),
|
|||
|
u: tt.B10("715317338270237792745674161133027331913306953524485480270742409164181533024685207574377116318911340995248759257081568534206599002649096879000033274962046481163095418392051555090184840289513260640923181142724977346034839256290483076"),
|
|||
|
},
|
|||
|
// Large values
|
|||
|
{
|
|||
|
bits: 512,
|
|||
|
p: tt.B10("13334877681824046536664719753000692481615243060546695171749157112026072862294410162436291925578885141357927002155461724765584886877402066038258074266638227"),
|
|||
|
q: tt.B10("12122745362522189816168535264551355768089283231069686330301128627041958196835868405970767150401427191976786435200511843851744213149595052566013030642866907"),
|
|||
|
n: tt.B10("161655326577133109177725996877941503037044267143093183990772875721980297379977570900477874093780897364088511586139843445141992295002878403748750051858500001631307112890860155944955185080369964944108396477646372269079498823545159135772467319334869864305928043113234061678778620562861360302446649667820279453889"),
|
|||
|
totient: tt.B10("161655326577133109177725996877941503037044267143093183990772875721980297379977570900477874093780897364088511586139843445141992295002878403748750051858499976173684068544623803111700167528321715239582104861264870218793759755514100005493898912275793883993594708399796705705210003233761333305328045396715369948756"),
|
|||
|
lambda: tt.B10("80827663288566554588862998438970751518522133571546591995386437860990148689988785450238937046890448682044255793069921722570996147501439201874375025929249988086842034272311901555850083764160857619791052430632435109396879877757050002746949456137896941996797354199898352852605001616880666652664022698357684974378"),
|
|||
|
u: tt.B10("143261270242335180420072816055839865064298362037063587448317467367577401621254503191376775173811231300545030557865973916661565869494495913728327166081853904903334058396967815592631415604767903602152339275761555997082956433277741333963496039496540726125762611561934388357363014028934069272035911913194424272603"),
|
|||
|
},
|
|||
|
{
|
|||
|
bits: 768,
|
|||
|
p: tt.B10("1346090925391135119143470623782502005582449208798686393499686094146720873293257316154858443761764176763426496081748327594475673914483978883075080616518148610864446133054517784818794038700373924492201179029136162262578223994386497407"),
|
|||
|
q: tt.B10("1267888740317619255987103204389173685200460862251480292534873171503916906509928280188817985770625788023592223617980306560361856737457586891910981446078699966027435065022526191471061668427090194699255004927681350300606724099539148139"),
|
|||
|
n: tt.B10("1706693527747144711594288434414073474898396319145231571914859473075446769444443882426378206783148798161228984036593560566511416432995440677335990047411064284625144780381208381275798262584775575885562112174608693614583699626181565327188316266582808161080083810509077419565819105286361318424233748287133200189491965280880943430756926385486914657888021988499576975592342792662208243895780558951878131107691067112167457219510292850345325644694079605526537816712375573"),
|
|||
|
totient: tt.B10("1706693527747144711594288434414073474898396319145231571914859473075446769444443882426378206783148798161228984036593560566511416432995440677335990047411064284625144780381208381275798262584775575885562112174608693614583699626181565324574336600874053785949509982337401728782909034236194632389674482636495420386306368937204513898366961598468194958159387833662046323650777017676146181298931982059996933030647090822311750092046173658889141687876567042341589722786730028"),
|
|||
|
lambda: tt.B10("853346763873572355797144217207036737449198159572615785957429736537723384722221941213189103391574399080614492018296780283255708216497720338667995023705532142312572390190604190637899131292387787942781056087304346807291849813090782662287168300437026892974754991168700864391454517118097316194837241318247710193153184468602256949183480799234097479079693916831023161825388508838073090649465991029998466515323545411155875046023086829444570843938283521170794861393365014"),
|
|||
|
u: tt.B10("779879106968621551612916279464123438735012661607976871766884426257741506106933684516528094230394847057111517560275304735511075756729605155799199673159820709716869729022492405360829062001458468008371167876032343417620981083465124988041616116692784740773729428828021798152577117895496702246006365934433098458747623402795759758566365836593488130254049427800131843438461226605279227891251815575333006410913379796415963477224332006612563517643916428864744112156376520"),
|
|||
|
},
|
|||
|
{
|
|||
|
bits: 1024,
|
|||
|
p: tt.B10("323048346478810234804346724288317979049543453886657577003300101860710127877799870550562838407667268404599358826513829060160504303395418566677040422188661745067470888457815635033321184439746580337024906877384167362567610372271431186610013379997212856608697550064099211785613236213633622219571487990672693003787"),
|
|||
|
q: tt.B10("289955956844872723713267618282085026937397801221604643862282902289352466511076698253093993268863225914839327563609168378629851975959785812001060859728689670901677697805606458924299545852498153652948060776824445669854015488773545309215892532182626763404124068861635361632889336491051975303142403383113070034867"),
|
|||
|
n: tt.B10("93669792410417391755898616958812213604373878875285824927431988118477734285768665211145268050244414695456141707631724902135831803247956851156058161652431398586664582925077157366114568914615913189006980440640666538921106871639116459047133240204886962593927223154881396777466153081835208630039047664120224812531738646998208894219436266840478325951526823776791414200683451217351791095609379048292074062880637329062218371522375097661526583290635879391529194601725476785472157424230313351359992497803391595095260449578824637692631790170131436072668730121222036510650215208397389118631464109460927478825133780143983053041329"),
|
|||
|
lambda: tt.B10("46834896205208695877949308479406106802186939437642912463715994059238867142884332605572634025122207347728070853815862451067915901623978425578029080826215699293332291462538578683057284457307956594503490220320333269460553435819558229523566620102443481296963611577440698388733076540917604315019523832060112406265562821347442605630459326248953961472769941260841575989908934106600864250610251239744208615602053417371389842566126050111368113505640337506425546659904062684751504418983445628701185883755573430552643740962308012330105082154543229788421412104521098445318696794735827272606480768378120940651209944385098645001338"),
|
|||
|
totient: tt.B10("93669792410417391755898616958812213604373878875285824927431988118477734285768665211145268050244414695456141707631724902135831803247956851156058161652431398586664582925077157366114568914615913189006980440640666538921106871639116459047133240204886962593927223154881396777466153081835208630039047664120224812531125642694885211260918652497907922945539882521683151979817868213201728501220502479488417231204106834742779685132252100222736227011280675012851093319808125369503008837966891257402371767511146861105287481924616024660210164309086459576842824209042196890637393589471654545212961536756241881302419888770197290002676"),
|
|||
|
u: tt.B10("38135949745652485811937226692116929429180649272477224483199257365577156885532690396567815884583937557608568699362433418166707048319324785327166624071125908609604488150973723257324029836008236113484260165701873141666619439620722921574373345283540196413007597899672199365492304562415424130214337263020773327553873482407654450455061737687873828877767689823341811598685374044652873284145859288532695538432223451947587392094598520855737584462011917578978549967062842845942828735580257392245879142299251014137170130879720213249399499545177941592508341271051010776972469394170182828098805388982944454017008931873419560331115"),
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
for _, test := range testValues {
|
|||
|
idx := 0
|
|||
|
safePrimes := []*big.Int{test.p, test.q}
|
|||
|
f := func(bits uint) (*big.Int, error) {
|
|||
|
r := safePrimes[idx]
|
|||
|
idx = (idx + 1) % 2
|
|||
|
return r, nil
|
|||
|
}
|
|||
|
|
|||
|
pub, sec, err := keyGenerator(f, test.bits)
|
|||
|
require.NoError(t, err)
|
|||
|
require.Equal(t, pub.N, test.n)
|
|||
|
require.Equal(t, sec.Totient, test.totient)
|
|||
|
require.Equal(t, sec.Lambda, test.lambda)
|
|||
|
require.Equal(t, sec.U, test.u)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestKeyGeneratorErrorConditions(t *testing.T) {
|
|||
|
// Should fail if a safe prime cannot be generated.
|
|||
|
f := func(bits uint) (*big.Int, error) {
|
|||
|
return nil, fmt.Errorf("safeprime error")
|
|||
|
}
|
|||
|
_, _, err := keyGenerator(f, 1)
|
|||
|
require.Contains(t, err.Error(), "safeprime error")
|
|||
|
|
|||
|
// Should fail if a gcd of p and q is zero.
|
|||
|
val := int64(0)
|
|||
|
oneF := func(bits uint) (*big.Int, error) {
|
|||
|
b := big.NewInt(val)
|
|||
|
val += 1
|
|||
|
return b, nil
|
|||
|
}
|
|||
|
_, _, err = keyGenerator(oneF, 1)
|
|||
|
require.Contains(t, err.Error(), "N cannot be 0")
|
|||
|
}
|
|||
|
|
|||
|
func TestKeyGenSameInput(t *testing.T) {
|
|||
|
p := tt.B10("4294967387")
|
|||
|
q := tt.B10("8589936203")
|
|||
|
idx := 0
|
|||
|
safePrimes := []*big.Int{p, q}
|
|||
|
f := func(bits uint) (*big.Int, error) {
|
|||
|
r := safePrimes[idx]
|
|||
|
idx = (idx + 1) % 2
|
|||
|
return r, nil
|
|||
|
}
|
|||
|
pub1, sec1, err := keyGenerator(f, 32)
|
|||
|
require.NoError(t, err)
|
|||
|
pub2, sec2, err := keyGenerator(f, 32)
|
|||
|
require.NoError(t, err)
|
|||
|
require.Equal(t, pub1.N, pub2.N)
|
|||
|
require.Equal(t, sec1.Lambda, sec2.Lambda)
|
|||
|
require.Equal(t, sec1.Totient, sec2.Totient)
|
|||
|
require.Equal(t, sec1.U, sec2.U)
|
|||
|
}
|
|||
|
|
|||
|
func TestNewKeysDistinct(t *testing.T) {
|
|||
|
if testing.Short() {
|
|||
|
t.Skip("Skipping TestNewKeys")
|
|||
|
}
|
|||
|
pub1, sec1, err := NewKeys()
|
|||
|
require.NoError(t, err)
|
|||
|
pub2, sec2, err := NewKeys()
|
|||
|
require.NoError(t, err)
|
|||
|
// Ensure two fresh keys are distinct
|
|||
|
require.NotEqual(t, pub1.N, pub2.N)
|
|||
|
require.NotEqual(t, sec1.Totient, sec2.Totient)
|
|||
|
require.NotEqual(t, sec1.Lambda, sec2.Lambda)
|
|||
|
require.NotEqual(t, sec1.U, sec2.U)
|
|||
|
}
|
|||
|
|
|||
|
// Tests the restrictions on input values for paillier.Add
|
|||
|
func TestAddErrorConditions(t *testing.T) {
|
|||
|
pk, err := NewPubkey(N)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
var tests = []struct {
|
|||
|
x, y *big.Int
|
|||
|
expectedPass bool
|
|||
|
}{
|
|||
|
// Good: 0 ≤ x,y < N²
|
|||
|
{crypto.Zero, crypto.One, true},
|
|||
|
{NminusOne, big.NewInt(1024), true}, // N-1, 1024
|
|||
|
{NplusOne, hundoN, true}, // N+1, 100N
|
|||
|
{crypto.One, NNminusOne, true}, // one, N²-1
|
|||
|
|
|||
|
// Bad
|
|||
|
{big.NewInt(-1), crypto.One, false}, // Negative values
|
|||
|
{crypto.One, big.NewInt(-1), false}, // Negative values
|
|||
|
{big.NewInt(-1000000), crypto.One, false}, // Negative values
|
|||
|
{crypto.One, big.NewInt(-9993654), false}, // Negative values
|
|||
|
|
|||
|
{nil, crypto.One, false}, // x nil
|
|||
|
{crypto.One, nil, false}, // y nil
|
|||
|
|
|||
|
{NNplusOne, crypto.One, false}, // N²+1
|
|||
|
{NNplusOne, NNplusOne, false}, // both bad
|
|||
|
{crypto.One, NNplusOne, false}, // N²+1
|
|||
|
{new(big.Int).Add(NN, NN), crypto.One, false}, // 2N²
|
|||
|
{crypto.One, new(big.Int).Add(NN, NN), false}, // 2N²
|
|||
|
{NN, crypto.One, false}, // = N²
|
|||
|
{crypto.One, NN, false}, // = N²
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// All the tests!
|
|||
|
for _, test := range tests {
|
|||
|
_, err := pk.Add(test.x, test.y)
|
|||
|
if test.expectedPass {
|
|||
|
require.NoError(t, err)
|
|||
|
} else {
|
|||
|
require.Error(t, err)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// Tests for paillier addition with known answers
|
|||
|
func TestAdd(t *testing.T) {
|
|||
|
z9, err := NewPubkey(big.NewInt(3))
|
|||
|
require.NoError(t, err)
|
|||
|
pk, err := NewPubkey(N)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
// Pre-compute values for testing
|
|||
|
NplusOne := NplusOne
|
|||
|
// z = 2N+1
|
|||
|
z := new(big.Int).Add(N, N)
|
|||
|
z.Add(z, crypto.One)
|
|||
|
|
|||
|
var tests = []struct {
|
|||
|
pk *PublicKey
|
|||
|
x, y, expected *big.Int
|
|||
|
}{
|
|||
|
// Small number tests: Z_9
|
|||
|
{z9, big.NewInt(0), big.NewInt(1), big.NewInt(0)},
|
|||
|
{z9, big.NewInt(1), big.NewInt(5), big.NewInt(5)},
|
|||
|
{z9, big.NewInt(2), big.NewInt(2), big.NewInt(4)},
|
|||
|
{z9, big.NewInt(5), big.NewInt(2), big.NewInt(1)},
|
|||
|
{z9, big.NewInt(6), big.NewInt(8), big.NewInt(3)},
|
|||
|
{z9, big.NewInt(7), big.NewInt(7), big.NewInt(4)},
|
|||
|
{z9, big.NewInt(2), big.NewInt(4), big.NewInt(8)},
|
|||
|
{z9, big.NewInt(8), big.NewInt(8), big.NewInt(1)},
|
|||
|
{z9, big.NewInt(8), big.NewInt(2), big.NewInt(7)},
|
|||
|
|
|||
|
// large number tests: Z_N²
|
|||
|
{pk, N, crypto.Zero, crypto.Zero},
|
|||
|
{pk, N, N, crypto.Zero}, // N² ≡ 0 (N²)
|
|||
|
{pk, crypto.Zero, NplusOne, crypto.Zero},
|
|||
|
{pk, NplusOne, NplusOne, z}, // (N+1)² = N² + 2N + 1 ≡ 2N + 1 (N²)
|
|||
|
{pk, tt.B10("11659564086467828628"), tt.B10("57089538512338875950"), tt.B10("665639132951488346363609789106750696600")},
|
|||
|
}
|
|||
|
// All the tests!
|
|||
|
for _, test := range tests {
|
|||
|
actual, err := test.pk.Add(test.x, test.y)
|
|||
|
require.NoError(t, err)
|
|||
|
require.Zero(t, test.expected.Cmp(actual))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Tests the restrictions on input values for paillier.Mul
|
|||
|
func TestMulErrorConditions(t *testing.T) {
|
|||
|
pk, err := NewPubkey(N)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
var tests = []struct {
|
|||
|
x, y *big.Int
|
|||
|
expectedPass bool
|
|||
|
}{
|
|||
|
// Good
|
|||
|
{crypto.Zero, crypto.One, true}, // 0 ≤ x,y < N
|
|||
|
{NminusOne, big.NewInt(1024), true}, // 0 ≤ x,y < N
|
|||
|
{NminusOne, hundoN, true}, // N-1 < N; 100N < N²
|
|||
|
{crypto.One, NNminusOne, true}, // 1 < N; N²-1 < N
|
|||
|
|
|||
|
// Bad
|
|||
|
{big.NewInt(-1), crypto.One, false}, // Negative value x
|
|||
|
{big.NewInt(-1000000), crypto.One, false}, // Negative values x
|
|||
|
{crypto.One, big.NewInt(-9993654), false}, // Negative values y
|
|||
|
{crypto.One, big.NewInt(-1), false}, // Negative value y
|
|||
|
{big.NewInt(-1), big.NewInt(-1), false}, // Negative values both
|
|||
|
|
|||
|
{NplusOne, crypto.One, false}, // x > N; y ok
|
|||
|
{NplusOne, NNplusOne, false}, // both x,y bad
|
|||
|
{crypto.One, NNplusOne, false}, // y bad
|
|||
|
{new(big.Int).Add(NN, NN), crypto.One, false}, // x really bad
|
|||
|
{crypto.One, new(big.Int).Add(NN, NN), false}, // y bad
|
|||
|
{N, crypto.One, false}, // x boundary condition
|
|||
|
{crypto.One, NN, false}, // y boundary condition
|
|||
|
{nil, crypto.One, false}, // x nil
|
|||
|
{crypto.One, nil, false}, // y nil
|
|||
|
}
|
|||
|
|
|||
|
// All the tests!
|
|||
|
for _, test := range tests {
|
|||
|
_, err := pk.Mul(test.x, test.y)
|
|||
|
if test.expectedPass {
|
|||
|
require.NoError(t, err)
|
|||
|
} else {
|
|||
|
require.Error(t, err)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Tests for paillier multiplication with known answers
|
|||
|
func TestMul(t *testing.T) {
|
|||
|
z25, err := NewPubkey(big.NewInt(5))
|
|||
|
require.NoError(t, err)
|
|||
|
pk, err := NewPubkey(N)
|
|||
|
require.NoError(t, err)
|
|||
|
newPk, err := NewPubkey(tt.B10("66563913295148834609789506"))
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
// Compute: ɑ ≡ -2N -1 (N²)
|
|||
|
alpha, err := crypto.Mul(N, big.NewInt(-2), NN)
|
|||
|
require.Nil(t, err)
|
|||
|
alpha.Add(alpha, crypto.One)
|
|||
|
|
|||
|
var tests = []struct {
|
|||
|
pk *PublicKey
|
|||
|
// Note: these values are in reverse-order from the order passed in as args
|
|||
|
c, a, expected *big.Int
|
|||
|
}{
|
|||
|
// Small number tests: Z_{25}
|
|||
|
{z25, big.NewInt(1), big.NewInt(0), big.NewInt(1)},
|
|||
|
{z25, big.NewInt(5), big.NewInt(1), big.NewInt(5)},
|
|||
|
{z25, big.NewInt(2), big.NewInt(2), big.NewInt(4)},
|
|||
|
{z25, big.NewInt(2), big.NewInt(1), big.NewInt(2)},
|
|||
|
{z25, big.NewInt(8), big.NewInt(4), big.NewInt(21)},
|
|||
|
{z25, big.NewInt(7), big.NewInt(3), big.NewInt(18)},
|
|||
|
{z25, big.NewInt(6), big.NewInt(0), big.NewInt(1)},
|
|||
|
{z25, big.NewInt(4), big.NewInt(3), big.NewInt(14)},
|
|||
|
{z25, big.NewInt(8), big.NewInt(1), big.NewInt(8)},
|
|||
|
{z25, big.NewInt(2), big.NewInt(2), big.NewInt(4)},
|
|||
|
|
|||
|
// large number tests
|
|||
|
{pk, x, crypto.Zero, crypto.One}, // x^0 = 1
|
|||
|
{pk, y, crypto.One, y}, // y^1 = 1
|
|||
|
{pk, crypto.Zero, NminusOne, crypto.Zero}, // 0^{N-1} = 0
|
|||
|
{pk, NminusOne, two, alpha}, // (N-1)² = N² - 2N - 1 ≡ -2N -1 (N²)
|
|||
|
|
|||
|
// large number test: WorlframAlpha test case
|
|||
|
{newPk,
|
|||
|
tt.B10("11659564086467828628"),
|
|||
|
tt.B10("57089538512338875950"),
|
|||
|
tt.B10("1487259371808822575685230766372478858208831958946972")},
|
|||
|
}
|
|||
|
// All the tests!
|
|||
|
for _, test := range tests {
|
|||
|
actual, err := test.pk.Mul(test.a, test.c)
|
|||
|
require.NoError(t, err)
|
|||
|
require.Zero(t, test.expected.Cmp(actual))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// encrypt() is provided a nonce and must be deterministic
|
|||
|
func TestLittleEncryptDeterministic(t *testing.T) {
|
|||
|
pk, err := NewPubkey(N)
|
|||
|
require.NoError(t, err)
|
|||
|
r, err := crypto.Rand(pk.N)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
msg, _ := crypto.Rand(pk.N)
|
|||
|
|
|||
|
// Encrypt the same msg/nonce multiple times
|
|||
|
a0, err := pk.encrypt(msg, r)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
a1, err := pk.encrypt(msg, r)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
a2, err := pk.encrypt(msg, r)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
// ❄️ == bad; confirm results are identical
|
|||
|
require.Equal(t, a0, a1)
|
|||
|
require.Equal(t, a0, a2)
|
|||
|
}
|
|||
|
|
|||
|
// Tests the restrictions on input values for paillier.Encrypt
|
|||
|
func TestEncryptErrorConditions(t *testing.T) {
|
|||
|
pk, err := NewPubkey(N)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
var tests = []struct {
|
|||
|
msg, r *big.Int
|
|||
|
expectedPass bool
|
|||
|
}{
|
|||
|
// Good
|
|||
|
{crypto.Zero, crypto.One, true}, // 0 ≤ m,r < N
|
|||
|
{crypto.One, NminusOne, true}, // 0 ≤ m,r < N
|
|||
|
{NminusOne, two, true}, // 0 ≤ m,r < N
|
|||
|
|
|||
|
// Bad
|
|||
|
{crypto.Zero, crypto.Zero, false}, // r cannot be 0
|
|||
|
{big.NewInt(-1), crypto.One, false}, // Negative value m
|
|||
|
{big.NewInt(-1000000), crypto.One, false}, // Negative value r
|
|||
|
{big.NewInt(-1), big.NewInt(-1), false}, // Negative values both
|
|||
|
{nil, crypto.One, false}, // m nil
|
|||
|
{crypto.One, nil, false}, // r nil
|
|||
|
{nil, nil, false}, // both nil
|
|||
|
{N, crypto.One, false}, // m == N
|
|||
|
{crypto.One, N, false}, // r == N
|
|||
|
}
|
|||
|
|
|||
|
// All the tests!
|
|||
|
for _, test := range tests {
|
|||
|
_, err := pk.encrypt(test.msg, test.r)
|
|||
|
if test.expectedPass {
|
|||
|
require.NoError(t, err)
|
|||
|
} else {
|
|||
|
require.Error(t, err)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Fail if N is nil
|
|||
|
pk = &PublicKey{N: nil, N2: nil}
|
|||
|
_, _, err = pk.Encrypt(crypto.One)
|
|||
|
require.Contains(t, err.Error(), "arguments cannot be nil")
|
|||
|
}
|
|||
|
|
|||
|
// Tests that each invocation of Encrypt() produces a distinct output
|
|||
|
func TestEncryptIsRandomized(t *testing.T) {
|
|||
|
pk, err := NewPubkey(N)
|
|||
|
require.NoError(t, err)
|
|||
|
msg := crypto.One
|
|||
|
|
|||
|
// Encrypt the same msg multiple times
|
|||
|
a0, _, err := pk.Encrypt(msg)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
a1, _, err := pk.Encrypt(msg)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
a2, _, err := pk.Encrypt(msg)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
// ❄️ ❄️ ❄️
|
|||
|
require.NotEqual(t, a0, a1)
|
|||
|
require.NotEqual(t, a0, a2)
|
|||
|
}
|
|||
|
|
|||
|
// Small number tests of Encrypt()
|
|||
|
func TestEncryptKnownAnswers(t *testing.T) {
|
|||
|
// N=3, NN=9
|
|||
|
z9, err := NewPubkey(big.NewInt(3))
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
var tests = []struct {
|
|||
|
m, r, expected *big.Int // m,r inputs
|
|||
|
}{
|
|||
|
// All operations below mod 9
|
|||
|
{big.NewInt(1), big.NewInt(1), big.NewInt(4)}, // c = (3+1)^1 * (1^3) = 4*1 = 4
|
|||
|
{big.NewInt(0), big.NewInt(1), big.NewInt(1)}, // c = (3+1)^0 * 1^3 = 1
|
|||
|
{big.NewInt(2), big.NewInt(2), big.NewInt(2)}, // c = (3+1)^2 * 2^3 = 16*8 ≡ -7 ≡ 2
|
|||
|
{big.NewInt(1), big.NewInt(2), big.NewInt(5)}, // c = (3+1)^1 * 2^3 = 4*8 ≡ 5
|
|||
|
}
|
|||
|
|
|||
|
// All the tests!
|
|||
|
for _, test := range tests {
|
|||
|
actual, err := z9.encrypt(test.m, test.r)
|
|||
|
require.NoError(t, err)
|
|||
|
require.Zero(t, test.expected.Cmp(actual))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Encrypt should succeed over a range of arbitrary, valid messages
|
|||
|
func TestEncryptSucceeds(t *testing.T) {
|
|||
|
pk, err := NewPubkey(N)
|
|||
|
require.NoError(t, err)
|
|||
|
iterations := 100
|
|||
|
for i := 0; i < iterations; i++ {
|
|||
|
msg, _ := crypto.Rand(pk.N)
|
|||
|
c, r, err := pk.Encrypt(msg)
|
|||
|
require.NoError(t, err)
|
|||
|
require.NotNil(t, c, r)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Tests the restrictions on input values for paillier.Decrypt
|
|||
|
func TestDecryptErrorConditions(t *testing.T) {
|
|||
|
pk, err := NewPubkey(N)
|
|||
|
require.NoError(t, err)
|
|||
|
// A fake secret key, but good enough to test parameter validation
|
|||
|
sk := &SecretKey{*pk, NplusOne, NplusOne, NplusOne}
|
|||
|
|
|||
|
var tests = []struct {
|
|||
|
c *big.Int
|
|||
|
expectedPass bool
|
|||
|
}{
|
|||
|
// Good: c ∈ Z_N²
|
|||
|
// TODO: Fix when L() param restrictions settled
|
|||
|
// {crypto.Zero, true},
|
|||
|
// {crypto.One, true},
|
|||
|
// {N, true},
|
|||
|
// {NplusOne, true},
|
|||
|
// {hundoN, true},
|
|||
|
// {NNminusOne, true},
|
|||
|
|
|||
|
// Bad
|
|||
|
{big.NewInt(-1), false}, // Negative
|
|||
|
{big.NewInt(-1000000), false}, // Negative
|
|||
|
{NN, false}, // c = N²
|
|||
|
{NNplusOne, false}, // c > N²
|
|||
|
{nil, false}, // nil
|
|||
|
}
|
|||
|
|
|||
|
// All the tests!
|
|||
|
for _, test := range tests {
|
|||
|
_, err := sk.Decrypt(test.c)
|
|||
|
if test.expectedPass {
|
|||
|
require.NoError(t, err)
|
|||
|
} else {
|
|||
|
require.Error(t, err)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// nil values in the SecretKey
|
|||
|
sk = &SecretKey{
|
|||
|
PublicKey: PublicKey{N: big.NewInt(100), N2: big.NewInt(10000)},
|
|||
|
Lambda: big.NewInt(200),
|
|||
|
Totient: nil,
|
|||
|
U: nil,
|
|||
|
}
|
|||
|
_, err = sk.Decrypt(crypto.One)
|
|||
|
require.Error(t, err)
|
|||
|
|
|||
|
// N = 0 is pub key
|
|||
|
sk = &SecretKey{
|
|||
|
PublicKey: PublicKey{N: big.NewInt(0), N2: big.NewInt(10000)},
|
|||
|
Lambda: big.NewInt(200),
|
|||
|
Totient: nil,
|
|||
|
U: nil,
|
|||
|
}
|
|||
|
_, err = sk.Decrypt(crypto.One)
|
|||
|
require.Contains(t, err.Error(), "N cannot be 0")
|
|||
|
}
|
|||
|
|
|||
|
// Decrypt·Encrypt is the identity function
|
|||
|
func TestEncryptDecryptRoundTrip(t *testing.T) {
|
|||
|
// Pre-computed safe primes
|
|||
|
p := tt.B10("133788347333574532510542341875219452703250094560184213896952738579939377079849213618116996737030817731544214409221015150233522821287955673536671953914660520267670984696713816508768479853621956967492030516224494353641551367310541202655075859386716364585825364092974073148178887544704793573033779774765431460367")
|
|||
|
q := tt.B10("121400263190232595456200749546561304956161672968687911935494950378721768184159069938532869288284686583150658925255722159156454219960265942696166947144912738151554579878178746701374346180640493532962639632666540478486867810588884360492830920363713588684509182704981665082591486786717530494254613085570321507623")
|
|||
|
n := tt.B10("16241940578082201531943448855852277578391761356628379864603641922876623601321625229339135653813019543205064366507109899018615521640687222340376734033815591736764469510811142260074144789284382858541066390183237904579674336717818949214144339382239132186500111594251680147962383065732964214151653795512167674648653475620307856642151695559944756719719799945193072239010815330021803557074201060705849949820706127488164694762724694756011467249889383401729777382247223470577114290663770295230883950621358271613200219512401437571399087878832070221157976750549142719310423012055140771277730139053532825828483343855582012877641")
|
|||
|
nMinusOne := new(big.Int).Sub(n, crypto.One)
|
|||
|
// Artbitrary value < 2^1024
|
|||
|
x := tt.B10("20317113632585528798845062224869200275863225217624919914930609441107430244099181911960782321973293974573717329695193847701610218076524443400374940131739854056496412361090757880543495337916419061120521895395069964501013582917510846097488944684808895337780780147474736309539340360589608026856645992290890400384")
|
|||
|
|
|||
|
// Create sk, pk for testing
|
|||
|
sk, err := NewSecretKey(p, q)
|
|||
|
require.NoError(t, err)
|
|||
|
pk, err := NewPubkey(n)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
// Valid msgs ∈ Z_N
|
|||
|
msgs := []*big.Int{
|
|||
|
crypto.Zero,
|
|||
|
crypto.One,
|
|||
|
nMinusOne,
|
|||
|
x,
|
|||
|
}
|
|||
|
|
|||
|
// All the tests!
|
|||
|
for _, m := range msgs {
|
|||
|
// Encrypt,validate
|
|||
|
c, _, err := pk.Encrypt(m)
|
|||
|
require.NoError(t, err)
|
|||
|
require.NotNil(t, c)
|
|||
|
|
|||
|
// Decrypt-validate
|
|||
|
actual, err := sk.Decrypt(c)
|
|||
|
require.NoError(t, err)
|
|||
|
require.Equal(t, m, actual)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestSerializePublicKeyWorks(t *testing.T) {
|
|||
|
n := tt.B10("16241940578082201531943448855852277578391761356628379864603641922876623601321625229339135653813019543205064366507109899018615521640687222340376734033815591736764469510811142260074144789284382858541066390183237904579674336717818949214144339382239132186500111594251680147962383065732964214151653795512167674648653475620307856642151695559944756719719799945193072239010815330021803557074201060705849949820706127488164694762724694756011467249889383401729777382247223470577114290663770295230883950621358271613200219512401437571399087878832070221157976750549142719310423012055140771277730139053532825828483343855582012877641")
|
|||
|
pk, err := NewPubkey(n)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
data, err := pk.MarshalJSON()
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
pk2 := new(PublicKey)
|
|||
|
require.NoError(t, pk2.UnmarshalJSON(data))
|
|||
|
require.Equal(t, pk2, pk)
|
|||
|
require.NoError(t, pk2.UnmarshalJSON([]byte(`{"N":1251}`)))
|
|||
|
}
|
|||
|
|
|||
|
func TestSerializePublicKeyIgnoreFields(t *testing.T) {
|
|||
|
tests := [][]byte{
|
|||
|
[]byte(`{}`),
|
|||
|
[]byte(`{"a":null}`),
|
|||
|
[]byte(`{"n":null}`),
|
|||
|
[]byte(`{"N":null}`),
|
|||
|
}
|
|||
|
pk := new(PublicKey)
|
|||
|
for _, test := range tests {
|
|||
|
require.NoError(t, pk.UnmarshalJSON(test))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestSerializeSecretKeyWorks(t *testing.T) {
|
|||
|
p := tt.B10("133788347333574532510542341875219452703250094560184213896952738579939377079849213618116996737030817731544214409221015150233522821287955673536671953914660520267670984696713816508768479853621956967492030516224494353641551367310541202655075859386716364585825364092974073148178887544704793573033779774765431460367")
|
|||
|
q := tt.B10("121400263190232595456200749546561304956161672968687911935494950378721768184159069938532869288284686583150658925255722159156454219960265942696166947144912738151554579878178746701374346180640493532962639632666540478486867810588884360492830920363713588684509182704981665082591486786717530494254613085570321507623")
|
|||
|
sk, err := NewSecretKey(p, q)
|
|||
|
require.NoError(t, err)
|
|||
|
|
|||
|
data, err := sk.MarshalJSON()
|
|||
|
require.NoError(t, err)
|
|||
|
sk2 := new(SecretKey)
|
|||
|
require.NoError(t, sk2.UnmarshalJSON(data))
|
|||
|
require.Equal(t, sk2, sk)
|
|||
|
require.NoError(t, sk2.UnmarshalJSON([]byte(`{"N":2,"Totient":1,"U":1,"Lambda":1}`)))
|
|||
|
}
|
|||
|
|
|||
|
func TestSerializeSecretKeyIgnoreFields(t *testing.T) {
|
|||
|
tests := [][]byte{
|
|||
|
[]byte(`{}`),
|
|||
|
[]byte(`{"a":null}`),
|
|||
|
[]byte(`{"n":null}`),
|
|||
|
[]byte(`{"N":null}`),
|
|||
|
[]byte(`{"N":null,"U":1}`),
|
|||
|
}
|
|||
|
sk := new(SecretKey)
|
|||
|
for _, test := range tests {
|
|||
|
require.NoError(t, sk.UnmarshalJSON(test))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestSerializationErrorConditions(t *testing.T) {
|
|||
|
pk := new(PublicKey)
|
|||
|
require.Error(t, pk.UnmarshalJSON([]byte(`invalid`)))
|
|||
|
|
|||
|
sk := new(SecretKey)
|
|||
|
require.Error(t, sk.UnmarshalJSON([]byte(`invalid`)))
|
|||
|
}
|
|||
|
|
|||
|
func TestNewSecretKeyErrorConditions(t *testing.T) {
|
|||
|
testArgs := []lcmTest{
|
|||
|
{
|
|||
|
x: nil,
|
|||
|
y: big.NewInt(1),
|
|||
|
},
|
|||
|
{
|
|||
|
x: big.NewInt(1),
|
|||
|
y: nil,
|
|||
|
},
|
|||
|
{
|
|||
|
x: nil,
|
|||
|
y: nil,
|
|||
|
},
|
|||
|
}
|
|||
|
for _, arg := range testArgs {
|
|||
|
_, err := NewSecretKey(arg.x, arg.y)
|
|||
|
require.Contains(t, err.Error(), "arguments cannot be nil")
|
|||
|
}
|
|||
|
}
|