mirror of
https://github.com/arnaucube/go-iden3-crypto.git
synced 2026-02-07 11:36:41 +01:00
Merge pull request #55 from iden3/feature/PID-676-support-golang-interfaces
PID-676: support hash interface for poseidon; support golang crypto interfaces…
This commit is contained in:
81
babyjub/babyjub_wrapper.go
Normal file
81
babyjub/babyjub_wrapper.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package babyjub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BjjWrappedPublicKey is a wrapper for PublicKey.
|
||||||
|
type BjjWrappedPublicKey struct {
|
||||||
|
pubKey *PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns true if the public keys are equal.
|
||||||
|
func (pub *BjjWrappedPublicKey) Equal(x crypto.PublicKey) bool {
|
||||||
|
var xk *BjjWrappedPublicKey
|
||||||
|
switch x := x.(type) {
|
||||||
|
case BjjWrappedPublicKey:
|
||||||
|
xk = &x
|
||||||
|
case *BjjWrappedPublicKey:
|
||||||
|
xk = x
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return pub.pubKey.X.Cmp(xk.pubKey.X) == 0 &&
|
||||||
|
pub.pubKey.Y.Cmp(xk.pubKey.Y) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// BjjWrappedPrivateKey is a wrapper for PrivateKey.
|
||||||
|
type BjjWrappedPrivateKey struct {
|
||||||
|
privKey *PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBjjWrappedKey creates a new BjjWrappedPrivateKey.
|
||||||
|
func NewBjjWrappedKey(privKey *PrivateKey) *BjjWrappedPrivateKey {
|
||||||
|
return &BjjWrappedPrivateKey{privKey}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomBjjWrappedKey creates a new BjjWrappedPrivateKey with a random private key.
|
||||||
|
func RandomBjjWrappedKey() *BjjWrappedPrivateKey {
|
||||||
|
privKey := NewRandPrivKey()
|
||||||
|
return NewBjjWrappedKey(&privKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public returns the public key of the private key.
|
||||||
|
func (w *BjjWrappedPrivateKey) Public() crypto.PublicKey {
|
||||||
|
return &BjjWrappedPublicKey{w.privKey.Public()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign signs the digest with the private key.
|
||||||
|
func (w *BjjWrappedPrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
|
||||||
|
hash := opts.HashFunc()
|
||||||
|
|
||||||
|
switch hash {
|
||||||
|
// alredy hashed
|
||||||
|
case crypto.Hash(0):
|
||||||
|
default:
|
||||||
|
hasher := hash.New()
|
||||||
|
hasher.Write(digest)
|
||||||
|
digest = hasher.Sum(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
digestBI := big.NewInt(0).SetBytes(digest)
|
||||||
|
sig := w.privKey.SignPoseidon(digestBI)
|
||||||
|
return sig.Compress().MarshalText()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns true if the private keys are equal.
|
||||||
|
func (w *BjjWrappedPrivateKey) Equal(x crypto.PrivateKey) bool {
|
||||||
|
var xk *BjjWrappedPrivateKey
|
||||||
|
switch x := x.(type) {
|
||||||
|
case BjjWrappedPrivateKey:
|
||||||
|
xk = &x
|
||||||
|
case *BjjWrappedPrivateKey:
|
||||||
|
xk = x
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return bytes.Equal(w.privKey[:], xk.privKey[:])
|
||||||
|
}
|
||||||
65
babyjub/babyjub_wrapper_test.go
Normal file
65
babyjub/babyjub_wrapper_test.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package babyjub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/rand"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/iden3/go-iden3-crypto/poseidon"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://pkg.go.dev/crypto#PrivateKey
|
||||||
|
type shadowPrivateKey interface {
|
||||||
|
Public() crypto.PublicKey
|
||||||
|
Equal(x crypto.PrivateKey) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://pkg.go.dev/crypto#PublicKey
|
||||||
|
type shadowPublicKey interface {
|
||||||
|
Equal(x crypto.PublicKey) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBjjWrappedPrivateKeyInterfaceImpl(t *testing.T) {
|
||||||
|
require.Implements(t, (*crypto.Signer)(nil), new(BjjWrappedPrivateKey))
|
||||||
|
require.Implements(t, (*shadowPrivateKey)(nil), new(BjjWrappedPrivateKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBjjWrappedPrivateKey(t *testing.T) {
|
||||||
|
pk := RandomBjjWrappedKey()
|
||||||
|
|
||||||
|
hasher, err := poseidon.New(16)
|
||||||
|
require.NoError(t, err)
|
||||||
|
hasher.Write([]byte("test"))
|
||||||
|
digest := hasher.Sum(nil)
|
||||||
|
|
||||||
|
sig, err := pk.Sign(rand.Reader, digest, crypto.Hash(0))
|
||||||
|
require.NoError(t, err)
|
||||||
|
pub, ok := pk.Public().(*BjjWrappedPublicKey)
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
decomrpessSig, err := DecompressSig(sig)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
digestBI := big.NewInt(0).SetBytes(digest)
|
||||||
|
pub.pubKey.VerifyPoseidon(digestBI, decomrpessSig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBjjWrappedPrivateKeyEqual(t *testing.T) {
|
||||||
|
x1 := RandomBjjWrappedKey()
|
||||||
|
require.True(t, x1.Equal(x1))
|
||||||
|
x2 := RandomBjjWrappedKey()
|
||||||
|
require.False(t, x1.Equal(x2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBjjWrappedPublicKeyInterfaceImpl(t *testing.T) {
|
||||||
|
require.Implements(t, (*shadowPublicKey)(nil), new(BjjWrappedPublicKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBjjWrappedPublicKeyEqual(t *testing.T) {
|
||||||
|
x1 := RandomBjjWrappedKey().Public().(*BjjWrappedPublicKey)
|
||||||
|
require.True(t, x1.Equal(x1))
|
||||||
|
x2 := RandomBjjWrappedKey().Public()
|
||||||
|
require.False(t, x1.Equal(x2))
|
||||||
|
}
|
||||||
@@ -18,3 +18,16 @@ func Blake512(m []byte) []byte {
|
|||||||
}
|
}
|
||||||
return h.Sum(nil)
|
return h.Sum(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecompressSig decompresses a compressed signature.
|
||||||
|
func DecompressSig(commpresedSig []byte) (*Signature, error) {
|
||||||
|
poseidonComSig := &SignatureComp{}
|
||||||
|
if err := poseidonComSig.UnmarshalText(commpresedSig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
poseidonDecSig, err := poseidonComSig.Decompress()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return poseidonDecSig, nil
|
||||||
|
}
|
||||||
|
|||||||
60
poseidon/poseidon_wrapper.go
Normal file
60
poseidon/poseidon_wrapper.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package poseidon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"hash"
|
||||||
|
)
|
||||||
|
|
||||||
|
type hasher struct {
|
||||||
|
buf *bytes.Buffer
|
||||||
|
frameSize int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum returns the Poseidon hash of the input bytes.
|
||||||
|
// use frame size of 16 inputs by default
|
||||||
|
func Sum(b []byte) []byte {
|
||||||
|
h, _ := New(16)
|
||||||
|
h.Write(b)
|
||||||
|
return h.Sum(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new hash.Hash computing the Poseidon hash.
|
||||||
|
func New(frameSize int) (hash.Hash, error) {
|
||||||
|
if frameSize < 2 || frameSize > 16 {
|
||||||
|
return nil, errors.New("incorrect frame size")
|
||||||
|
}
|
||||||
|
return &hasher{
|
||||||
|
buf: bytes.NewBuffer([]byte{}),
|
||||||
|
frameSize: frameSize,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write (via the embedded io.Writer interface) adds more data to the running hash.
|
||||||
|
func (h *hasher) Write(p []byte) (n int, err error) {
|
||||||
|
return h.buf.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum returns the Poseidon digest of the data.
|
||||||
|
func (h *hasher) Sum(b []byte) []byte {
|
||||||
|
hahs, err := HashBytesX(h.buf.Bytes(), h.frameSize)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return append(b, hahs.Bytes()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset resets the Hash to its initial state.
|
||||||
|
func (h *hasher) Reset() {
|
||||||
|
h.buf.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the number of bytes Sum will return.
|
||||||
|
func (h *hasher) Size() int {
|
||||||
|
return 32
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockSize returns the hash block size.
|
||||||
|
func (h *hasher) BlockSize() int {
|
||||||
|
return spongeChunkSize
|
||||||
|
}
|
||||||
483
poseidon/poseidon_wrapper_test.go
Normal file
483
poseidon/poseidon_wrapper_test.go
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user