mirror of
https://github.com/arnaucube/go-iden3-crypto.git
synced 2026-02-07 11:36:41 +01:00
add babyjub-eddsa Poseidon sign & verify
This commit is contained in:
@@ -171,10 +171,7 @@ func PackPoint(ay *big.Int, sign bool) [32]byte {
|
|||||||
// Compress the point into a 32 byte array that contains the y coordinate in
|
// Compress the point into a 32 byte array that contains the y coordinate in
|
||||||
// little endian and the sign of the x coordinate.
|
// little endian and the sign of the x coordinate.
|
||||||
func (p *Point) Compress() [32]byte {
|
func (p *Point) Compress() [32]byte {
|
||||||
sign := false
|
sign := PointCoordSign(p.X)
|
||||||
if PointCoordSign(p.X) {
|
|
||||||
sign = true
|
|
||||||
}
|
|
||||||
return PackPoint(p.Y, sign)
|
return PackPoint(p.Y, sign)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
|
||||||
"github.com/iden3/go-iden3-crypto/mimc7"
|
"github.com/iden3/go-iden3-crypto/mimc7"
|
||||||
|
"github.com/iden3/go-iden3-crypto/poseidon"
|
||||||
"github.com/iden3/go-iden3-crypto/utils"
|
"github.com/iden3/go-iden3-crypto/utils"
|
||||||
|
|
||||||
"math/big"
|
"math/big"
|
||||||
@@ -208,3 +209,45 @@ func (p *PublicKey) VerifyMimc7(msg *big.Int, sig *Signature) bool {
|
|||||||
right.Add(sig.R8, right) // right = 8 * R + 8 * hm * A
|
right.Add(sig.R8, right) // right = 8 * R + 8 * hm * A
|
||||||
return (left.X.Cmp(right.X) == 0) && (left.Y.Cmp(right.Y) == 0)
|
return (left.X.Cmp(right.X) == 0) && (left.Y.Cmp(right.Y) == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignPoseidon signs a message encoded as a big.Int in Zq using blake-512 hash
|
||||||
|
// for buffer hashing and Poseidon for big.Int hashing.
|
||||||
|
func (k *PrivateKey) SignPoseidon(msg *big.Int) *Signature {
|
||||||
|
h1 := Blake512(k[:])
|
||||||
|
msgBuf := utils.BigIntLEBytes(msg)
|
||||||
|
msgBuf32 := [32]byte{}
|
||||||
|
copy(msgBuf32[:], msgBuf[:])
|
||||||
|
rBuf := Blake512(append(h1[32:], msgBuf32[:]...))
|
||||||
|
r := utils.SetBigIntFromLEBytes(new(big.Int), rBuf) // r = H(H_{32..63}(k), msg)
|
||||||
|
r.Mod(r, SubOrder)
|
||||||
|
R8 := NewPoint().Mul(r, B8) // R8 = r * 8 * B
|
||||||
|
A := k.Public().Point()
|
||||||
|
hmInput := []*big.Int{R8.X, R8.Y, A.X, A.Y, msg}
|
||||||
|
hm, err := poseidon.Hash(hmInput) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
S := new(big.Int).Lsh(k.Scalar().BigInt(), 3)
|
||||||
|
S = S.Mul(hm, S)
|
||||||
|
S.Add(r, S)
|
||||||
|
S.Mod(S, SubOrder) // S = r + hm * 8 * s
|
||||||
|
|
||||||
|
return &Signature{R8: R8, S: S}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyPoseidon verifies the signature of a message encoded as a big.Int in Zq
|
||||||
|
// using blake-512 hash for buffer hashing and Poseidon for big.Int hashing.
|
||||||
|
func (p *PublicKey) VerifyPoseidon(msg *big.Int, sig *Signature) bool {
|
||||||
|
hmInput := []*big.Int{sig.R8.X, sig.R8.Y, p.X, p.Y, msg}
|
||||||
|
hm, err := poseidon.Hash(hmInput) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
left := NewPoint().Mul(sig.S, B8) // left = s * 8 * B
|
||||||
|
r1 := big.NewInt(8)
|
||||||
|
r1.Mul(r1, hm)
|
||||||
|
right := NewPoint().Mul(r1, p.Point())
|
||||||
|
right.Add(sig.R8, right) // right = 8 * R + 8 * hm * A
|
||||||
|
return (left.X.Cmp(right.X) == 0) && (left.Y.Cmp(right.Y) == 0)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,13 +4,12 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/iden3/go-iden3-crypto/constants"
|
"github.com/iden3/go-iden3-crypto/constants"
|
||||||
"github.com/iden3/go-iden3-crypto/utils"
|
"github.com/iden3/go-iden3-crypto/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"math/big"
|
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func genInputs() (*PrivateKey, *big.Int) {
|
func genInputs() (*PrivateKey, *big.Int) {
|
||||||
@@ -26,7 +25,7 @@ func genInputs() (*PrivateKey, *big.Int) {
|
|||||||
return &k, msg
|
return &k, msg
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSignVerify1(t *testing.T) {
|
func TestSignVerifyMimc7(t *testing.T) {
|
||||||
var k PrivateKey
|
var k PrivateKey
|
||||||
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||||
msgBuf, err := hex.DecodeString("00010203040506070809")
|
msgBuf, err := hex.DecodeString("00010203040506070809")
|
||||||
@@ -70,6 +69,50 @@ func TestSignVerify1(t *testing.T) {
|
|||||||
assert.Equal(t, true, ok)
|
assert.Equal(t, true, ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSignVerifyPoseidon(t *testing.T) {
|
||||||
|
var k PrivateKey
|
||||||
|
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||||
|
msgBuf, err := hex.DecodeString("00010203040506070809")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
msg := utils.SetBigIntFromLEBytes(new(big.Int), msgBuf)
|
||||||
|
|
||||||
|
pk := k.Public()
|
||||||
|
assert.Equal(t,
|
||||||
|
"13277427435165878497778222415993513565335242147425444199013288855685581939618",
|
||||||
|
pk.X.String())
|
||||||
|
assert.Equal(t,
|
||||||
|
"13622229784656158136036771217484571176836296686641868549125388198837476602820",
|
||||||
|
pk.Y.String())
|
||||||
|
|
||||||
|
sig := k.SignPoseidon(msg)
|
||||||
|
assert.Equal(t,
|
||||||
|
"11384336176656855268977457483345535180380036354188103142384839473266348197733",
|
||||||
|
sig.R8.X.String())
|
||||||
|
assert.Equal(t,
|
||||||
|
"15383486972088797283337779941324724402501462225528836549661220478783371668959",
|
||||||
|
sig.R8.Y.String())
|
||||||
|
assert.Equal(t,
|
||||||
|
"248298168863866362217836334079793350221620631973732197668910946177382043688",
|
||||||
|
sig.S.String())
|
||||||
|
|
||||||
|
ok := pk.VerifyPoseidon(msg, sig)
|
||||||
|
assert.Equal(t, true, ok)
|
||||||
|
|
||||||
|
sigBuf := sig.Compress()
|
||||||
|
sig2, err := new(Signature).Decompress(sigBuf)
|
||||||
|
assert.Equal(t, nil, err)
|
||||||
|
|
||||||
|
assert.Equal(t, ""+
|
||||||
|
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+
|
||||||
|
"28506bce274aa1b3f7e7c2fd7e4fe09bff8f9aa37a42def7994e98f322888c00",
|
||||||
|
hex.EncodeToString(sigBuf[:]))
|
||||||
|
|
||||||
|
ok = pk.VerifyPoseidon(msg, sig2)
|
||||||
|
assert.Equal(t, true, ok)
|
||||||
|
}
|
||||||
|
|
||||||
func TestCompressDecompress(t *testing.T) {
|
func TestCompressDecompress(t *testing.T) {
|
||||||
var k PrivateKey
|
var k PrivateKey
|
||||||
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||||
|
|||||||
Reference in New Issue
Block a user