Skip to content

Commit

Permalink
Merge pull request from GHSA-h24c-6p6p-m3vx
Browse files Browse the repository at this point in the history
CGGMP21 Proofs
  • Loading branch information
pdyraga committed Sep 1, 2023
2 parents afbe264 + 0995329 commit 2e71268
Show file tree
Hide file tree
Showing 68 changed files with 3,628 additions and 924 deletions.
33 changes: 30 additions & 3 deletions common/hash_utils.go
Expand Up @@ -10,9 +10,36 @@ import (
"math/big"
)

// RejectionSample implements the rejection sampling logic for converting a
// SHA512/256 hash to a value between 0-q
func RejectionSample(q *big.Int, eHash *big.Int) *big.Int { // e' = eHash
// LiterallyJustMod implements the logic for converting a
// SHA512/256 hash to a value between 0-q by taking the number modulo q.
// XXX: this is only safe if used with values of q that are extremely close
// to a power of 2. The order of secp256k1 happens to be one of those values,
// and the bias introduced by the modulus is around 1.27*2^-128.
// The same applies to the order of curve25519.
func LiterallyJustMod(q *big.Int, eHash *big.Int) *big.Int { // e' = eHash
e := eHash.Mod(eHash, q)
return e
}

// Return a big.Int between 0 and N
func HashToN(N *big.Int, in ...*big.Int) *big.Int {
bitCnt := N.BitLen()
// Add 256 bits to remove bias from LiterallyJustMod,
// and another 256 bits to compensate for any remainder from the division.
blockCnt := (bitCnt / 256) + 2

dest := big.NewInt(0)
tmp := make([]*big.Int, 1, 1+len(in))
tmp = append(tmp, in...)

for i := 0; i < blockCnt; i++ {
// dest = h(0, in) | h(1, in) | h(2, in) | ...
tmp[0] = big.NewInt(int64(i))
dest.Lsh(dest, 256)
dest.Or(dest, SHA512_256i(tmp...))
}

// dest has at least N.BitLen + 256 bits,
// thus it is safe to use Mod
return LiterallyJustMod(N, dest)
}
10 changes: 5 additions & 5 deletions common/hash_utils_test.go
Expand Up @@ -14,13 +14,13 @@ import (
"github.com/bnb-chain/tss-lib/common"
)

func TestRejectionSample(t *testing.T) {
func TestLiterallyJustMod(t *testing.T) {
curveQ := common.GetRandomPrimeInt(256)
randomQ := common.MustGetRandomInt(64)
hash := common.SHA512_256iOne(big.NewInt(123))
rs1 := common.RejectionSample(curveQ, hash)
rs2 := common.RejectionSample(randomQ, hash)
rs3 := common.RejectionSample(common.MustGetRandomInt(64), hash)
rs1 := common.LiterallyJustMod(curveQ, hash)
rs2 := common.LiterallyJustMod(randomQ, hash)
rs3 := common.LiterallyJustMod(common.MustGetRandomInt(64), hash)
type args struct {
q *big.Int
eHash *big.Int
Expand Down Expand Up @@ -50,7 +50,7 @@ func TestRejectionSample(t *testing.T) {
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := common.RejectionSample(tt.args.q, tt.args.eHash)
got := common.LiterallyJustMod(tt.args.q, tt.args.eHash)
if !tt.notEqual && !reflect.DeepEqual(got, tt.want) {
t.Errorf("RejectionSample() = %v, want %v", got, tt.want)
}
Expand Down
92 changes: 92 additions & 0 deletions common/int.go
Expand Up @@ -19,10 +19,41 @@ var (
two = big.NewInt(2)
)

func Eq(x, y *big.Int) bool {
return x.Cmp(y) == 0
}

func Gt(x, y *big.Int) bool {
return x.Cmp(y) == 1
}

func Lt(x, y *big.Int) bool {
return x.Cmp(y) == -1
}

func Coprime(x, y *big.Int) bool {
z := new(big.Int).GCD(nil, nil, x, y)
return Eq(z, big.NewInt(1))
}

// return x + yz
func AddMul(x, y, z *big.Int) *big.Int {
res := new(big.Int)
res.Mul(y, z)
res.Add(res, x)
return res
}

func ModInt(mod *big.Int) *modInt {
return (*modInt)(mod)
}

func (mi *modInt) Neg(x *big.Int) *big.Int {
i := new(big.Int)
i.Neg(x)
return i.Mod(i, mi.i())
}

func (mi *modInt) Add(x, y *big.Int) *big.Int {
i := new(big.Int)
i.Add(x, y)
Expand Down Expand Up @@ -51,10 +82,71 @@ func (mi *modInt) Exp(x, y *big.Int) *big.Int {
return new(big.Int).Exp(x, y, mi.i())
}

// return x * y^z % mi
func (mi *modInt) MulExp(x, y, z *big.Int) *big.Int {
return mi.Mul(x, mi.Exp(y, z))
}

// return x^y * z^w % mi
func (mi *modInt) ExpMulExp(x, y, z, w *big.Int) *big.Int {
return mi.Mul(mi.Exp(x, y), mi.Exp(z, w))
}

func (mi *modInt) ModInverse(g *big.Int) *big.Int {
return new(big.Int).ModInverse(g, mi.i())
}

func (mi *modInt) i() *big.Int {
return (*big.Int)(mi)
}

// Marshal the given bigint into bytes.
// with the sign stored in the first byte and the absolute value in the rest.
// `nil` or 0 is stored as the byte 0x00.
// The sign byte is 0x00 for positive and 0x01 for negative.
func MarshalSigned(i *big.Int) []byte {
if i == nil || Eq(i, big.NewInt(0)) {
return []byte{0}
}

// 0 = positive, 1 = negative
sign := make([]byte, 1)
if i.Sign() == 1 {
sign[0] = 0
} else {
sign[0] = 1
}

bs := i.Bytes()

return append(sign, bs...)
}

// Unmarshal a signed bigint from the given bytes.
// Slices of length 1 are interpreted as 0;
// in longer slices the first byte determines the sign
// (0x00 is positive, anything else is negative)
// and the remaining bytes contain the value of the bigint.
func UnmarshalSigned(b []byte) *big.Int {
if len(b) <= 1 {
return big.NewInt(0)
}

sign := b[0]
rest := b[1:]
i := new(big.Int).SetBytes(rest)
if sign != 0 {
i.Neg(i)
}
return i
}

// Returns true when at least one of the arguments is nil
func AnyIsNil(is ...*big.Int) bool {
for _, i := range is {
if i == nil {
return true
}
}
return false
}
146 changes: 146 additions & 0 deletions common/int_test.go
@@ -0,0 +1,146 @@
package common_test

import (
"math/big"
"testing"

"github.com/stretchr/testify/assert"

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

func TestMarshalSigned(t *testing.T) {
assert := assert.New(t)

assert.Equal([]byte{0}, common.MarshalSigned(nil), "Nil should marshal to 0x00")
assert.Equal([]byte{0}, common.MarshalSigned(big.NewInt(0)), "0 should marshal to 0x00")
assert.Equal([]byte{0, 1}, common.MarshalSigned(big.NewInt(1)), "1 should marshal to 0x0001")
assert.Equal([]byte{0, 1, 1}, common.MarshalSigned(big.NewInt(257)), "257 should marshal to 0x000101")
assert.Equal([]byte{1, 1}, common.MarshalSigned(big.NewInt(-1)), "-1 should marshal to 0x0101")
}

func TestInt(t *testing.T) {
assert := assert.New(t)
zero := big.NewInt(0)
one := big.NewInt(1)
two := big.NewInt(2)
three := big.NewInt(3)
four := big.NewInt(4)
five := big.NewInt(5)
six := big.NewInt(6)
seven := big.NewInt(7)

minusOne := big.NewInt(-1)
minusTwo := big.NewInt(-2)

assert.True(common.Eq(one, one))
assert.False(common.Eq(zero, one))
assert.False(common.Eq(minusOne, one))

assert.Equal(seven, common.AddMul(one, two, three))

mod7 := common.ModInt(seven)

assert.Equal(six, mod7.Neg(one))

assert.True(common.Eq(zero, mod7.Add(one, six)))
assert.Equal(two, mod7.Add(four, five))
assert.Equal(six, mod7.Add(zero, minusOne))

assert.Equal(two, mod7.Sub(five, three))
assert.Equal(six, mod7.Sub(one, two))

assert.Equal(two, mod7.Div(six, three))
assert.Equal(one, mod7.Div(five, three))
assert.Equal(two, mod7.Div(big.NewInt(81), big.NewInt(9)))
assert.Equal(three, mod7.Div(four, minusOne))

assert.Equal(six, mod7.Mul(two, three))
assert.Equal(two, mod7.Mul(three, three))
assert.Equal(three, mod7.Mul(big.NewInt(8), big.NewInt(10)))
assert.Equal(three, mod7.Mul(four, minusOne))

assert.Equal(two, mod7.Exp(three, two))
assert.Equal(four, mod7.Exp(two, two))
// 2 is the multiplicative inverse of 4 mod 7
assert.Equal(four, mod7.Exp(four, minusTwo))

// 4 * 3^2 = 36 == 1 mod 7
assert.Equal(one, mod7.MulExp(four, three, two))
// 2^2 * 3^2 = 36 == 1 mod 7
assert.Equal(one, mod7.ExpMulExp(two, two, three, two))

assert.Equal(two, mod7.ModInverse(four))
}

func TestUnmarshalSigned(t *testing.T) {
assert := assert.New(t)

assert.True(
big.NewInt(0).Cmp(common.UnmarshalSigned([]byte{})) == 0,
"empty array should unmarshal to 0",
)

assert.True(
big.NewInt(0).Cmp(common.UnmarshalSigned([]byte{0})) == 0,
"0x00 should unmarshal to 0",
)
assert.True(
big.NewInt(0).Cmp(common.UnmarshalSigned([]byte{1})) == 0,
"0x01 should unmarshal to 0",
)
assert.True(
big.NewInt(0).Cmp(common.UnmarshalSigned([]byte{255})) == 0,
"0xff should unmarshal to 0",
)

assert.True(
big.NewInt(0).Cmp(common.UnmarshalSigned([]byte{0, 0})) == 0,
"0x0000 should unmarshal to 0",
)
assert.True(
big.NewInt(0).Cmp(common.UnmarshalSigned([]byte{1, 0})) == 0,
"0x0100 should unmarshal to 0",
)
assert.True(
big.NewInt(0).Cmp(common.UnmarshalSigned([]byte{255, 0})) == 0,
"0xff00 should unmarshal to 0",
)

assert.True(
big.NewInt(1).Cmp(common.UnmarshalSigned([]byte{0, 1})) == 0,
"0x0001 should unmarshal to 1",
)
assert.True(
big.NewInt(-1).Cmp(common.UnmarshalSigned([]byte{1, 1})) == 0,
"0x0101 should unmarshal to -1",
)
assert.True(
big.NewInt(-1).Cmp(common.UnmarshalSigned([]byte{255, 1})) == 0,
"0xff01 should unmarshal to -1",
)

assert.True(
big.NewInt(255).Cmp(common.UnmarshalSigned([]byte{0, 255})) == 0,
"0x00ff should unmarshal to 255",
)
assert.True(
big.NewInt(-255).Cmp(common.UnmarshalSigned([]byte{1, 255})) == 0,
"0x01ff should unmarshal to -255",
)
assert.True(
big.NewInt(-255).Cmp(common.UnmarshalSigned([]byte{255, 255})) == 0,
"0xffff should unmarshal to -255",
)
}

func TestAnyIsNil(t *testing.T) {
assert := assert.New(t)

assert.True(common.AnyIsNil(nil))
assert.False(common.AnyIsNil(big.NewInt(1)))

assert.True(common.AnyIsNil(big.NewInt(1), nil))
assert.True(common.AnyIsNil(nil, big.NewInt(2)))
assert.False(common.AnyIsNil(big.NewInt(1), big.NewInt(2)))
}
31 changes: 29 additions & 2 deletions common/random.go
Expand Up @@ -49,6 +49,17 @@ func GetRandomPositiveInt(lessThan *big.Int) *big.Int {
return try
}

// Sample an integer in range (-limit, limit)
func GetRandomInt(limit *big.Int) *big.Int {
limitMinus1 := new(big.Int).Sub(limit, big.NewInt(1))
limitDoubleMinus1 := new(big.Int).Add(limit, limitMinus1)
// get an integer in [0, 2*limit-1) and subtract limit-1
// to get an integer in [-limit+1, limit-1]
i := GetRandomPositiveInt(limitDoubleMinus1)
i = i.Sub(i, limitMinus1)
return i
}

func GetRandomPrimeInt(bits int) *big.Int {
if bits <= 0 {
return nil
Expand Down Expand Up @@ -92,11 +103,27 @@ func IsNumberInMultiplicativeGroup(n, v *big.Int) bool {
gcd.GCD(nil, nil, v, n).Cmp(one) == 0
}

// Return a random generator of RQn with high probability.
// THIS METHOD ONLY WORKS IF N IS THE PRODUCT OF TWO SAFE PRIMES!
// Return a random generator of RQn with high probability.
// THIS METHOD ONLY WORKS IF N IS THE PRODUCT OF TWO SAFE PRIMES!
//
// https://github.com/didiercrunch/paillier/blob/d03e8850a8e4c53d04e8016a2ce8762af3278b71/utils.go#L39
func GetRandomGeneratorOfTheQuadraticResidue(n *big.Int) *big.Int {
f := GetRandomPositiveRelativelyPrimeInt(n)
fSq := new(big.Int).Mul(f, f)
return fSq.Mod(fSq, n)
}

// Sample an integer in range (-2^power, 2^power)
func GetRandomIntIn2PowerRange(power uint) *big.Int {
limit := big.NewInt(1)
limit.Lsh(limit, power)
return GetRandomInt(limit)
}

// Sample an integer in range (-2^power * multiplier, 2^power * multiplier)
func GetRandomIntIn2PowerMulRange(power uint, multiplier *big.Int) *big.Int {
limit := big.NewInt(1)
limit.Lsh(limit, power)
limit.Mul(limit, multiplier)
return GetRandomInt(limit)
}

0 comments on commit 2e71268

Please sign in to comment.