ceremonyclient/nekryptology/pkg/paillier/paillier_test.go

1086 lines
42 KiB
Go
Raw Normal View History

2023-07-05 05:32:28 +00:00
//
// 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")
}
}