ceremonyclient/nekryptology/pkg/paillier/paillier_test.go
2023-07-05 00:32:28 -05:00

1086 lines
42 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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")
}
}