Skip to content

Commit

Permalink
Merge pull request #4 from sei-protocol/mj/audit
Browse files Browse the repository at this point in the history
Add validations for zero values
  • Loading branch information
mj850 authored Dec 4, 2024
2 parents ef88c69 + 9d53ea4 commit e566c8f
Show file tree
Hide file tree
Showing 13 changed files with 343 additions and 42 deletions.
47 changes: 35 additions & 12 deletions pkg/zkproofs/ciphertext_ciphertext_equality.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package zkproofs

import (
"crypto/rand"
"encoding/json"
"errors"

"github.com/coinbase/kryptology/pkg/core/curves"
"github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal"
)
Expand Down Expand Up @@ -67,10 +67,19 @@ func NewCiphertextCiphertextEqualityProof(
r := *destinationOpening

// Generate random scalars
ed25519 := curves.ED25519()
ys := ed25519.Scalar.Random(rand.Reader)
yx := ed25519.Scalar.Random(rand.Reader)
yr := ed25519.Scalar.Random(rand.Reader)
curve := curves.ED25519()
ys, err := GenerateRandomNonZeroScalar(curve)
if err != nil {
return nil, err
}
yx, err := GenerateRandomNonZeroScalar(curve)
if err != nil {
return nil, err
}
yr, err := GenerateRandomNonZeroScalar(curve)
if err != nil {
return nil, err
}

eg := elgamal.NewTwistedElgamal()
G := eg.GetG()
Expand Down Expand Up @@ -133,16 +142,15 @@ func VerifyCiphertextCiphertextEquality(
sourceCiphertext *elgamal.Ciphertext,
destinationCiphertext *elgamal.Ciphertext,
) bool {
// validate proof for nil values
if proof == nil || proof.Y0 == nil || proof.Y1 == nil || proof.Y2 == nil || proof.Y3 == nil || proof.Zs == nil ||
proof.Zx == nil || proof.Zr == nil {
// validate inputs
if proof == nil || sourcePubKey == nil || destinationPubKey == nil ||
sourceCiphertext == nil || sourceCiphertext.C == nil || sourceCiphertext.D == nil ||
destinationCiphertext == nil || destinationCiphertext.C == nil || destinationCiphertext.D == nil {
return false
}

// validate other input
if sourcePubKey == nil || destinationPubKey == nil ||
sourceCiphertext == nil || sourceCiphertext.C == nil || sourceCiphertext.D == nil ||
destinationCiphertext == nil || destinationCiphertext.C == nil || destinationCiphertext.D == nil {
// validate proof for nil and zero values
if !proof.validateContents() {
return false
}

Expand Down Expand Up @@ -213,6 +221,21 @@ func VerifyCiphertextCiphertextEquality(
return lhsY3.Equal(rhsY3)
}

func (c *CiphertextCiphertextEqualityProof) validateContents() bool {
// Validate that fields are not nil
if c == nil || c.Y0 == nil || c.Y1 == nil || c.Y2 == nil || c.Y3 == nil || c.Zs == nil ||
c.Zx == nil || c.Zr == nil {
return false
}

// Validate that fields are non zero. Though it is technically possible if the randomly generated scalars are zero, it is highly unlikely (1 in 2^255 chance)
if c.Y0.IsIdentity() || c.Y1.IsIdentity() || c.Y2.IsIdentity() || c.Y3.IsIdentity() || c.Zr.IsZero() || c.Zs.IsZero() || c.Zx.IsZero() {
return false
}

return true
}

// MarshalJSON for CiphertextCiphertextEqualityProof
func (p *CiphertextCiphertextEqualityProof) MarshalJSON() ([]byte, error) {
// Serialize the points and scalars to a format you prefer
Expand Down
36 changes: 36 additions & 0 deletions pkg/zkproofs/ciphertext_ciphertext_equality_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,4 +415,40 @@ func TestVerifyCiphertextCiphertextEquality_InvalidInputs(t *testing.T) {
)
require.False(t, valid, "Proof verification should fail for nil destination ciphertext")
})

t.Run("Invalid Proof Params", func(t *testing.T) {
// Y2 is zero point
clone := *proof
clone.Y2 = curves.ED25519().NewIdentityPoint()
valid := VerifyCiphertextCiphertextEquality(
&clone,
&sourceKeypair.PublicKey,
&destinationKeypair.PublicKey,
sourceCiphertext,
sourceCiphertext,
)
require.False(t, valid, "Proof verification should fail for proof params with zero value")

clone = *proof
clone.Zx = curves.ED25519().Scalar.Zero()
valid = VerifyCiphertextCiphertextEquality(
&clone,
&sourceKeypair.PublicKey,
&destinationKeypair.PublicKey,
sourceCiphertext,
sourceCiphertext,
)
require.False(t, valid, "Proof verification should fail for proof params with zero value")

clone = *proof
clone.Y1 = nil
valid = VerifyCiphertextCiphertextEquality(
&clone,
&sourceKeypair.PublicKey,
&destinationKeypair.PublicKey,
sourceCiphertext,
sourceCiphertext,
)
require.False(t, valid, "Proof verification should fail for proof params with zero value")
})
}
42 changes: 32 additions & 10 deletions pkg/zkproofs/ciphertext_commitment_equality.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package zkproofs

import (
"crypto/rand"
"encoding/json"
"errors"

"github.com/coinbase/kryptology/pkg/core/curves"
"github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal"
)
Expand Down Expand Up @@ -59,11 +59,22 @@ func NewCiphertextCommitmentEqualityProof(
G := eg.GetG() // Fixed base point G
H := eg.GetH() // Fixed base point H

ed25519 := curves.ED25519()
// Generate random masking factors
ys := ed25519.Scalar.Random(rand.Reader)
yx := ed25519.Scalar.Random(rand.Reader)
yr := ed25519.Scalar.Random(rand.Reader)
curve := curves.ED25519()
ys, err := GenerateRandomNonZeroScalar(curve)
if err != nil {
return nil, err
}

yx, err := GenerateRandomNonZeroScalar(curve)
if err != nil {
return nil, err
}

yr, err := GenerateRandomNonZeroScalar(curve)
if err != nil {
return nil, err
}

// Compute Y0 = ys * P
Y0 := P.Mul(ys)
Expand Down Expand Up @@ -118,14 +129,13 @@ func VerifyCiphertextCommitmentEquality(
sourceCiphertext *elgamal.Ciphertext,
pedersenCommitment *curves.Point,
) bool {
// Validate proof
if proof == nil || proof.Y0 == nil || proof.Y1 == nil || proof.Y2 == nil || proof.Zs == nil || proof.Zx == nil ||
proof.Zr == nil {
// Validate input
if proof == nil || sourcePubKey == nil || sourceCiphertext == nil || pedersenCommitment == nil {
return false
}

// Validate input
if sourcePubKey == nil || sourceCiphertext == nil || pedersenCommitment == nil {
// Validate proof
if !proof.validateContents() {
return false
}

Expand Down Expand Up @@ -176,6 +186,18 @@ func VerifyCiphertextCommitmentEquality(
return lhsY2.Equal(rhsY2)
}

func (c *CiphertextCommitmentEqualityProof) validateContents() bool {
if c.Y0 == nil || c.Y1 == nil || c.Y2 == nil || c.Zs == nil || c.Zx == nil || c.Zr == nil {
return false
}

if c.Y0.IsIdentity() || c.Y1.IsIdentity() || c.Y2.IsIdentity() || c.Zs.IsZero() || c.Zx.IsZero() || c.Zr.IsZero() {
return false
}

return true
}

// MarshalJSON for CiphertextCommitmentEqualityProof
func (p *CiphertextCommitmentEqualityProof) MarshalJSON() ([]byte, error) {
// Serialize the points and scalars to a format you prefer
Expand Down
33 changes: 33 additions & 0 deletions pkg/zkproofs/ciphertext_commitment_equality_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,39 @@ func TestVerifyCiphertextCommitmentEquality_InvalidInput(t *testing.T) {
require.False(t, valid, "Proof verification should fail for proof with nil fields")
})

t.Run("Invalid Proof Params", func(t *testing.T) {
// Y2 is zero point
clone := *proof
clone.Y2 = curves.ED25519().NewIdentityPoint()
valid := VerifyCiphertextCommitmentEquality(
&clone,
&sourceKeypair.PublicKey,
sourceCiphertext,
&sourceCiphertext.C,
)
require.False(t, valid, "Proof verification should fail for proof params with zero value")

clone = *proof
clone.Zx = curves.ED25519().Scalar.Zero()
valid = VerifyCiphertextCommitmentEquality(
&clone,
&sourceKeypair.PublicKey,
sourceCiphertext,
&sourceCiphertext.C,
)
require.False(t, valid, "Proof verification should fail for proof params with zero value")

clone = *proof
clone.Y1 = nil
valid = VerifyCiphertextCommitmentEquality(
&clone,
&sourceKeypair.PublicKey,
sourceCiphertext,
&sourceCiphertext.C,
)
require.False(t, valid, "Proof verification should fail for proof params with zero value")
})

t.Run("Invalid Source Public Key", func(t *testing.T) {
// Source public key is nil
valid := VerifyCiphertextCommitmentEquality(
Expand Down
32 changes: 27 additions & 5 deletions pkg/zkproofs/ciphertext_validity.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package zkproofs

import (
crand "crypto/rand"
"encoding/json"
"errors"
"math/big"
Expand Down Expand Up @@ -48,8 +47,16 @@ func NewCiphertextValidityProof(pedersenOpening *curves.Scalar, pubKey curves.Po
x, _ := ed25519.Scalar.SetBigInt(message)

// Step 1: Generate random blinding factors for the proof
rBlind := ed25519.Scalar.Random(crand.Reader) // Blinding factor for random value r
xBlind := ed25519.Scalar.Random(crand.Reader) // Blinding factor for random value x
curve := curves.ED25519()
rBlind, err := GenerateRandomNonZeroScalar(curve) // Blinding factor for random value r
if err != nil {
return nil, err
}

xBlind, err := GenerateRandomNonZeroScalar(curve) // Blinding factor for random value x
if err != nil {
return nil, err
}

// Step 2: Create commitments
rBlindH := H.Mul(rBlind) // rBlind * H
Expand Down Expand Up @@ -88,8 +95,11 @@ func NewCiphertextValidityProof(pedersenOpening *curves.Scalar, pubKey curves.Po
// - ciphertext: The ciphertext to prove the validity of.
func VerifyCiphertextValidity(proof *CiphertextValidityProof, pubKey curves.Point, ciphertext *elgamal.Ciphertext) bool {
// Validate input
if proof == nil || proof.Commitment1 == nil || proof.Commitment2 == nil || proof.Response1 == nil ||
proof.Response2 == nil || pubKey == nil || ciphertext == nil || ciphertext.C == nil || ciphertext.D == nil {
if proof == nil || pubKey == nil || ciphertext == nil || ciphertext.C == nil || ciphertext.D == nil {
return false
}

if !proof.validateContents() {
return false
}

Expand Down Expand Up @@ -119,6 +129,18 @@ func VerifyCiphertextValidity(proof *CiphertextValidityProof, pubKey curves.Poin
return recomputedCommitment1.Equal(proof.Commitment1) && recomputedCommitment2.Equal(proof.Commitment2)
}

func (p *CiphertextValidityProof) validateContents() bool {
if p.Commitment1 == nil || p.Commitment2 == nil || p.Response1 == nil || p.Response2 == nil {
return false
}

if p.Commitment1.IsIdentity() || p.Commitment2.IsIdentity() || p.Response1.IsZero() || p.Response2.IsZero() {
return false
}

return true
}

// MarshalJSON for CiphertextValidityProof
func (p *CiphertextValidityProof) MarshalJSON() ([]byte, error) {
// Serialize the points and scalars to a format you prefer
Expand Down
25 changes: 25 additions & 0 deletions pkg/zkproofs/ciphertext_validity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"math/big"
"testing"

"github.com/coinbase/kryptology/pkg/core/curves"
"github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal"
testutils "github.com/sei-protocol/sei-cryptography/pkg/testing"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -155,6 +156,30 @@ func TestVerifyCiphertextValidityProof_Invalid_Input(t *testing.T) {
require.False(t, validated, "Validation should fail for proof with nil fields")
})

t.Run("Invalid Proof Params", func(t *testing.T) {
// Y2 is zero point
clone := *proof
clone.Commitment1 = curves.ED25519().NewIdentityPoint()
valid := VerifyCiphertextValidity(
&clone, keys.PublicKey, ciphertext,
)
require.False(t, valid, "Proof verification should fail for proof params with zero value")

clone = *proof
clone.Response1 = curves.ED25519().Scalar.Zero()
valid = VerifyCiphertextValidity(
&clone, keys.PublicKey, ciphertext,
)
require.False(t, valid, "Proof verification should fail for proof params with zero value")

clone = *proof
clone.Commitment2 = nil
valid = VerifyCiphertextValidity(
&clone, keys.PublicKey, ciphertext,
)
require.False(t, valid, "Proof verification should fail for proof params with zero value")
})

t.Run("Invalid Public Key", func(t *testing.T) {
// Proof challenge is nil
validated := VerifyCiphertextValidity(proof, nil, ciphertext)
Expand Down
28 changes: 24 additions & 4 deletions pkg/zkproofs/pubkey_validity.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package zkproofs

import (
"crypto/rand"
"encoding/json"
"errors"

"github.com/coinbase/kryptology/pkg/core/curves"
"github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal"
)
Expand Down Expand Up @@ -36,8 +36,13 @@ func NewPubKeyValidityProof(pubKey curves.Point, privKey curves.Scalar) (*PubKey

eg := elgamal.NewTwistedElgamal()
H := eg.GetH()

// Prover generates a random scalar y
y := curves.ED25519().Scalar.Random(rand.Reader)
curve := curves.ED25519()
y, err := GenerateRandomNonZeroScalar(curve)
if err != nil {
return nil, err
}

// Commitment Y = y * H
Y := H.Mul(y)
Expand Down Expand Up @@ -65,9 +70,12 @@ func NewPubKeyValidityProof(pubKey curves.Point, privKey curves.Scalar) (*PubKey
// Parameters:
// - pubKey: The PublicKey to validate.
// - proof: The proof that the prover knows the corresponding PrivateKey.
func VerifyPubKeyValidity(pubKey curves.Point, proof PubKeyValidityProof) bool {
func VerifyPubKeyValidity(pubKey curves.Point, proof *PubKeyValidityProof) bool {
// Validate input
if pubKey == nil || proof.Y == nil || proof.Z == nil {
if proof == nil || pubKey == nil {
return false
}
if !proof.validateContents() {
return false
}

Expand All @@ -92,6 +100,18 @@ func VerifyPubKeyValidity(pubKey curves.Point, proof PubKeyValidityProof) bool {
return lhs.Equal(rhs)
}

func (p *PubKeyValidityProof) validateContents() bool {
if p.Y == nil || p.Z == nil {
return false
}

if p.Y.IsIdentity() || p.Z.IsZero() {
return false
}

return true
}

// MarshalJSON for PubKeyValidityProof
func (p *PubKeyValidityProof) MarshalJSON() ([]byte, error) {
// Serialize the points and scalars to a format you prefer
Expand Down
Loading

0 comments on commit e566c8f

Please sign in to comment.