From 02396aac05010307be7dcee96f03379ed0bbb0ab Mon Sep 17 00:00:00 2001 From: Shivam Mantri Date: Tue, 14 Jan 2025 15:07:38 +0530 Subject: [PATCH] fix(grpc): sign and verify message by ed25519 --- www/grpc/utils.go | 66 +++++++++++++++++++++++++++++--------- www/grpc/utils_test.go | 73 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 15 deletions(-) diff --git a/www/grpc/utils.go b/www/grpc/utils.go index 8c1f7c985..9171eb2a5 100644 --- a/www/grpc/utils.go +++ b/www/grpc/utils.go @@ -3,6 +3,8 @@ package grpc import ( "context" "fmt" + "github.com/pactus-project/pactus/crypto/ed25519" + "strings" "github.com/pactus-project/pactus/crypto/bls" pactus "github.com/pactus-project/pactus/www/grpc/gen/go" @@ -23,12 +25,31 @@ func newUtilsServer(server *Server) *utilServer { func (*utilServer) SignMessageWithPrivateKey(_ context.Context, req *pactus.SignMessageWithPrivateKeyRequest, ) (*pactus.SignMessageWithPrivateKeyResponse, error) { - prvKey, err := bls.PrivateKeyFromString(req.PrivateKey) - if err != nil { - return nil, status.Error(codes.InvalidArgument, "invalid private key") + var sig string + + maybeBLSPrivateKey := func(str string) bool { + return strings.Contains(strings.ToLower(str), "secret1p") } - sig := prvKey.Sign([]byte(req.Message)).String() + maybeEd25519PrivateKey := func(str string) bool { + return strings.Contains(strings.ToLower(str), "secret1r") + } + switch { + case maybeBLSPrivateKey(req.PrivateKey): + blsPrv, err := bls.PrivateKeyFromString(req.PrivateKey) + if err != nil { + return nil, status.Error(codes.InvalidArgument, "invalid private key") + } + sig = blsPrv.Sign([]byte(req.Message)).String() + case maybeEd25519PrivateKey(req.PrivateKey): + ed25519Prv, err := ed25519.PrivateKeyFromString(req.PrivateKey) + if err != nil { + return nil, status.Error(codes.InvalidArgument, "invalid private key") + } + sig = ed25519Prv.Sign([]byte(req.Message)).String() + default: + return nil, status.Error(codes.InvalidArgument, "invalid private key") + } return &pactus.SignMessageWithPrivateKeyResponse{ Signature: sig, @@ -38,20 +59,35 @@ func (*utilServer) SignMessageWithPrivateKey(_ context.Context, func (*utilServer) VerifyMessage(_ context.Context, req *pactus.VerifyMessageRequest, ) (*pactus.VerifyMessageResponse, error) { - sig, err := bls.SignatureFromString(req.Signature) - if err != nil { - return nil, status.Error(codes.InvalidArgument, "signature is invalid") - } + blsPub, err := bls.PublicKeyFromString(req.PublicKey) - pub, err := bls.PublicKeyFromString(req.PublicKey) if err != nil { - return nil, status.Error(codes.InvalidArgument, "public key is invalid") - } + ed25519Pub, err := ed25519.PublicKeyFromString(req.PublicKey) + if err != nil { + return nil, status.Error(codes.InvalidArgument, "public key is invalid") + } + + sig, err := ed25519.SignatureFromString(req.Signature) + if err != nil { + return nil, status.Error(codes.InvalidArgument, "signature is invalid") + } - if err := pub.Verify([]byte(req.Message), sig); err == nil { - return &pactus.VerifyMessageResponse{ - IsValid: true, - }, nil + if err = ed25519Pub.Verify([]byte(req.Message), sig); err == nil { + return &pactus.VerifyMessageResponse{ + IsValid: true, + }, nil + } + } else { + sig, err := bls.SignatureFromString(req.Signature) + if err != nil { + return nil, status.Error(codes.InvalidArgument, "signature is invalid") + } + + if err = blsPub.Verify([]byte(req.Message), sig); err == nil { + return &pactus.VerifyMessageResponse{ + IsValid: true, + }, nil + } } return &pactus.VerifyMessageResponse{ diff --git a/www/grpc/utils_test.go b/www/grpc/utils_test.go index e004d80ab..53f909a51 100644 --- a/www/grpc/utils_test.go +++ b/www/grpc/utils_test.go @@ -46,6 +46,42 @@ func TestSignMessageWithPrivateKey(t *testing.T) { td.StopServer() } +func TestSignMessageWithED25519PrivateKey(t *testing.T) { + conf := testConfig() + td := setup(t, conf) + conn, client := td.utilClient(t) + + msg := "pactus" + prvStr := "SECRET1RYY62A96X25ZAL4DPL5Z63G83GCSFCCQ7K0CMQD3MFNLYK3A6R26QUUK3Y0" + invalidPrvStr := "INVSECRET1RYY62A96X25ZAL4DPL5Z63G83GCSFCCQ7K0CMQD3MFNLYK3A6R26QUUK3Y0" + expectedSig := "361aaa09c408bfcf7e79dd90c583eeeaefe7c732ca5643cfb2ea7a6d22105b874a412080525a855bbd5df94110a7d0083d6e386e016ecf8b7f522c339f79d305" + + t.Run("", func(t *testing.T) { + res, err := client.SignMessageWithPrivateKey(context.Background(), + &pactus.SignMessageWithPrivateKeyRequest{ + Message: msg, + PrivateKey: prvStr, + }) + + assert.Nil(t, err) + assert.Equal(t, expectedSig, res.Signature) + }) + + t.Run("", func(t *testing.T) { + res, err := client.SignMessageWithPrivateKey(context.Background(), + &pactus.SignMessageWithPrivateKeyRequest{ + Message: msg, + PrivateKey: invalidPrvStr, + }) + + assert.NotNil(t, err) + assert.Nil(t, res) + }) + + assert.Nil(t, conn.Close(), "Error closing connection") + td.StopServer() +} + func TestVerifyMessage(t *testing.T) { conf := testConfig() td := setup(t, conf) @@ -84,6 +120,43 @@ func TestVerifyMessage(t *testing.T) { td.StopServer() } +func TestVerifyED25519Message(t *testing.T) { + conf := testConfig() + td := setup(t, conf) + conn, client := td.utilClient(t) + + msg := "pactus" + pubStr := "public1rvqxnpfph8tnc3ck55z85w285t5jetylmmktr9wlzs0zvx7kx500szxfudh" + sigStr := "361aaa09c408bfcf7e79dd90c583eeeaefe7c732ca5643cfb2ea7a6d22105b874a412080525a855bbd5df94110a7d0083d6e386e016ecf8b7f522c339f79d305" + invalidSigStr := "001aaa09c408bfcf7e79dd90c583eeeaefe7c732ca5643cfb2ea7a6d22105b874a412080525a855bbd5df94110a7d0083d6e386e016ecf8b7f522c339f79d305" + + t.Run("valid message", func(t *testing.T) { + res, err := client.VerifyMessage(context.Background(), + &pactus.VerifyMessageRequest{ + Message: msg, + Signature: sigStr, + PublicKey: pubStr, + }) + assert.Nil(t, err) + assert.True(t, res.IsValid) + }) + + t.Run("invalid message", func(t *testing.T) { + res, err := client.VerifyMessage(context.Background(), + &pactus.VerifyMessageRequest{ + Message: msg, + Signature: invalidSigStr, + PublicKey: pubStr, + }) + + assert.Nil(t, err) + assert.False(t, res.IsValid) + }) + + assert.Nil(t, conn.Close(), "Error closing connection") + td.StopServer() +} + func TestBLSPublicKeyAggregation(t *testing.T) { ts := testsuite.NewTestSuite(t) conf := testConfig()