package paillier import ( "crypto/rand" "encoding/hex" "math/big" "testing" "time" "github.com/stretchr/testify/assert" "xdx.jelly/xgcl/grand" "xdx.jelly/xgcl/sm/sm2" ) func bigFromBase16(s string) *big.Int { b, err := hex.DecodeString(s) if err != nil { panic(err) } return new(big.Int).SetBytes(b) } var p = bigFromBase16("ff03b1a74827c746db83d2eaff00067622f545b62584321256e62b01509f1096" + "2f9c5c8fd0b7f5184a9ce8e81f439df47dda14563dd55a221799d2aa57ed2713" + "271678a5a0b8b40a84ad13d5b6e6599e6467c670109cf1f45ccfed8f75ea3b81" + "4548ab294626fe4d14ff764dd8b091f11a0943a2dd2b983b0df02f4c4d00b413") var q = bigFromBase16("dacaabc1dc57faa9fd6a4274c4d588765a1d3311c22e57d8101431b07eb3ddcb" + "05d77d9a742ac2322fe6a063bd1e05acb13b0fe91c70115c2b1eee1155e07252" + "7011a5f849de7072a1ce8e6b71db525fbcda7a89aaed46d27aca5eaeaf35a262" + "70a4a833c5cda681ffd49baa0f610bad100cdf47cc86e5034e2a0b2179e04ec7") var n = new(big.Int).Mul(p, q) var lambda = new(big.Int) // lcm(lambda, new(big.Int).Sub(p, gmath.BigInt1), new(big.Int).Sub(q, gmath.BigInt1)) func TestPaillier(t *testing.T) { // pk, sk := GenerateKey(1024) sk, err := GenerateKeyFromPassword(2048, grand.GetRandom(32), grand.GetRandom(32), 1024) assert.Nil(t, err) pk := sk.Public() m1, _ := rand.Int(grand.Reader, pk.N) m2, _ := rand.Int(grand.Reader, pk.N) c1, _ := Encrypt(m1, pk, grand.Reader) c2, _ := Encrypt(m2, pk, grand.Reader) c := new(Cipher).HomomorphicAdd(c1, c2, pk) m, _ := Decrypt(c, sk) mm := new(big.Int).Add(m1, m2) mm.Mod(mm, pk.N) assert.Zero(t, m.Cmp(mm)) } func TestKeyMarshal(t *testing.T) { sk, pk, err := GenerateKey(2048, grand.Reader) assert.Nil(t, err) assert.Equal(t, pk.Size(), uint(2048)) skBytes, err := sk.Marshal() assert.Nil(t, err) sk2 := new(PrivateKey) assert.Nil(t, sk2.Unmarshal(skBytes)) assert.Zero(t, sk.p.Cmp(sk2.p)|sk.q.Cmp(sk2.q)|sk.lambda.Cmp(sk2.lambda)|sk.lambdaInv.Cmp(sk2.lambdaInv)) pkBytes, err := pk.Marshal() assert.Nil(t, err) pk2 := new(PublicKey) assert.Nil(t, pk2.Unmarshal(pkBytes)) assert.Zero(t, pk.N.Cmp(pk2.N)|pk.N2.Cmp(pk2.N2)) } func TestPaillierScalarMul(t *testing.T) { sk, err := GenerateKeyFromPassword(2048, grand.GetRandom(32), grand.GetRandom(32), 1024) assert.Nil(t, err) pk := sk.Public() limit := big.NewInt(1) limit.Lsh(limit, 256) ch := time.After(3 * time.Second) done := false for !done { select { case <-ch: done = true default: m, _ := rand.Int(grand.Reader, limit) k, _ := rand.Int(grand.Reader, limit) c, _ := Encrypt(m, pk, grand.Reader) c.HomomorphicScalarMul(c, k, sk.Public()) m1, err := Decrypt(c, sk) assert.Nil(t, err) m2 := new(big.Int).Mul(m, k) assert.Zero(t, m1.Cmp(m2)) } } } func BenchmarkParallelPaillierEnc(b *testing.B) { _, pk, _ := GenerateKey(2048, grand.Reader) m, _ := rand.Int(grand.Reader, pk.N) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { Encrypt(m, pk, grand.Reader) } }) } func BenchmarkPaillierEnc(b *testing.B) { _, pk, _ := GenerateKey(2048, grand.Reader) m, _ := rand.Int(grand.Reader, pk.N) b.ResetTimer() for i := 0; i < b.N; i++ { Encrypt(m, pk, grand.Reader) } } func BenchmarkPaillierDec(b *testing.B) { sk, pk, _ := GenerateKey(2048, grand.Reader) m, _ := rand.Int(grand.Reader, pk.N) c, _ := Encrypt(m, pk, grand.Reader) b.ResetTimer() for i := 0; i < b.N; i++ { Decrypt(c, sk) } } func BenchmarkPaillierHomomorphicScalarMul(b *testing.B) { sk, pk, _ := GenerateKey(2048, grand.Reader) limit := big.NewInt(1) limit.Lsh(limit, 256) m, _ := rand.Int(grand.Reader, limit) c, _ := Encrypt(m, pk, grand.Reader) k, _ := rand.Int(grand.Reader, limit) b.ResetTimer() for i := 0; i < b.N; i++ { c.HomomorphicScalarMul(c, k, sk.Public()) } } func TestPaillierHomomorphicEncSpeed(t *testing.T) { _, pk, _ := GenerateKey(2048, grand.Reader) m, _ := rand.Int(grand.Reader, pk.N) times := 1000 start := time.Now() for i := 0; i < times; i++ { Encrypt(m, pk, grand.Reader) } end := time.Now() elapsed := end.Sub(start) t.Logf("HomomorphicScalarMul: %.2f per second\n", float64(times)/elapsed.Seconds()) } func TestPaillierHomomorphicScalarMulSpeed(t *testing.T) { _, pk, _ := GenerateKey(2048, grand.Reader) limit := big.NewInt(1) limit.Lsh(limit, 256) m, _ := rand.Int(grand.Reader, limit) c, _ := Encrypt(m, pk, grand.Reader) k, _ := rand.Int(grand.Reader, limit) times := 1000 start := time.Now() for i := 0; i < times; i++ { c.HomomorphicScalarMul(c, k, pk) } end := time.Now() elapsed := end.Sub(start) t.Logf("HomomorphicScalarMul: %.2f per second\n", float64(times)/elapsed.Seconds()) } func BenchmarkBlind1(b *testing.B) { _, pk, _ := GenerateKey(2048, grand.Reader) limit := big.NewInt(1) limit.Lsh(limit, 256) k, _ := rand.Int(grand.Reader, limit) nc, _ := pk.Encrypt(sm2.OrderN(), grand.Reader) b.ResetTimer() for i := 0; i < b.N; i++ { (&Cipher{}).HomomorphicScalarMul(nc, k, pk) } } func BenchmarkBlind2(b *testing.B) { _, pk, _ := GenerateKey(2048, grand.Reader) limit := big.NewInt(1) limit.Lsh(limit, 256) k, _ := rand.Int(grand.Reader, limit) kn := new(big.Int).Mul(k, sm2.OrderN()) b.ResetTimer() for i := 0; i < b.N; i++ { kn.Mul(k, sm2.OrderN()) pk.Encrypt(kn, grand.Reader) } } // func BenchmarkGMPIntExp(b *testing.B) { // sk, _, _ := GenerateKey(2048, grand.Reader) // n := gmp.NewInt(1).SetBytes(sk.N.Bytes()) // n2 := gmp.NewInt(1).Mul(n, n) // r := gmp.NewInt(1).SetBytes(grand.GetRandom(128)) // b.ResetTimer() // for i := 0; i < b.N; i++ { // r.Exp(r, n, n2) // } // } func BenchmarkIntExp(b *testing.B) { sk, _, _ := GenerateKey(2048, grand.Reader) n := sk.N n2 := sk.N2 r := new(big.Int).SetBytes(grand.GetRandom(128)) b.ResetTimer() for i := 0; i < b.N; i++ { r.Exp(r, n, n2) } } func TestGenerateKeyFromPassword(t *testing.T) { b, _ := hex.DecodeString("12345678abcdef") sk, _ := GenerateKeyFromPassword(2048, []byte("1234567812345678"), b, 1024) assert.Equal(t, sk.N.Text(16), "86257d4f684edb672420a6e0d6a6e66b00a316080c0b025d96e9d22c57d6fc7166bcddc07dadc2f0dca7440c6f43a90fab494ea810304af2abc18d54bcdeb8803c8c245270d70b897f3bf2e43c3a5e9d777fb256f84cf5b4705cba19283952dd10aa2b15793a401195ee2a418b999bbf72e35bd94f48267597ab7cfb699b3bbab78a6201a9ee18a22d25e841a66c54d5ebf45c10491ea43cca5e9e6f487c7aedc24d15cda20e6f80a755477b6e2b1d1a9e669ba0773bb31e2fb76e550fdef1be4d02ec820aba5ebfbfd0fbb37bd1c748af1f4a0c17f5cfb41e4cb44a05587bcff2937415eb2e13398da514224def6c03f61a07319512362912caa08bded076dd") assert.Equal(t, sk.Size(), uint(2048)) }