Skip to content

Commit

Permalink
✨ feat(front): delete tss and add frost algothim >>> ⏰ 1.5
Browse files Browse the repository at this point in the history
  • Loading branch information
logicalangel committed May 18, 2024
1 parent 5acf9bb commit 5a61099
Show file tree
Hide file tree
Showing 13 changed files with 3,769 additions and 0 deletions.
47 changes: 47 additions & 0 deletions internal/crypto/bls/bls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package bls

import (
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
)

func Hash(message []byte) (bls12381.G1Affine, error) {
dst := []byte("UNCHAINED")
return bls12381.HashToG1(message, dst)
}

func RecoverSignature(bytes [48]byte) (bls12381.G1Affine, error) {
signature := new(bls12381.G1Affine)
_, err := signature.SetBytes(bytes[:])
return *signature, err
}

func RecoverPublicKey(bytes [96]byte) (bls12381.G2Affine, error) {
pk := new(bls12381.G2Affine)
_, err := pk.SetBytes(bytes[:])
return *pk, err
}

func AggregateSignatures(signatures [][]byte) ([]byte, error) {
signaturesBls := []bls12381.G1Affine{}

for _, signature := range signatures {
signatureBls, err := RecoverSignature([48]byte(signature))
if err != nil {
return nil, err
}

signaturesBls = append(signaturesBls, signatureBls)
}

aggregated := new(bls12381.G1Jac).FromAffine(&signaturesBls[0])

for _, sig := range signaturesBls[1:] {
sigJac := new(bls12381.G1Jac).FromAffine(&sig)
aggregated.AddAssign(sigJac)
}

aggregatedAffine := new(bls12381.G1Affine).FromJacobian(aggregated)
aggregatedAffineByte := aggregatedAffine.Bytes()

return aggregatedAffineByte[:], nil
}
130 changes: 130 additions & 0 deletions internal/crypto/bls/identity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package bls

import (
"crypto/rand"
"encoding/hex"
"math/big"

"github.com/TimeleapLabs/unchained/internal/consts"

"github.com/TimeleapLabs/unchained/internal/utils"
"github.com/btcsuite/btcutil/base58"
bls12381_fr "github.com/consensys/gnark-crypto/ecc/bls12-381/fr"

"github.com/TimeleapLabs/unchained/internal/utils/address"

"github.com/TimeleapLabs/unchained/internal/config"
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
)

// Signer represents a BLS identity.
type Signer struct {
Name string
SecretKey *big.Int
PublicKey *bls12381.G2Affine
ShortPublicKey *bls12381.G1Affine

g2Aff bls12381.G2Affine
g1Aff bls12381.G1Affine
}

// Sign will sign a data with bls secret and return signed data.
func (s *Signer) Sign(data []byte) ([]byte, error) {
hashedMessage, err := Hash(data)
if err != nil {
panic(err)
}

signature := new(bls12381.G1Affine).ScalarMultiplication(&hashedMessage, s.SecretKey).Bytes()

return signature[:], err
}

// WriteConfigs writes the secret key, public key and address to the global config object.
func (s *Signer) WriteConfigs() {
pkBytes := s.PublicKey.Bytes()
config.App.Secret.SecretKey = hex.EncodeToString(s.SecretKey.Bytes())
config.App.Secret.PublicKey = hex.EncodeToString(pkBytes[:])
config.App.Secret.Address = address.Calculate(pkBytes[:])
}

// Verify verifies the signature of a message belongs to the public key.
func (s *Signer) Verify(signature []byte, hashedMessage []byte, publicKey []byte) (bool, error) {
signatureBls, err := RecoverSignature([48]byte(signature))
if err != nil {
utils.Logger.With("Err", err).Error("Can't recover bls signature")
return false, consts.ErrInternalError
}

publicKeyBls, err := RecoverPublicKey([96]byte(publicKey))
if err != nil {
utils.Logger.With("Err", err).Error("Can't recover pub-key")
return false, consts.ErrInternalError
}

messageBls, err := Hash(hashedMessage)
if err != nil {
utils.Logger.With("Err", err).Error("Can't convert message to hash")
return false, consts.ErrInternalError
}

pairingSigG2, err := bls12381.Pair(
[]bls12381.G1Affine{signatureBls},
[]bls12381.G2Affine{s.g2Aff})
if err != nil {
return false, err
}

pairingHmPk, pairingError := bls12381.Pair(
[]bls12381.G1Affine{messageBls},
[]bls12381.G2Affine{publicKeyBls})

ok := pairingSigG2.Equal(&pairingHmPk)

return ok, pairingError
}

