Skip to content
This repository was archived by the owner on Nov 7, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
67 changes: 67 additions & 0 deletions crypto/pedersen/pedersen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package pedersen

import (
"math/big"
"runtime"

"github.com/okx/threshold-lib/crypto"
)

const (
PrimeBits = 1024
)

type (
// N = p * q, where p and q are safe primes
// s = rnd1^2 mod N
// t = rnd2^2 mod N
PedersenParameters struct {
S, T, Ntilde *big.Int
}
)

func NewPedersenParameters(concurrency ...int) (*PedersenParameters, error) {
var currency int
if 0 < len(concurrency) {
currency = concurrency[0]
} else {
currency = runtime.NumCPU()
}

var values = make(chan *big.Int, currency)
var p, q *big.Int
for p == q {
var quit = make(chan int)
for i := 0; i < currency; i++ {
go crypto.GenerateSafePrime(PrimeBits, values, quit)
}
p, q = <-values, <-values
close(quit)
}

// N = p * q, as described in the paper: https://eprint.iacr.org/2020/492.pdf Definition 1.2
N := new(big.Int).Mul(p, q)
rnd1 := crypto.RandomNum(N)
rnd2 := crypto.RandomNum(N)

s := new(big.Int).Mod(new(big.Int).Mul(rnd1, rnd1), N)
t := new(big.Int).Mod(new(big.Int).Mul(rnd2, rnd2), N)

return &PedersenParameters{Ntilde: N, S: s, T: t}, nil
}

// commit c = s^m * t^r mod N
func (pedersen *PedersenParameters) Commit(m, r *big.Int) (*big.Int, error) {
a := new(big.Int).Exp(pedersen.S, m, pedersen.Ntilde)
b := new(big.Int).Exp(pedersen.T, r, pedersen.Ntilde)
c := new(big.Int).Mod(new(big.Int).Mul(a, b), pedersen.Ntilde)
return c, nil
}

// open c = s^m * t^r mod N
func (pedersen *PedersenParameters) Open(c, m, r *big.Int) (bool, error) {
a := new(big.Int).Exp(pedersen.S, m, pedersen.Ntilde)
b := new(big.Int).Exp(pedersen.T, r, pedersen.Ntilde)
c1 := new(big.Int).Mod(new(big.Int).Mul(a, b), pedersen.Ntilde)
return c1.Cmp(c) == 0, nil
}
23 changes: 23 additions & 0 deletions crypto/pedersen/pedersen_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package pedersen

import (
"encoding/json"
"fmt"
"math/big"
"testing"
)

func TestPedersen(t *testing.T) {
parameters, _ := NewPedersenParameters(8)

m := big.NewInt(10)
r := big.NewInt(32)

c1, _ := parameters.Commit(m, r)
ok, _ := parameters.Open(c1, m, r)
fmt.Println("ok", ok)

ped, _ := json.Marshal(parameters)
fmt.Println("ped", string(ped))

}
169 changes: 169 additions & 0 deletions crypto/zkp/aff_g_proof.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package zkp

import (
"math/big"

"github.com/decred/dcrd/dcrec/secp256k1/v2"
"github.com/okx/threshold-lib/crypto"
"github.com/okx/threshold-lib/crypto/curves"
"github.com/okx/threshold-lib/crypto/pedersen"
)

type (
AffGStatement struct {
N, C, D *big.Int
X, Y *curves.ECPoint
}

AffGWitness struct {
X, Y, Rho *big.Int
}

AffGProof struct {
A, E, S, F, T, Z1, Z2, Z3, Z4, W *big.Int
Bx, By, X, Y *curves.ECPoint
}
)

var (
two = big.NewInt(2)
curve = secp256k1.S256()
L0_Aff_G = 2 * 256
L1_Aff_G = 3 * 256
Epsilon_Aff_G = 3 * 256
)

