Files
zeekay 101c01a0f8 fix: resolve lint errors and improve code quality
- Fix variable naming issues (no underscores in Go names)
- Fix receiver naming consistency
- Fix unused parameters
- Fix error handling (add error checks)
- Fix comment formatting (godot)
- Fix type assertions
- Run goimports on files
- Update internal/ot field names to follow Go conventions
2025-08-06 02:00:20 -05:00

192 lines
4.1 KiB
Go
Raw Permalink 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.
package zkencelg
import (
"crypto/rand"
"github.com/cronokirby/saferith"
"github.com/luxfi/threshold/pkg/hash"
"github.com/luxfi/threshold/pkg/math/arith"
"github.com/luxfi/threshold/pkg/math/curve"
"github.com/luxfi/threshold/pkg/math/sample"
"github.com/luxfi/threshold/pkg/paillier"
"github.com/luxfi/threshold/pkg/pedersen"
)
type Public struct {
// C = Enc(x;ρ)
C *paillier.Ciphertext
// A = a⋅G
A curve.Point
// B = b⋅G
B curve.Point
// X = (ab+x)⋅G
X curve.Point
Prover *paillier.PublicKey
Aux *pedersen.Parameters
}
type Private struct {
// X = x = Dec(C)
X *saferith.Int
// Rho = ρ = Nonce(C)
Rho *saferith.Nat
// A = a
A curve.Scalar
// B = b
B curve.Scalar
}
type Commitment struct {
// S = sˣtᵘ
S *saferith.Nat
// D = Enc(α, r)
D *paillier.Ciphertext
// Y = β⋅A+α⋅G
Y curve.Point
// Z = β⋅G
Z curve.Point
// C = sᵃtᵍ
T *saferith.Nat
}
type Proof struct {
group curve.Curve
*Commitment
// Z1 = z₁ = α + ex
Z1 *saferith.Int
// W = w = β + eb (mod q)
W curve.Scalar
// Z2 = z₂ = r⋅ρᵉ (mod N₀)
Z2 *saferith.Nat
// Z3 = z₃ = γ + eμ
Z3 *saferith.Int
}
func (p *Proof) IsValid(public Public) bool {
if p == nil {
return false
}
if !public.Prover.ValidateCiphertexts(p.D) {
return false
}
if p.W.IsZero() || p.Y.IsIdentity() || p.Z.IsIdentity() {
return false
}
if !arith.IsValidNatModN(public.Prover.N(), p.Z2) {
return false
}
return true
}
func NewProof(group curve.Curve, hash *hash.Hash, public Public, private Private) *Proof {
N := public.Prover.N()
NModulus := public.Prover.Modulus()
alpha := sample.IntervalLEps(rand.Reader)
alphaScalar := group.NewScalar().SetNat(alpha.Mod(group.Order()))
mu := sample.IntervalLN(rand.Reader)
r := sample.UnitModN(rand.Reader, N)
beta := sample.Scalar(rand.Reader, group)
gamma := sample.IntervalLEpsN(rand.Reader)
commitment := &Commitment{
S: public.Aux.Commit(private.X, mu),
D: public.Prover.EncWithNonce(alpha, r),
Y: beta.Act(public.A).Add(alphaScalar.ActOnBase()),
Z: beta.ActOnBase(),
T: public.Aux.Commit(alpha, gamma),
}
e, _ := challenge(hash, group, public, commitment)
z1 := new(saferith.Int).SetInt(private.X)
z1.Mul(e, z1, -1)
z1.Add(z1, alpha, -1)
w := group.NewScalar().SetNat(e.Mod(group.Order())).Mul(private.B).Add(beta)
z2 := NModulus.ExpI(private.Rho, e)
z2.ModMul(z2, r, N)
z3 := new(saferith.Int).Mul(e, mu, -1)
z3.Add(z3, gamma, -1)
return &Proof{
group: group,
Commitment: commitment,
Z1: z1,
W: w,
Z2: z2,
Z3: z3,
}
}
func (p *Proof) Verify(hash *hash.Hash, public Public) bool {
if !p.IsValid(public) {
return false
}
prover := public.Prover
if !arith.IsInIntervalLEps(p.Z1) {
return false
}
e, err := challenge(hash, p.group, public, p.Commitment)
if err != nil {
return false
}
group := p.group
q := group.Order()
eScalar := group.NewScalar().SetNat(e.Mod(q))
{
lhs := prover.EncWithNonce(p.Z1, p.Z2) // lhs = Enc(z₁;z₂)
rhs := public.C.Clone().Mul(prover, e).Add(prover, p.D) // rhs = (e ⊙ C) ⊕ D
if !lhs.Equal(rhs) {
return false
}
}
{
z1 := group.NewScalar().SetNat(p.Z1.Mod(q))
lhs := z1.ActOnBase().Add(p.W.Act(public.A)) // lhs = w⋅A+z₁⋅G
rhs := eScalar.Act(public.X).Add(p.Y) // rhs = Y+e⋅X
if !lhs.Equal(rhs) {
return false
}
}
{
lhs := p.W.ActOnBase() // lhs = w⋅G
rhs := eScalar.Act(public.B).Add(p.Z) // rhs = Z+e⋅B
if !lhs.Equal(rhs) {
return false
}
}
return public.Aux.Verify(p.Z1, p.Z3, e, p.T, p.S)
}
func challenge(hash *hash.Hash, group curve.Curve, public Public, commitment *Commitment) (e *saferith.Int, err error) {
err = hash.WriteAny(public.Aux, public.Prover, public.C, public.A, public.B, public.X,
commitment.S, commitment.D, commitment.Y, commitment.Z, commitment.T)
e = sample.IntervalScalar(hash.Digest(), group)
return
}
func Empty(group curve.Curve) *Proof {
return &Proof{
group: group,
Commitment: &Commitment{
Y: group.NewPoint(),
Z: group.NewPoint(),
},
W: group.NewScalar(),
}
}