From 7f1df6d8d3373009c82d318c0f8a18875b141a34 Mon Sep 17 00:00:00 2001 From: Quint Daenen Date: Sat, 17 Aug 2024 08:47:25 +0200 Subject: [PATCH] Replace BLS w/ non-cgo based module. --- certification/bls/bls.go | 111 +++++++++++++++-------- certification/bls/bls_test.go | 12 +-- certification/certificate.go | 2 +- clients/registry/proto/v1/operator.pb.go | 108 +++++++++++----------- go.mod | 11 ++- go.sum | 28 +++++- 6 files changed, 167 insertions(+), 105 deletions(-) diff --git a/certification/bls/bls.go b/certification/bls/bls.go index f0ebeab..7f3b68d 100644 --- a/certification/bls/bls.go +++ b/certification/bls/bls.go @@ -1,70 +1,101 @@ package bls -import "github.com/herumi/bls-go-binary/bls" - -const ( - dstG1 = "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_" - publicKeyGenerator = "1 0x24aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be" +import ( + "encoding/hex" + "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "math/big" ) -func init() { - if err := bls.Init(bls.BLS12_381); err != nil { - panic(err) - } - - // Set Ethereum serialization format. - bls.SetETHserialization(true) - if err := bls.SetMapToMode(bls.IRTF); err != nil { - panic(err) - } +const dstG1 = "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_" - // Set the generator of G2. see https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html#section-4.2.1 - var gen bls.PublicKey - if err := gen.SetHexString(publicKeyGenerator); err != nil { - panic(err) - } - if err := bls.SetGeneratorOfPublicKey(&gen); err != nil { - panic(err) - } +var ( + g2, g2Gen bls12381.G2Affine +) - if err := bls.SetDstG1(dstG1); err != nil { - panic(err) - } +func init() { + _, _, _, g2Gen = bls12381.Generators() + g2.Neg(&g2Gen) } -type PublicKey = bls.PublicKey +type PublicKey bls12381.G2Affine // PublicKeyFromBytes returns a PublicKey from a byte slice. func PublicKeyFromBytes(b []byte) (*PublicKey, error) { - var pub bls.PublicKey - return &pub, pub.Deserialize(b) + var g2 bls12381.G2Affine + if err := g2.Unmarshal(b); err != nil { + return nil, err + } + return (*PublicKey)(&g2), nil } // PublicKeyFromHexString returns a PublicKey from a hex string. func PublicKeyFromHexString(s string) (*PublicKey, error) { - var pub bls.PublicKey - return &pub, pub.DeserializeHexStr(s) + raw, err := hex.DecodeString(s) + if err != nil { + return nil, err + } + return PublicKeyFromBytes(raw) } -type SecretKey = bls.SecretKey +type SecretKey fr.Element // NewSecretKeyByCSPRNG returns a new SecretKey generated by CSPRNG. func NewSecretKeyByCSPRNG() *SecretKey { - var sk bls.SecretKey - sk.SetByCSPRNG() - return &sk + var e fr.Element + if _, err := e.SetRandom(); err != nil { + return nil + } + return (*SecretKey)(&e) +} + +func (sk *SecretKey) GetPublicKey() *PublicKey { + e := fr.Element(*sk) + pk := g2Gen.ScalarMultiplication( + &g2Gen, + e.BigInt(big.NewInt(0)), + ) + return (*PublicKey)(pk) +} + +func (sk *SecretKey) Sign(msg []byte) *Signature { + e := fr.Element(*sk) + g1, _ := bls12381.HashToG1(msg, []byte(dstG1)) + sig := g1.ScalarMultiplication( + &g1, + e.BigInt(big.NewInt(0)), + ) + return (*Signature)(sig) } -type Signature = bls.Sign +type Signature bls12381.G1Affine // SignatureFromBytes returns a Signature from a byte slice. func SignatureFromBytes(b []byte) (*Signature, error) { - var sig bls.Sign - return &sig, sig.Deserialize(b) + var sig bls12381.G1Affine + if _, err := sig.SetBytes(b); err != nil { + return nil, err + } + return (*Signature)(&sig), nil } // SignatureFromHexString returns a Signature from a hex string. func SignatureFromHexString(s string) (*Signature, error) { - var sig bls.Sign - return &sig, sig.DeserializeHexStr(s) + raw, err := hex.DecodeString(s) + if err != nil { + return nil, err + } + return SignatureFromBytes(raw) +} + +// Verify returns true if the signature is valid for the message. +func (sig *Signature) Verify(pk *PublicKey, msg []byte) bool { + g1, _ := bls12381.HashToG1(msg, []byte(dstG1)) + valid, err := bls12381.PairingCheck( + []bls12381.G1Affine{bls12381.G1Affine(*sig), g1}, + []bls12381.G2Affine{g2, bls12381.G2Affine(*pk)}) + if err != nil { + return false + } + return valid } diff --git a/certification/bls/bls_test.go b/certification/bls/bls_test.go index 5811088..0da6bdc 100644 --- a/certification/bls/bls_test.go +++ b/certification/bls/bls_test.go @@ -6,9 +6,9 @@ import ( ) func TestSecretKey(t *testing.T) { + msg := []byte("hello") sk := NewSecretKeyByCSPRNG() - s := sk.Sign("hello") - if !s.Verify(sk.GetPublicKey(), "hello") { + if !sk.Sign(msg).Verify(sk.GetPublicKey(), msg) { t.Error() } } @@ -29,10 +29,10 @@ func TestVerify(t *testing.T) { t.Fatal(err) } - if signature.Verify(publicKey, "bye") { + if signature.Verify(publicKey, []byte("bye")) { t.Error() } - if !signature.Verify(publicKey, "hello") { + if !signature.Verify(publicKey, []byte("hello")) { t.Error() } } @@ -51,10 +51,10 @@ func TestVerify_hex(t *testing.T) { t.Fatal(err) } - if signature.Verify(publicKey, "bye") { + if signature.Verify(publicKey, []byte("bye")) { t.Error() } - if !signature.Verify(publicKey, "hello") { + if !signature.Verify(publicKey, []byte("hello")) { t.Error() } } diff --git a/certification/certificate.go b/certification/certificate.go index 3082615..058ce58 100644 --- a/certification/certificate.go +++ b/certification/certificate.go @@ -163,7 +163,7 @@ func verifyCertificateSignature(certificate Certificate, publicKey *bls.PublicKe if err != nil { return err } - if !signature.VerifyByte(publicKey, message) { + if !signature.Verify(publicKey, message) { return fmt.Errorf("signature verification failed") } return nil diff --git a/clients/registry/proto/v1/operator.pb.go b/clients/registry/proto/v1/operator.pb.go index 430bc94..32b40e1 100644 --- a/clients/registry/proto/v1/operator.pb.go +++ b/clients/registry/proto/v1/operator.pb.go @@ -83,6 +83,57 @@ var file_operator_proto_rawDesc = []byte{ 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } +func file_operator_proto_init() { + if File_operator_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_operator_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*NodeOperatorRecord); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_operator_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*RemoveNodeOperatorsPayload); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_operator_proto_msgTypes[0].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_operator_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_operator_proto_goTypes, + DependencyIndexes: file_operator_proto_depIdxs, + MessageInfos: file_operator_proto_msgTypes, + }.Build() + File_operator_proto = out.File + file_operator_proto_rawDesc = nil + file_operator_proto_goTypes = nil + file_operator_proto_depIdxs = nil +} + func file_operator_proto_rawDescGZIP() []byte { file_operator_proto_rawDescOnce.Do(func() { file_operator_proto_rawDescData = protoimpl.X.CompressGZIP(file_operator_proto_rawDescData) @@ -90,6 +141,8 @@ func file_operator_proto_rawDescGZIP() []byte { return file_operator_proto_rawDescData } +func init() { file_operator_proto_init() } + // A record for a node operator. Each node operator is associated with a // unique principal id, a.k.a. NOID. // @@ -212,9 +265,7 @@ func (x *RemoveNodeOperatorsPayload) GetNodeOperatorsToRemove() [][]byte { } return nil } - func (*RemoveNodeOperatorsPayload) ProtoMessage() {} - func (x *RemoveNodeOperatorsPayload) ProtoReflect() protoreflect.Message { mi := &file_operator_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { @@ -226,6 +277,7 @@ func (x *RemoveNodeOperatorsPayload) ProtoReflect() protoreflect.Message { } return mi.MessageOf(x) } + func (x *RemoveNodeOperatorsPayload) Reset() { *x = RemoveNodeOperatorsPayload{} if protoimpl.UnsafeEnabled { @@ -237,55 +289,3 @@ func (x *RemoveNodeOperatorsPayload) Reset() { func (x *RemoveNodeOperatorsPayload) String() string { return protoimpl.X.MessageStringOf(x) } - -func init() { file_operator_proto_init() } -func file_operator_proto_init() { - if File_operator_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_operator_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*NodeOperatorRecord); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_operator_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*RemoveNodeOperatorsPayload); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_operator_proto_msgTypes[0].OneofWrappers = []any{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_operator_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_operator_proto_goTypes, - DependencyIndexes: file_operator_proto_depIdxs, - MessageInfos: file_operator_proto_msgTypes, - }.Build() - File_operator_proto = out.File - file_operator_proto_rawDesc = nil - file_operator_proto_goTypes = nil - file_operator_proto_depIdxs = nil -} diff --git a/go.mod b/go.mod index 2272231..7f8103b 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,17 @@ go 1.22.1 require ( github.com/aviate-labs/leb128 v0.3.0 github.com/aviate-labs/secp256k1 v0.0.0-5e6736a + github.com/consensys/gnark-crypto v0.13.0 github.com/di-wu/parser v0.3.0 github.com/fxamacker/cbor/v2 v2.6.0 - github.com/herumi/bls-go-binary v1.34.0 google.golang.org/protobuf v1.34.1 ) -require github.com/x448/float16 v0.8.4 // indirect +require ( + github.com/bits-and-blooms/bitset v1.7.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/x448/float16 v0.8.4 // indirect + golang.org/x/sys v0.15.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) diff --git a/go.sum b/go.sum index 9ade8c0..3f3a917 100644 --- a/go.sum +++ b/go.sum @@ -2,17 +2,41 @@ github.com/aviate-labs/leb128 v0.3.0 h1:s9htRv3OYk8nuHqJu9PiVFJxv1jIUTIcpEeiURa9 github.com/aviate-labs/leb128 v0.3.0/go.mod h1:GclhBOjhIKmcDlgHKhj0AEZollzERfZUbcRUKiQVqgY= github.com/aviate-labs/secp256k1 v0.0.0-5e6736a h1:aQkG/D+l8Y7tr809l8pN+KebH2jzacWReSFQmeEKFgM= github.com/aviate-labs/secp256k1 v0.0.0-5e6736a/go.mod h1:C/lr3F9TimrVkdZckG5mz+VU0TrmpeyVKUjzv2YyGwA= +github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= +github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.13.0 h1:VPULb/v6bbYELAPTDFINEVaMTTybV5GLxDdcjnS+4oc= +github.com/consensys/gnark-crypto v0.13.0/go.mod h1:wKqwsieaKPThcFkHe0d0zMsbHEUWFmZcG7KBCse210o= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/di-wu/parser v0.3.0 h1:NMOvy5ifswgt4gsdhySVcKOQtvjC43cHZIfViWctqQY= github.com/di-wu/parser v0.3.0/go.mod h1:SLp58pW6WamdmznrVRrw2NTyn4wAvT9rrEFynKX7nYo= github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/herumi/bls-go-binary v1.34.0 h1:x1sKp8zzx+alvlifB+vbA0KkY0Pz4Br31cZ/saDkiFE= -github.com/herumi/bls-go-binary v1.34.0/go.mod h1:O4Vp1AfR4raRGwFeQpr9X/PQtncEicMoOe6BQt1oX0Y= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=