Skip to content

Commit

Permalink
add: ecdsa proof session byte
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhAnGeek committed Aug 22, 2023
1 parent 4288238 commit 4c340f4
Show file tree
Hide file tree
Showing 43 changed files with 359 additions and 157 deletions.
41 changes: 41 additions & 0 deletions common/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,47 @@ func SHA512_256i(in ...*big.Int) *big.Int {
return new(big.Int).SetBytes(state.Sum(nil))
}

// SHA512_256i_TAGGED tagged version of SHA512_256i
func SHA512_256i_TAGGED(tag []byte, in ...*big.Int) *big.Int {
tagBz := SHA512_256(tag)
var data []byte
state := crypto.SHA512_256.New()
state.Write(tagBz)
state.Write(tagBz)
inLen := len(in)
if inLen == 0 {
return nil
}
bzSize := 0
// prevent hash collisions with this prefix containing the block count
inLenBz := make([]byte, 64/8)
// converting between int and uint64 doesn't change the sign bit, but it may be interpreted as a larger value.
// this prefix is never read/interpreted, so that doesn't matter.
binary.LittleEndian.PutUint64(inLenBz, uint64(inLen))
ptrs := make([][]byte, inLen)
for i, n := range in {
if n == nil {
ptrs[i] = zero.Bytes()
} else {
ptrs[i] = n.Bytes()
}
bzSize += len(ptrs[i])
}
data = make([]byte, 0, len(inLenBz)+bzSize+inLen)
data = append(data, inLenBz...)
for i := range in {
data = append(data, ptrs[i]...)
data = append(data, hashInputDelimiter) // safety delimiter
}
// n < len(data) or an error will never happen.
// see: https://golang.org/pkg/hash/#Hash and https://github.com/golang/go/wiki/Hashing#the-hashhash-interface
if _, err := state.Write(data); err != nil {
Logger.Error(err)
return nil
}
return new(big.Int).SetBytes(state.Sum(nil))
}

func SHA512_256iOne(in *big.Int) *big.Int {
var data []byte
state := crypto.SHA512_256.New()
Expand Down
7 changes: 7 additions & 0 deletions common/int.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,10 @@ func (mi *modInt) i() *big.Int {
func IsInInterval(b *big.Int, bound *big.Int) bool {
return b.Cmp(bound) == -1 && b.Cmp(zero) >= 0
}

func AppendBigIntToBytesSlice(commonBytes []byte, appended *big.Int) []byte {
resultBytes := make([]byte, len(commonBytes), len(commonBytes)+len(appended.Bytes()))
copy(resultBytes, commonBytes)
resultBytes = append(resultBytes, appended.Bytes()...)
return resultBytes
}
16 changes: 16 additions & 0 deletions common/random.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,19 @@ func GetRandomQuadraticNonResidue(n *big.Int) *big.Int {
}
}
}

// GetRandomBytes returns random bytes of length.
func GetRandomBytes(length int) ([]byte, error) {
// Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes].
if length <= 0 {
return nil, errors.New("invalid length")
}

buf := make([]byte, length)
_, err := rand.Read(buf)
if err != nil {
return nil, err
}

return buf, nil
}
103 changes: 27 additions & 76 deletions crypto/facproof/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import (
"crypto/elliptic"
"errors"
"fmt"
"github.com/bnb-chain/tss-lib/common"
"math/big"

"github.com/bnb-chain/tss-lib/common"
)

