Skip to content

Commit

Permalink
Merge pull request #825 from multiversx/multiBLS-secpr1-more-crypto
Browse files Browse the repository at this point in the history
Multi bls secpr1 more crypto
  • Loading branch information
sasurobert authored May 7, 2024
2 parents 4958bb2 + 59fd4f9 commit 8e89ddb
Show file tree
Hide file tree
Showing 63 changed files with 2,418 additions and 1,303 deletions.
25 changes: 0 additions & 25 deletions .github/workflows/build-test-macos-arm64.yml

This file was deleted.

14 changes: 11 additions & 3 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ jobs:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Test
run: |
make test

- name: Test (Linux)
if: runner.os == 'Linux'
run: |
make test
- name: Test (MacOS ARM64)
if: runner.os == 'macOS'
run: |
make test-w2
37 changes: 20 additions & 17 deletions config/gasCost.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,23 +173,26 @@ type BigFloatAPICost struct {

// CryptoAPICost defines the crypto operations gas cost config structure
type CryptoAPICost struct {
SHA256 uint64
Keccak256 uint64
Ripemd160 uint64
VerifyBLS uint64
VerifyEd25519 uint64
VerifySecp256k1 uint64
EllipticCurveNew uint64
AddECC uint64
DoubleECC uint64
IsOnCurveECC uint64
ScalarMultECC uint64
MarshalECC uint64
MarshalCompressedECC uint64
UnmarshalECC uint64
UnmarshalCompressedECC uint64
GenerateKeyECC uint64
EncodeDERSig uint64
SHA256 uint64
Keccak256 uint64
Ripemd160 uint64
VerifyBLS uint64
VerifyEd25519 uint64
VerifySecp256k1 uint64
EllipticCurveNew uint64
AddECC uint64
DoubleECC uint64
IsOnCurveECC uint64
ScalarMultECC uint64
MarshalECC uint64
MarshalCompressedECC uint64
UnmarshalECC uint64
UnmarshalCompressedECC uint64
GenerateKeyECC uint64
EncodeDERSig uint64
VerifySecp256r1 uint64
VerifyBLSSignatureShare uint64
VerifyBLSMultiSig uint64
}

// ManagedBufferAPICost defines the managed buffer operations gas cost config structure
Expand Down
3 changes: 3 additions & 0 deletions config/gasSchedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,9 @@ func FillGasMapCryptoAPICosts(value uint64) map[string]uint64 {
gasMap["UnmarshalCompressedECC"] = value
gasMap["GenerateKeyECC"] = value
gasMap["EncodeDERSig"] = value
gasMap["VerifySecp256r1"] = value
gasMap["VerifyBLSSignatureShare"] = value
gasMap["VerifyBLSMultiSig"] = value

return gasMap
}
Expand Down
26 changes: 18 additions & 8 deletions crypto/factory/cryptovm.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,30 @@ import (
"github.com/multiversx/mx-chain-vm-go/crypto/hashing"
"github.com/multiversx/mx-chain-vm-go/crypto/signing/bls"
"github.com/multiversx/mx-chain-vm-go/crypto/signing/ed25519"
"github.com/multiversx/mx-chain-vm-go/crypto/signing/secp256k1"
"github.com/multiversx/mx-chain-vm-go/crypto/signing/secp256"
)

// NewVMCrypto returns a composite struct containing VMCrypto functionality implementations
func NewVMCrypto() crypto.VMCrypto {
func NewVMCrypto() (crypto.VMCrypto, error) {
blsVerifier, err := bls.NewBLS()
if err != nil {
return nil, err
}

secp, err := secp256.NewSecp256()
if err != nil {
return nil, err
}

return struct {
crypto.Hasher
crypto.Ed25519
crypto.BLS
crypto.Secp256k1
crypto.Secp256
}{
Hasher: hashing.NewHasher(),
Ed25519: ed25519.NewEd25519Signer(),
BLS: bls.NewBLS(),
Secp256k1: secp256k1.NewSecp256k1(),
}
Hasher: hashing.NewHasher(),
Ed25519: ed25519.NewEd25519Signer(),
BLS: blsVerifier,
Secp256: secp,
}, nil
}
9 changes: 6 additions & 3 deletions crypto/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,26 @@ type Hasher interface {
// BLS defines the functionality of a component able to verify BLS signatures
type BLS interface {
VerifyBLS(key []byte, msg []byte, sig []byte) error
VerifySignatureShare(publicKey []byte, message []byte, sig []byte) error
VerifyAggregatedSig(pubKeysSigners [][]byte, message []byte, aggSig []byte) error
}

// Ed25519 defines the functionality of a component able to verify Ed25519 signatures
type Ed25519 interface {
VerifyEd25519(key []byte, msg []byte, sig []byte) error
}

// Secp256k1 defines the functionality of a component able to verify and encode Secp256k1 signatures
type Secp256k1 interface {
// Secp256 defines the functionality of a component able to verify and encode Secp256 signatures
type Secp256 interface {
VerifySecp256k1(key []byte, msg []byte, sig []byte, hashType uint8) error
EncodeSecp256k1DERSignature(r, s []byte) []byte
VerifySecp256r1(key []byte, msg []byte, sig []byte) error
}

// VMCrypto will provide the interface to the main crypto functionalities of the vm
type VMCrypto interface {
Hasher
Ed25519
BLS
Secp256k1
Secp256
}
21 changes: 19 additions & 2 deletions crypto/signing/bls/bls.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,29 @@ import (
"github.com/multiversx/mx-chain-crypto-go"
"github.com/multiversx/mx-chain-crypto-go/signing"
"github.com/multiversx/mx-chain-crypto-go/signing/mcl"
mclMultiSig "github.com/multiversx/mx-chain-crypto-go/signing/mcl/multisig"
"github.com/multiversx/mx-chain-crypto-go/signing/mcl/singlesig"
"github.com/multiversx/mx-chain-crypto-go/signing/multisig"
)

type bls struct {
keyGenerator crypto.KeyGenerator
signer crypto.SingleSigner

multiSigner crypto.MultiSigner
}

// NewBLS returns the component able to verify BLS signatures
func NewBLS() *bls {
func NewBLS() (*bls, error) {
b := &bls{}
suite := mcl.NewSuiteBLS12()
b.keyGenerator = signing.NewKeyGenerator(suite)
b.signer = singlesig.NewBlsSigner()

return b
var err error
b.multiSigner, err = multisig.NewBLSMultisig(&mclMultiSig.BlsMultiSignerKOSK{}, b.keyGenerator)

return b, err
}

// VerifyBLS verifies a BLS signatures
Expand All @@ -31,3 +38,13 @@ func (b *bls) VerifyBLS(key []byte, msg []byte, sig []byte) error {

return b.signer.Verify(publicKey, msg, sig)
}

// VerifySignatureShare verifies signature share of BLS MultiSig
func (b *bls) VerifySignatureShare(publicKey []byte, message []byte, sig []byte) error {
return b.multiSigner.VerifySignatureShare(publicKey, message, sig)
}

// VerifyAggregatedSig verifies aggregated signature of BLS MultiSig
func (b *bls) VerifyAggregatedSig(pubKeysSigners [][]byte, message []byte, aggSig []byte) error {
return b.multiSigner.VerifyAggregatedSig(pubKeysSigners, message, aggSig)
}
117 changes: 116 additions & 1 deletion crypto/signing/bls/bls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,70 @@ package bls

import (
"encoding/hex"
"fmt"
"strings"
"testing"

crypto "github.com/multiversx/mx-chain-crypto-go"
"github.com/multiversx/mx-chain-crypto-go/signing"
"github.com/multiversx/mx-chain-crypto-go/signing/mcl"
llsig "github.com/multiversx/mx-chain-crypto-go/signing/mcl/multisig"
"github.com/multiversx/mx-chain-crypto-go/signing/multisig"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type multiSignerSetup struct {
privKeys [][]byte
pubKeys [][]byte
partialSignatures [][][]byte
messages []string
aggSignatures [][]byte
}

const checkOK = "3e886a4c6e109a151f4105aee65a5192d150ef1fa68d3cd76964a0b086006dbe4324c989deb0e4416c6d6706db1b1910eb2732f08842fb4886067b9ed191109ac2188d76002d2e11da80a3f0ea89fee6b59c834cc478a6bd49cb8a193b1abb16@e96bd0f36b70c5ccc0c4396343bd7d8255b8a526c55fa1e218511fafe6539b8e@04725db195e37aa237cdbbda76270d4a229b6e7a3651104dc58c4349c0388e8546976fe54a04240530b99064e434c90f"
const checkNOK = "2c9a358953f61d34401d7ee4175eec105c476b18baacab371e2f47270035b539d84ad79ba587552b7e38802be00ff7148fc2a9c7a7034ff1e63ee24602ee952235ad14ca7d36e2be617fb2c99ed22a7a2729d86ae9fbb4df06f957ba07fec50e@1e46d9cbb995e30b82485525c29f80ac78aca295a6e88a11c3df8f9a445494bb@be8c460db180d6254c712ead3aa81935bc9be15b919dd45cb152b3dece04762569778c5e70e7af03fa1c66409d4f4711"

func TestBls_VerifyBLS(t *testing.T) {
t.Parallel()

b := NewBLS()
b, _ := NewBLS()
assert.Nil(t, b.VerifyBLS(splitString(t, checkOK)))
assert.NotNil(t, b.VerifyBLS(splitString(t, checkNOK)))
}

func TestBls_VerifyBLSSigShare(t *testing.T) {
t.Parallel()

b, _ := NewBLS()
assert.Nil(t, b.VerifySignatureShare(splitString(t, checkOK)))
assert.NotNil(t, b.VerifySignatureShare(splitString(t, checkNOK)))
}

func TestBls_VerifyBLSMultiSig(t *testing.T) {
t.Parallel()

b, _ := NewBLS()

numMessages := 5
setupKOSK, multiSignerKOSK := createMultiSigSetupKOSK(uint16(numMessages), numMessages)
setupKOSK.aggSignatures = aggregateSignatures(setupKOSK, multiSignerKOSK)

for i := 0; i < len(setupKOSK.pubKeys); i++ {
fmt.Println(hex.EncodeToString(setupKOSK.pubKeys[i]))
}
fmt.Println(setupKOSK.messages[0])
fmt.Println(hex.EncodeToString(setupKOSK.aggSignatures[0]))

for i := 0; i < numMessages; i++ {
assert.Nil(t, b.VerifyAggregatedSig(setupKOSK.pubKeys, []byte(setupKOSK.messages[i]), setupKOSK.aggSignatures[i]))
changedSig := make([]byte, len(setupKOSK.aggSignatures[i]))
copy(changedSig, setupKOSK.aggSignatures[i])
changedSig[0] += 1
assert.NotNil(t, b.VerifyAggregatedSig(setupKOSK.pubKeys, []byte(setupKOSK.messages[i]), changedSig))
}
}

func splitString(t testing.TB, str string) ([]byte, []byte, []byte) {
split := strings.Split(str, "@")
pkBuff, err := hex.DecodeString(split[0])
Expand All @@ -33,3 +79,72 @@ func splitString(t testing.TB, str string) ([]byte, []byte, []byte) {

return pkBuff, msgBuff, sigBuff
}

func createKeysAndMultiSignerBlsKOSK(
grSize uint16,
suite crypto.Suite,
) ([][]byte, [][]byte, crypto.MultiSigner) {

kg, privKeys, pubKeys := createMultiSignerSetup(grSize, suite)
llSigner := &llsig.BlsMultiSignerKOSK{}
multiSigner, _ := multisig.NewBLSMultisig(llSigner, kg)

return privKeys, pubKeys, multiSigner
}

func createMultiSignerSetup(grSize uint16, suite crypto.Suite) (crypto.KeyGenerator, [][]byte, [][]byte) {
kg := signing.NewKeyGenerator(suite)
privKeys := make([][]byte, grSize)
pubKeys := make([][]byte, grSize)

for i := uint16(0); i < grSize; i++ {
sk, pk := kg.GeneratePair()
privKeys[i], _ = sk.ToByteArray()
pubKeys[i], _ = pk.ToByteArray()
}
return kg, privKeys, pubKeys
}

func createSignaturesShares(privKeys [][]byte, multiSigner crypto.MultiSigner, message []byte) [][]byte {
sigShares := make([][]byte, len(privKeys))
for i := uint16(0); i < uint16(len(privKeys)); i++ {
sigShares[i], _ = multiSigner.CreateSignatureShare(privKeys[i], message)
}

return sigShares
}

func createMultiSigSetupKOSK(numSigners uint16, numMessages int) (*multiSignerSetup, crypto.MultiSigner) {
var multiSigner crypto.MultiSigner
setup := &multiSignerSetup{}
suite := mcl.NewSuiteBLS12()
setup.privKeys, setup.pubKeys, multiSigner = createKeysAndMultiSignerBlsKOSK(numSigners, suite)
setup.messages, setup.partialSignatures = createMessagesAndPartialSignatures(numMessages, setup.privKeys, multiSigner)

return setup, multiSigner
}

func createMessagesAndPartialSignatures(numMessages int, privKeys [][]byte, multiSigner crypto.MultiSigner) ([]string, [][][]byte) {
partialSignatures := make([][][]byte, numMessages)
messages := make([]string, numMessages)

for i := 0; i < numMessages; i++ {
messages[i] = fmt.Sprintf("message%d", i)
signatures := createSignaturesShares(privKeys, multiSigner, []byte(messages[i]))
partialSignatures[i] = signatures
}

return messages, partialSignatures
}

func aggregateSignatures(
setup *multiSignerSetup,
multiSigner crypto.MultiSigner,
) [][]byte {
aggSignatures := make([][]byte, len(setup.messages))
for i := 0; i < len(setup.messages); i++ {
aggSignatures[i], _ = multiSigner.AggregateSigs(setup.pubKeys, setup.partialSignatures[i])
}

return aggSignatures
}
Loading

0 comments on commit 8e89ddb

Please sign in to comment.