// https://eprint.iacr.org/2020/492.pdf 4.2 Paillier Operation with Group Commitment in Range ZK
// y is committed in elliptic curve group instead of Paillier group
func PaillierAffineProve(pedersen *pedersen.PedersenParameters, st *AffGStatement, wit *AffGWitness) *AffGProof {
N2 := new(big.Int).Mul(st.N, st.N)

// sample viaribles
rangeL0Epsilon := new(big.Int).Lsh(one, uint(L0_Aff_G+Epsilon_Aff_G))
rangeL1Epsilon := new(big.Int).Lsh(one, uint(L1_Aff_G+Epsilon_Aff_G))
rangeL0 := new(big.Int).Lsh(one, uint(L0_Aff_G))
// rangeL1 := new(big.Int).Lsh(one, uint(L1_Aff_G))

alpha := crypto.RandomNum(rangeL0Epsilon)
beta := crypto.RandomNum(rangeL1Epsilon)

r := crypto.RandomNum(st.N)
gamma := crypto.RandomNum(new(big.Int).Mul(rangeL0Epsilon, pedersen.Ntilde))
m := crypto.RandomNum(new(big.Int).Mul(rangeL0, pedersen.Ntilde))
// rangeL1 ?
delta := crypto.RandomNum(new(big.Int).Mul(rangeL0Epsilon, pedersen.Ntilde))
mu := crypto.RandomNum(new(big.Int).Mul(rangeL0, pedersen.Ntilde))

// compute A, Bx, By, E, S, F, T
// A = C^alpha * ((1+N)^beta * r^N) mod N2
A := new(big.Int).Exp(st.C, alpha, N2)
A = new(big.Int).Mod(new(big.Int).Mul(A, new(big.Int).Exp(new(big.Int).Add(one, st.N), beta, N2)), N2)
A = new(big.Int).Mod(new(big.Int).Mul(A, new(big.Int).Exp(r, st.N, N2)), N2)

// Bx = aplha * G
Bx := curves.ScalarToPoint(curve, alpha)

// By = beta * G
By := curves.ScalarToPoint(curve, beta)

// E = pedersen.Commit(alpha, gamma)
E, _ := pedersen.Commit(alpha, gamma)

// S = pedersen.Commit(x, m)
S, _ := pedersen.Commit(wit.X, m)

// F = pedersen.Commit(beta, delta)
F, _ := pedersen.Commit(beta, delta)

// T = pedersen.Commit(y, mu)
T, _ := pedersen.Commit(wit.Y, mu)

// compute challenge e
e := crypto.SHA256Int(st.N, st.C, st.D, st.X.X, st.Y.X, A, Bx.X, By.X, E, S, F, T)
e = new(big.Int).Mod(e, curve.N)

// compute Z1, Z2, Z3, Z4, W
// Z1 = alpha + e * x
Z1 := new(big.Int).Add(alpha, new(big.Int).Mul(e, wit.X))

// Z2 = beta + e * y
Z2 := new(big.Int).Add(beta, new(big.Int).Mul(e, wit.Y))

// Z3 = gamma + e * m
Z3 := new(big.Int).Add(gamma, new(big.Int).Mul(e, m))

// Z4 = delta + e * mu
Z4 := new(big.Int).Add(delta, new(big.Int).Mul(e, mu))

// W = r * rho^e mod N
W := new(big.Int).Mod(new(big.Int).Mul(r, new(big.Int).Exp(wit.Rho, e, st.N)), st.N)

return &AffGProof{A: A, Bx: Bx, By: By, E: E, S: S, F: F, T: T, Z1: Z1, Z2: Z2, Z3: Z3, Z4: Z4, W: W, X: st.X, Y: st.Y}
}

func PaillierAffineVerify(pedersen *pedersen.PedersenParameters, proof *AffGProof, st *AffGStatement) bool {
N2 := new(big.Int).Mul(st.N, st.N)
e := crypto.SHA256Int(st.N, st.C, st.D, st.X.X, st.Y.X, proof.A, proof.Bx.X, proof.By.X, proof.E, proof.S, proof.F, proof.T)
e = new(big.Int).Mod(e, curve.N)

// check A
// C^Z1 * ((1+N)^Z2 * w^N) = A * D^e mod N2
left0 := new(big.Int).Exp(st.C, proof.Z1, N2)
left0 = new(big.Int).Mod(new(big.Int).Mul(left0, new(big.Int).Exp(new(big.Int).Add(one, st.N), proof.Z2, N2)), N2)
left0 = new(big.Int).Mod(new(big.Int).Mul(left0, new(big.Int).Exp(proof.W, st.N, N2)), N2)
right0 := new(big.Int).Mod(new(big.Int).Mul(proof.A, new(big.Int).Exp(st.D, e, N2)), N2)
if left0.Cmp(right0) != 0 {
return false
}

// check Bx
// Z1 * G = Bx + e * X
left1 := curves.ScalarToPoint(curve, proof.Z1)
right1, err := proof.Bx.Add(st.X.ScalarMult(e))
if err != nil {
return false
}
if !left1.Equals(right1) {
return false
}

// check By
// Z2 * G = By + e * Y
left2 := curves.ScalarToPoint(curve, proof.Z2)
right2, err := proof.By.Add(st.Y.ScalarMult(e))
if err != nil {
return false
}
if !left2.Equals(right2) {
return false
}

// check E, S
// pedersen.Commit(Z1, Z3) = E * S^e mod N2
left3, _ := pedersen.Commit(proof.Z1, proof.Z3)
right3 := new(big.Int).Mod(new(big.Int).Mul(proof.E, new(big.Int).Exp(proof.S, e, pedersen.Ntilde)), pedersen.Ntilde)
if left3.Cmp(right3) != 0 {
return false
}

// check F, T
// pedersen.Commit(Z2, Z4) = F * T^e mod N2
left4, _ := pedersen.Commit(proof.Z2, proof.Z4)
right4 := new(big.Int).Mod(new(big.Int).Mul(proof.F, new(big.Int).Exp(proof.T, e, pedersen.Ntilde)), pedersen.Ntilde)
if left4.Cmp(right4) != 0 {
return false
}

// range check
// Z1 < 2^(L0 + Epsilon)
if proof.Z1.Cmp(new(big.Int).Lsh(one, uint(L0_Aff_G+Epsilon_Aff_G))) != -1 {
return false
}

// Z2 < 2^(L1 + Epsilon)
if proof.Z2.Cmp(new(big.Int).Lsh(one, uint(L1_Aff_G+Epsilon_Aff_G))) != -1 {
return false
}

return true
}
81 changes: 81 additions & 0 deletions crypto/zkp/aff_g_proof_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package zkp