const (
Expand All @@ -30,31 +31,31 @@ var (
one = big.NewInt(1)
)

// NewProof implements proofFac
func NewProof(ec elliptic.Curve, N0, NCap, s, t, N0p, N0q *big.Int) (*ProofFac, error) {
// NewProof implements prooffac
func NewProof(Session []byte, ec elliptic.Curve, N0, NCap, s, t, N0p, N0q *big.Int) (*ProofFac, error) {
if ec == nil || N0 == nil || NCap == nil || s == nil || t == nil || N0p == nil || N0q == nil {
return nil, errors.New("ProveFac constructor received nil value(s)")
}

q := ec.Params().N
q3 := new(big.Int).Mul(q, q)
q3 = new(big.Int).Mul(q, q3)
qNCap := new(big.Int).Mul(q, NCap)
qN0NCap := new(big.Int).Mul(qNCap, N0)
q3NCap := new(big.Int).Mul(q3, NCap)
q3N0NCap := new(big.Int).Mul(q3NCap, N0)
sqrtN0 := new(big.Int).Sqrt(N0)

leSqrtN0 := new(big.Int).Mul(rangeParameter, q)
leSqrtN0 = new(big.Int).Mul(leSqrtN0, sqrtN0)
lNCap := new(big.Int).Mul(rangeParameter, NCap)
lN0NCap := new(big.Int).Mul(lNCap, N0)
leN0NCap := new(big.Int).Mul(lN0NCap, q)
leNCap := new(big.Int).Mul(lNCap, q)
q3SqrtN0 := new(big.Int).Mul(q3, sqrtN0)

// Fig 28.1 sample
alpha := common.GetRandomPositiveInt(leSqrtN0)
beta := common.GetRandomPositiveInt(leSqrtN0)
mu := common.GetRandomPositiveInt(lNCap)
nu := common.GetRandomPositiveInt(lNCap)
sigma := common.GetRandomPositiveInt(lN0NCap)
r := common.GetRandomPositiveRelativelyPrimeInt(leN0NCap)
x := common.GetRandomPositiveInt(leNCap)
y := common.GetRandomPositiveInt(leNCap)
alpha := common.GetRandomPositiveInt(q3SqrtN0)
beta := common.GetRandomPositiveInt(q3SqrtN0)
mu := common.GetRandomPositiveInt(qNCap)
nu := common.GetRandomPositiveInt(qNCap)
sigma := common.GetRandomPositiveInt(qN0NCap)
r := common.GetRandomPositiveRelativelyPrimeInt(q3N0NCap)
x := common.GetRandomPositiveInt(q3NCap)
y := common.GetRandomPositiveInt(q3NCap)

// Fig 28.1 compute
modNCap := common.ModInt(NCap)
Expand All @@ -76,7 +77,7 @@ func NewProof(ec elliptic.Curve, N0, NCap, s, t, N0p, N0q *big.Int) (*ProofFac,
// Fig 28.2 e
var e *big.Int
{
eHash := common.SHA512_256i(N0, NCap, s, t, P, Q, A, B, T, sigma)
eHash := common.SHA512_256i_TAGGED(Session, N0, NCap, s, t, P, Q, A, B, T, sigma)
e = common.RejectionSample(q, eHash)
}

Expand Down Expand Up @@ -120,82 +121,32 @@ func NewProofFromBytes(bzs [][]byte) (*ProofFac, error) {
}, nil
}

func (pf *ProofFac) Verify(ec elliptic.Curve, N0, NCap, s, t *big.Int) bool {
func (pf *ProofFac) Verify(Session []byte, ec elliptic.Curve, N0, NCap, s, t *big.Int) bool {
if pf == nil || !pf.ValidateBasic() || ec == nil || N0 == nil || NCap == nil || s == nil || t == nil {
return false
}
if N0.Sign() != 1 {
return false
}
if NCap.Sign() != 1 {
return false
}

q := ec.Params().N
q3 := new(big.Int).Mul(q, q)
q3 = new(big.Int).Mul(q, q3)
sqrtN0 := new(big.Int).Sqrt(N0)

leSqrtN0 := new(big.Int).Mul(rangeParameter, q)
leSqrtN0 = new(big.Int).Mul(leSqrtN0, sqrtN0)
lNCap := new(big.Int).Mul(rangeParameter, NCap)
lN0NCap := new(big.Int).Mul(lNCap, N0)
leN0NCap2 := new(big.Int).Lsh(new(big.Int).Mul(lN0NCap, q), 1)
leNCap2 := new(big.Int).Lsh(new(big.Int).Mul(lNCap, q), 1)

if !common.IsInInterval(pf.P, NCap) {
return false
}
if !common.IsInInterval(pf.Q, NCap) {
return false
}
if !common.IsInInterval(pf.A, NCap) {
return false
}
if !common.IsInInterval(pf.B, NCap) {
return false
}
if !common.IsInInterval(pf.T, NCap) {
return false
}
if !common.IsInInterval(pf.Sigma, lN0NCap) {
return false
}
if new(big.Int).GCD(nil, nil, pf.P, NCap).Cmp(one) != 0 {
return false
}
if new(big.Int).GCD(nil, nil, pf.Q, NCap).Cmp(one) != 0 {
return false
}
if new(big.Int).GCD(nil, nil, pf.A, NCap).Cmp(one) != 0 {
return false
}
if new(big.Int).GCD(nil, nil, pf.B, NCap).Cmp(one) != 0 {
return false
}
if new(big.Int).GCD(nil, nil, pf.T, NCap).Cmp(one) != 0 {
return false
}
if !common.IsInInterval(pf.W1, leNCap2) {
return false
}
if !common.IsInInterval(pf.W2, leNCap2) {
return false
}
if !common.IsInInterval(pf.V, leN0NCap2) {
return false
}
q3SqrtN0 := new(big.Int).Mul(q3, sqrtN0)

// Fig 28. Range Check
if !common.IsInInterval(pf.Z1, leSqrtN0) {
if !common.IsInInterval(pf.Z1, q3SqrtN0) {
return false
}

if !common.IsInInterval(pf.Z2, leSqrtN0) {
if !common.IsInInterval(pf.Z2, q3SqrtN0) {
return false
}

var e *big.Int
{
eHash := common.SHA512_256i(N0, NCap, s, t, pf.P, pf.Q, pf.A, pf.B, pf.T, pf.Sigma)
eHash := common.SHA512_256i_TAGGED(Session, N0, NCap, s, t, pf.P, pf.Q, pf.A, pf.B, pf.T, pf.Sigma)
e = common.RejectionSample(q, eHash)
}

Expand Down
24 changes: 8 additions & 16 deletions crypto/facproof/proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ const (
testSafePrimeBits = 1024
)

var (
Session = []byte("session")
)

func TestFac(test *testing.T) {
ec := tss.EC()

Expand All @@ -33,31 +37,19 @@ func TestFac(test *testing.T) {
primes := [2]*big.Int{common.GetRandomPrimeInt(testSafePrimeBits), common.GetRandomPrimeInt(testSafePrimeBits)}
NCap, s, t, err := crypto.GenerateNTildei(primes)
assert.NoError(test, err)
proof, err := NewProof(ec, N0, NCap, s, t, N0p, N0q)
proof, err := NewProof(Session, ec, N0, NCap, s, t, N0p, N0q)
assert.NoError(test, err)

ok := proof.Verify(ec, N0, NCap, s, t)
ok := proof.Verify(Session, ec, N0, NCap, s, t)
assert.True(test, ok, "proof must verify")

N0p = common.GetRandomPrimeInt(1024)
N0q = common.GetRandomPrimeInt(1024)
N0 = new(big.Int).Mul(N0p, N0q)

proof, err = NewProof(ec, N0, NCap, s, t, N0p, N0q)
proof, err = NewProof(Session, ec, N0, NCap, s, t, N0p, N0q)
assert.NoError(test, err)

ok = proof.Verify(ec, N0, NCap, s, t)
ok = proof.Verify(Session, ec, N0, NCap, s, t)
assert.True(test, ok, "proof must verify")

// factor should have bits [1024-16, 1024+16]
smallFactor := 900
N0p = common.GetRandomPrimeInt(smallFactor)
N0q = common.GetRandomPrimeInt(2048 - smallFactor)
N0 = new(big.Int).Mul(N0p, N0q)

proof, err = NewProof(ec, N0, NCap, s, t, N0p, N0q)
assert.NoError(test, err)

ok = proof.Verify(ec, N0, NCap, s, t)
assert.False(test, ok, "proof must not verify")
}
8 changes: 4 additions & 4 deletions crypto/modproof/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ func isQuadraticResidue(X, N *big.Int) bool {
return big.Jacobi(X, N) == 1
}

func NewProof(N, P, Q *big.Int) (*ProofMod, error) {
func NewProof(Session []byte, N, P, Q *big.Int) (*ProofMod, error) {
Phi := new(big.Int).Mul(new(big.Int).Sub(P, one), new(big.Int).Sub(Q, one))
// Fig 16.1
W := common.GetRandomQuadraticNonResidue(N)

// Fig 16.2
Y := [Iterations]*big.Int{}
for i := range Y {
ei := common.SHA512_256i(append([]*big.Int{W, N}, Y[:i]...)...)
ei := common.SHA512_256i_TAGGED(Session, append([]*big.Int{W, N}, Y[:i]...)...)
Y[i] = common.RejectionSample(N, ei)
}

Expand Down Expand Up @@ -112,7 +112,7 @@ func NewProofFromBytes(bzs [][]byte) (*ProofMod, error) {
}, nil
}

func (pf *ProofMod) Verify(N *big.Int) bool {
func (pf *ProofMod) Verify(Session []byte, N *big.Int) bool {
if pf == nil || !pf.ValidateBasic() {
return false
}
Expand Down Expand Up @@ -143,7 +143,7 @@ func (pf *ProofMod) Verify(N *big.Int) bool {
modN := common.ModInt(N)
Y := [Iterations]*big.Int{}
for i := range Y {
ei := common.SHA512_256i(append([]*big.Int{pf.W, N}, Y[:i]...)...)
ei := common.SHA512_256i_TAGGED(Session, append([]*big.Int{pf.W, N}, Y[:i]...)...)
Y[i] = common.RejectionSample(N, ei)
}

Expand Down
8 changes: 6 additions & 2 deletions crypto/modproof/proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,23 @@ import (
"github.com/stretchr/testify/assert"
)

var (
Session = []byte("session")
)

func TestMod(test *testing.T) {
preParams, err := keygen.GeneratePreParams(time.Minute*10, 8)
assert.NoError(test, err)

P, Q, N := preParams.PaillierSK.P, preParams.PaillierSK.Q, preParams.PaillierSK.N

proof, err := NewProof(N, P, Q)
proof, err := NewProof(Session, N, P, Q)
assert.NoError(test, err)

proofBzs := proof.Bytes()
proof, err = NewProofFromBytes(proofBzs[:])
assert.NoError(test, err)

ok := proof.Verify(N)
ok := proof.Verify(Session, N)
assert.True(test, ok, "proof must verify")
}
Loading

0 comments on commit 4c340f4

Please sign in to comment.