Files
zeekay eeaa2a1c07 fix: resolve go vet and formatting issues
- Fix go vet error in lss_bench_test.go: replace b.Fatal with panic in goroutine
- Fix go vet error in lss_test.go: remove t.Skip call from goroutine
- Apply gofmt to all files to fix formatting issues

All go vet errors and formatting issues have been resolved.
2025-08-05 17:59:18 -05:00

206 lines
4.9 KiB
Go

package paillier
import (
"crypto/rand"
"testing"
"testing/quick"
"github.com/cronokirby/saferith"
"github.com/luxfi/threshold/pkg/math/sample"
"github.com/luxfi/threshold/pkg/pool"
"github.com/stretchr/testify/assert"
)
var (
paillierPublic *PublicKey
paillierSecret *SecretKey
)
func init() {
p, _ := new(saferith.Nat).SetHex("FD90167F42443623D284EA828FB13E374CBF73E16CC6755422B97640AB7FC77FDAF452B4F3A2E8472614EEE11CC8EAF48783CE2B4876A3BB72E9ACF248E86DAA5CE4D5A88E77352BCBA30A998CD8B0AD2414D43222E3BA56D82523E2073730F817695B34A4A26128D5E030A7307D3D04456DC512EBB8B53FDBD1DFC07662099B")
q, _ := new(saferith.Nat).SetHex("DB531C32024A262A0DF9603E48C79E863F9539A82B8619480289EC38C3664CC63E3AC2C04888827559FFDBCB735A8D2F1D24BAF910643CE819452D95CAFFB686E6110057985E93605DE89E33B99C34140EF362117F975A5056BFF14A51C9CD16A4961BE1F02C081C7AD8B2A5450858023A157AFA3C3441E8E00941F8D33ED6B7")
paillierSecret = NewSecretKeyFromPrimes(p, q)
paillierPublic = paillierSecret.PublicKey
if err := ValidatePrime(p); err != nil {
panic(err)
}
if err := ValidatePrime(q); err != nil {
panic(err)
}
}
func reinit() {
pl := pool.NewPool(0)
defer pl.TearDown()
paillierPublic, paillierSecret = KeyGen(pl)
}
func TestCiphertextValidate(t *testing.T) {
if !testing.Short() {
reinit()
}
C := new(saferith.Nat)
ct := &Ciphertext{C}
_, err := paillierSecret.Dec(ct)
assert.Error(t, err, "decrypting 0 should fail")
C.SetNat(paillierPublic.nNat)
_, err = paillierSecret.Dec(ct)
assert.Error(t, err, "decrypting N should fail")
C.Add(C, C, -1)
_, err = paillierSecret.Dec(ct)
assert.Error(t, err, "decrypting 2N should fail")
C.SetNat(paillierPublic.nSquared.Nat())
_, err = paillierSecret.Dec(ct)
assert.Error(t, err, "decrypting N^2 should fail")
}
func testEncDecRoundTrip(x uint64, xNeg bool) bool {
m := new(saferith.Int).SetUint64(x)
if xNeg {
m.Neg(1)
}
ciphertext, _ := paillierPublic.Enc(m)
shouldBeM, err := paillierSecret.Dec(ciphertext)
if err != nil {
return false
}
return m.Eq(shouldBeM) == 1
}
func TestEncDecRoundTrip(t *testing.T) {
if !testing.Short() {
reinit()
}
err := quick.Check(testEncDecRoundTrip, &quick.Config{
MaxCount: 10, // Limit test cases to prevent timeout
})
if err != nil {
t.Error(err)
}
}
func testEncDecHomomorphic(a, b uint64, aNeg, bNeg bool) bool {
ma := new(saferith.Int).SetUint64(a)
if aNeg {
ma.Neg(1)
}
mb := new(saferith.Int).SetUint64(b)
if bNeg {
mb.Neg(1)
}
ca, _ := paillierPublic.Enc(ma)
cb, _ := paillierPublic.Enc(mb)
expected := new(saferith.Int).Add(ma, mb, -1)
actual, err := paillierSecret.Dec(ca.Add(paillierPublic, cb))
if err != nil {
return false
}
return actual.Eq(expected) == 1
}
func TestEncDecHomomorphic(t *testing.T) {
if !testing.Short() {
reinit()
}
err := quick.Check(testEncDecHomomorphic, &quick.Config{
MaxCount: 10, // Limit test cases to prevent timeout
})
if err != nil {
t.Error(err)
}
}
func testEncDecScalingHomomorphic(s, x uint64, sNeg, xNeg bool) bool {
m := new(saferith.Int).SetUint64(x)
if xNeg {
m.Neg(1)
}
sInt := new(saferith.Int).SetUint64(s)
if sNeg {
sInt.Neg(1)
}
c, _ := paillierPublic.Enc(m)
expected := new(saferith.Int).Mul(m, sInt, -1)
actual, err := paillierSecret.Dec(c.Mul(paillierPublic, sInt))
if err != nil {
return false
}
return actual.Eq(expected) == 1
}
func TestEncDecScalingHomomorphic(t *testing.T) {
if !testing.Short() {
reinit()
}
err := quick.Check(testEncDecScalingHomomorphic, &quick.Config{
MaxCount: 10, // Limit test cases to prevent timeout
})
if err != nil {
t.Error(err)
}
}
func testDecWithRandomness(x, r uint64) bool {
mExpected := new(saferith.Int).SetUint64(x)
nonceExpected := new(saferith.Nat).SetUint64(r)
c := paillierPublic.EncWithNonce(mExpected, nonceExpected)
mActual, nonceActual, err := paillierSecret.DecWithRandomness(c)
if err != nil {
return false
}
if mActual.Eq(mExpected) != 1 {
return false
}
if nonceActual.Eq(nonceExpected) != 1 {
return false
}
return true
}
func TestDecWithRandomness(t *testing.T) {
if !testing.Short() {
reinit()
}
err := quick.Check(testDecWithRandomness, &quick.Config{
MaxCount: 10, // Limit test cases to prevent timeout
})
if err != nil {
t.Error(err)
}
}
// Used to avoid benchmark optimization.
var resultCiphertext *Ciphertext
func BenchmarkEncryption(b *testing.B) {
b.StopTimer()
m := sample.IntervalLEps(rand.Reader)
b.StartTimer()
for i := 0; i < b.N; i++ {
resultCiphertext, _ = paillierPublic.Enc(m)
}
}
func BenchmarkAddCiphertext(b *testing.B) {
b.StopTimer()
m := sample.IntervalLEps(rand.Reader)
c, _ := paillierPublic.Enc(m)
b.StartTimer()
for i := 0; i < b.N; i++ {
resultCiphertext = c.Add(paillierPublic, c)
}
}
func BenchmarkMulCiphertext(b *testing.B) {
b.StopTimer()
m := sample.IntervalLEps(rand.Reader)
c, _ := paillierPublic.Enc(m)
b.StartTimer()
for i := 0; i < b.N; i++ {
resultCiphertext = c.Mul(paillierPublic, m)
}
}