import (
"fmt"
"math/big"
"testing"

"github.com/okx/threshold-lib/crypto"
"github.com/okx/threshold-lib/crypto/curves"
"github.com/okx/threshold-lib/crypto/pedersen"
)

func TestAffGProof(t *testing.T) {
// -----------------------GeneratePreParams-------------------------------
fmt.Println("----------------------- TestAffGProof ---------------------------------")
pesersen, _ := pedersen.NewPedersenParameters(8)
// const bits = 512
const bits = 1024

concurrency := 4
var values = make(chan *big.Int, concurrency)
var p, q *big.Int
for p == q {
var quit = make(chan int)
for i := 0; i < concurrency; i++ {
go crypto.GenerateSafePrime(bits, values, quit)
}
p, q = <-values, <-values
close(quit)
}
N := new(big.Int).Mul(p, q)
N2 := new(big.Int).Mul(N, N)

rangeL0 := new(big.Int).Lsh(one, uint(L0_Aff_G))
rangeL1 := new(big.Int).Lsh(one, uint(L1_Aff_G))

x := crypto.RandomNum(rangeL0)
y := crypto.RandomNum(rangeL1)
rho := crypto.RandomNum(N)

witness := &AffGWitness{
X: x,
Y: y,
Rho: rho,
}

// C is an ciphertext of an Paillier encryption of a secret
C := crypto.RandomNum(N2)

// D = C^x * (1+N)^y * rho^N mod N^2
D := new(big.Int).Exp(C, x, N2)
D = new(big.Int).Mod(new(big.Int).Mul(D, new(big.Int).Exp(new(big.Int).Add(one, N), y, N2)), N2)
D = new(big.Int).Mod(new(big.Int).Mul(D, new(big.Int).Exp(rho, N, N2)), N2)

X := curves.ScalarToPoint(curve, x)
Y := curves.ScalarToPoint(curve, y)

st := &AffGStatement{
N: N,
C: C,
D: D,
X: X,
Y: Y,
}

proof := PaillierAffineProve(pesersen, st, witness)
verify := PaillierAffineVerify(pesersen, proof, st)

fmt.Println("PaillierAffineProof of honest prover:", verify)

x = crypto.RandomNum(N)
witness = &AffGWitness{
X: x,
Y: y,
Rho: rho,
}
proof = PaillierAffineProve(pesersen, st, witness)
verify = PaillierAffineVerify(pesersen, proof, st)
fmt.Println("PaillierAffineProof of malicious prover:", verify)

}
4 changes: 3 additions & 1 deletion tss/ecdsa/keygen/keygen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package keygen
import (
"encoding/json"
"fmt"
"testing"

"github.com/okx/threshold-lib/crypto/curves"
"github.com/okx/threshold-lib/crypto/paillier"
"github.com/okx/threshold-lib/tss"
"github.com/okx/threshold-lib/tss/key/bip32"
"github.com/okx/threshold-lib/tss/key/dkg"
"testing"
)

const (
Expand Down Expand Up @@ -50,6 +51,7 @@ func TestKeyGen(t *testing.T) {
if err != nil {
fmt.Println("preParams Unmarshal error, ", err)
}

// 1-->2 1--->3
paiPriKey, _, _ := paillier.NewKeyPair(8)
p1Data, _ := P1(p1SaveData.ShareI, paiPriKey, setUp1.DeviceNumber, setUp2.DeviceNumber, preParams)
Expand Down
1 change: 1 addition & 0 deletions tss/ecdsa/keygen/party2.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func P2(share2 *big.Int, publicKey *curves.ECPoint, msg *tss.Message, from, to i
if !slackVerify {
return nil, fmt.Errorf("PDLwSlackVerify fail")
}

// P2 additional save key information
p2SaveData := &P2SaveData{
From: from,
Expand Down
Loading