// NewIdentity creates a new BLS identity.
func NewIdentity() *Signer {
s := &Signer{
SecretKey: new(big.Int),
}

if config.App.Secret.SecretKey == "" && !config.App.System.AllowGenerateSecrets {
panic("BLS secret key is not provided and secrets generation is not allowed")
}

_, _, s.g1Aff, s.g2Aff = bls12381.Generators()

if config.App.Secret.SecretKey != "" {
decoded, err := hex.DecodeString(config.App.Secret.SecretKey)
if err != nil {
// TODO: Backwards compatibility with base58 encoded secret keys
// Remove this after a few releases
decoded = base58.Decode(config.App.Secret.SecretKey)
}

s.SecretKey.SetBytes(decoded)
s.PublicKey = new(bls12381.G2Affine).ScalarMultiplication(&s.g2Aff, s.SecretKey)
} else {
// generate a random point in G2
g2Order := bls12381_fr.Modulus()
sk, err := rand.Int(rand.Reader, g2Order)
if err != nil {
panic(err)
}

pk := new(bls12381.G2Affine).ScalarMultiplication(&s.g2Aff, sk)

s.SecretKey = sk
s.PublicKey = pk
}

s.ShortPublicKey = new(bls12381.G1Affine).ScalarMultiplication(&s.g1Aff, s.SecretKey)

utils.Logger.
With("Address", s.ShortPublicKey.String()).
Info("Unchained identity initialized")

return s
}
77 changes: 77 additions & 0 deletions internal/crypto/bls/identity_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package bls

import (
"crypto/rand"
"testing"

"github.com/TimeleapLabs/unchained/internal/config"
"github.com/TimeleapLabs/unchained/internal/utils"
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
bls12381_fr "github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)

var (
testData = []byte("HELLO hello")
secondTestData = []byte("HELLO hello 2")
)

type BlsIdentityTestSuite struct {
suite.Suite
identity *Signer
}

func (s *BlsIdentityTestSuite) SetupTest() {
utils.SetupLogger("info")

config.App.System.AllowGenerateSecrets = true
s.identity = NewIdentity()
}

func (s *BlsIdentityTestSuite) TestSign() {
signedData, err := s.identity.Sign(testData)
assert.NoError(s.T(), err)

publicKey := s.identity.PublicKey.Bytes()

s.Run("Should verify the message correctly", func() {
isVerified, err := s.identity.Verify(signedData, testData, publicKey[:])
assert.NoError(s.T(), err)
assert.True(s.T(), isVerified)
})

s.Run("Should not verify the message because of wrong data case", func() {
isVerified, err := s.identity.Verify(signedData, secondTestData, publicKey[:])
assert.NoError(s.T(), err)
assert.False(s.T(), isVerified)
})

s.Run("Should not verify the message because of wrong data case", func() {
signedSecondData, err := s.identity.Sign(secondTestData)
assert.NoError(s.T(), err)

isVerified, err := s.identity.Verify(signedSecondData, testData, publicKey[:])
assert.NoError(s.T(), err)
assert.False(s.T(), isVerified)
})

s.Run("Should not verify the message because publicKey is not belong to this message", func() {
_, _, _, g2Aff := bls12381.Generators()
g2Order := bls12381_fr.Modulus()
sk, err := rand.Int(rand.Reader, g2Order)
if err != nil {
panic(err)
}

pk := new(bls12381.G2Affine).ScalarMultiplication(&g2Aff, sk).Bytes()

isVerified, err := s.identity.Verify(signedData, secondTestData, pk[:])
assert.NoError(s.T(), err)
assert.False(s.T(), isVerified)
})
}

func TestBlsIdentitySuite(t *testing.T) {
suite.Run(t, new(BlsIdentityTestSuite))
}
2,644 changes: 2,644 additions & 0 deletions internal/crypto/ethereum/contracts/UnchainedStaking.go

Large diffs are not rendered by default.

Loading

0 comments on commit 5a61099

Please sign in to comment.