From bdde0c2e5ceb37c2e1c367851ecb54f2715817d3 Mon Sep 17 00:00:00 2001 From: Alex Guo Date: Mon, 7 Jun 2021 20:11:41 +0000 Subject: [PATCH 1/5] convert MIRACL public key to herumi/bls public key --- .../0chain.net/blobbercore/handler/handler.go | 3 ++- .../handler/handler_integration_tests.go | 3 ++- .../0chain.net/blobbercore/handler/helper.go | 3 ++- code/go/0chain.net/core/encryption/keys.go | 24 +++++++++++++++++++ .../0chain.net/core/encryption/keys_test.go | 19 +++++++++++++++ code/go/0chain.net/go.mod | 1 + .../validatorcore/storage/context.go | 4 +++- 7 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 code/go/0chain.net/core/encryption/keys_test.go diff --git a/code/go/0chain.net/blobbercore/handler/handler.go b/code/go/0chain.net/blobbercore/handler/handler.go index 49da5ac50..2a5f51563 100644 --- a/code/go/0chain.net/blobbercore/handler/handler.go +++ b/code/go/0chain.net/blobbercore/handler/handler.go @@ -14,6 +14,7 @@ import ( "0chain.net/blobbercore/datastore" "0chain.net/blobbercore/stats" "0chain.net/core/common" + "0chain.net/core/encryption" . "0chain.net/core/logging" "go.uber.org/zap" @@ -105,7 +106,7 @@ func setupHandlerContext(ctx context.Context, r *http.Request) context.Context { ctx = context.WithValue(ctx, constants.CLIENT_CONTEXT_KEY, r.Header.Get(common.ClientHeader)) ctx = context.WithValue(ctx, constants.CLIENT_KEY_CONTEXT_KEY, - r.Header.Get(common.ClientKeyHeader)) + encryption.MiraclToHerumiPK(r.Header.Get(common.ClientKeyHeader))) ctx = context.WithValue(ctx, constants.ALLOCATION_CONTEXT_KEY, vars["allocation"]) // signature is not requered for all requests, but if header is empty it won`t affect anything diff --git a/code/go/0chain.net/blobbercore/handler/handler_integration_tests.go b/code/go/0chain.net/blobbercore/handler/handler_integration_tests.go index d386f15b1..f94b30354 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_integration_tests.go +++ b/code/go/0chain.net/blobbercore/handler/handler_integration_tests.go @@ -18,6 +18,7 @@ import ( "0chain.net/blobbercore/datastore" "0chain.net/blobbercore/stats" "0chain.net/core/common" + "0chain.net/core/encryption" "0chain.net/core/node" "github.com/gorilla/mux" @@ -99,7 +100,7 @@ func setupHandlerContext(ctx context.Context, r *http.Request) context.Context { ctx = context.WithValue(ctx, constants.CLIENT_CONTEXT_KEY, r.Header.Get(common.ClientHeader)) ctx = context.WithValue(ctx, constants.CLIENT_KEY_CONTEXT_KEY, - r.Header.Get(common.ClientKeyHeader)) + encryption.MiraclToHerumiPK(r.Header.Get(common.ClientKeyHeader))) ctx = context.WithValue(ctx, constants.ALLOCATION_CONTEXT_KEY, vars["allocation"]) return ctx diff --git a/code/go/0chain.net/blobbercore/handler/helper.go b/code/go/0chain.net/blobbercore/handler/helper.go index b412aa718..c6afa5b96 100644 --- a/code/go/0chain.net/blobbercore/handler/helper.go +++ b/code/go/0chain.net/blobbercore/handler/helper.go @@ -13,13 +13,14 @@ import ( "0chain.net/blobbercore/blobbergrpc" "0chain.net/blobbercore/constants" + "0chain.net/core/encryption" ) func setupGRPCHandlerContext(ctx context.Context, r *blobbergrpc.RequestContext) context.Context { ctx = context.WithValue(ctx, constants.CLIENT_CONTEXT_KEY, r.Client) ctx = context.WithValue(ctx, constants.CLIENT_KEY_CONTEXT_KEY, - r.ClientKey) + encryption.MiraclToHerumiPK(r.ClientKey)) ctx = context.WithValue(ctx, constants.ALLOCATION_CONTEXT_KEY, r.Allocation) return ctx diff --git a/code/go/0chain.net/core/encryption/keys.go b/code/go/0chain.net/core/encryption/keys.go index bda80893a..c6436a99e 100644 --- a/code/go/0chain.net/core/encryption/keys.go +++ b/code/go/0chain.net/core/encryption/keys.go @@ -8,6 +8,7 @@ import ( "0chain.net/core/config" "github.com/0chain/gosdk/core/zcncrypto" + "github.com/herumi/bls-go-binary/bls" ) /*ReadKeys - reads a publicKey and a privateKey from a Reader. @@ -38,3 +39,26 @@ func Verify(publicKey string, signature string, hash string) (bool, error) { } return false, common.NewError("invalid_signature_scheme", "Invalid signature scheme. Please check configuration") } + +// If input is normal herumi/bls public key, it returns it immmediately. +// So this is completely backward compatible with herumi/bls. +// If input is MIRACL public key, convert it to herumi/bls public key. +// +// This is an example of the raw public key we expect from MIRACL +var miraclExamplePK = `0418a02c6bd223ae0dfda1d2f9a3c81726ab436ce5e9d17c531ff0a385a13a0b491bdfed3a85690775ee35c61678957aaba7b1a1899438829f1dc94248d87ed36817f6dfafec19bfa87bf791a4d694f43fec227ae6f5a867490e30328cac05eaff039ac7dfc3364e851ebd2631ea6f1685609fc66d50223cc696cb59ff2fee47ac` +// +// This is an example of the same MIRACL public key serialized with ToString(). +// pk ([1bdfed3a85690775ee35c61678957aaba7b1a1899438829f1dc94248d87ed368,18a02c6bd223ae0dfda1d2f9a3c81726ab436ce5e9d17c531ff0a385a13a0b49],[039ac7dfc3364e851ebd2631ea6f1685609fc66d50223cc696cb59ff2fee47ac,17f6dfafec19bfa87bf791a4d694f43fec227ae6f5a867490e30328cac05eaff]) +func MiraclToHerumiPK(pk string) string { + if len(pk) != len(miraclExamplePK) { + // If input is normal herumi/bls public key, it returns it immmediately. + return pk + } + n1 := pk[2:66] + n2 := pk[66:(66+64)] + n3 := pk[(66+64):(66+64+64)] + n4 := pk[(66+64+64):(66+64+64+64)] + var p bls.PublicKey + p.SetHexString("1 " + n2 + " " + n1 + " " + n4 + " " + n3) + return p.SerializeToHexStr() +} diff --git a/code/go/0chain.net/core/encryption/keys_test.go b/code/go/0chain.net/core/encryption/keys_test.go new file mode 100644 index 000000000..050c8e8ca --- /dev/null +++ b/code/go/0chain.net/core/encryption/keys_test.go @@ -0,0 +1,19 @@ +package encryption + +import ( + "testing" + "github.com/herumi/bls-go-binary/bls" + "github.com/stretchr/testify/require" +) + +func TestMiraclToHerumiPK(t *testing.T) { + miraclpk1 := `0418a02c6bd223ae0dfda1d2f9a3c81726ab436ce5e9d17c531ff0a385a13a0b491bdfed3a85690775ee35c61678957aaba7b1a1899438829f1dc94248d87ed36817f6dfafec19bfa87bf791a4d694f43fec227ae6f5a867490e30328cac05eaff039ac7dfc3364e851ebd2631ea6f1685609fc66d50223cc696cb59ff2fee47ac` + pk1 := MiraclToHerumiPK(miraclpk1) + + require.EqualValues(t, pk1, "68d37ed84842c91d9f82389489a1b1a7ab7a957816c635ee750769853aeddf1b490b3aa185a3f01f537cd1e9e56c43ab2617c8a3f9d2a1fd0dae23d26b2ca018") + + // Assert DeserializeHexStr works on the output of MiraclToHerumiPK + var pk bls.PublicKey + err := pk.DeserializeHexStr(pk1) + require.NoError(t, err) +} diff --git a/code/go/0chain.net/go.mod b/code/go/0chain.net/go.mod index ef3b0dd34..8bdf88b70 100644 --- a/code/go/0chain.net/go.mod +++ b/code/go/0chain.net/go.mod @@ -9,6 +9,7 @@ require ( github.com/gorilla/mux v1.7.3 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.3.0 + github.com/herumi/bls-go-binary v0.0.0-20191119080710-898950e1a520 // indirect github.com/jackc/pgproto3/v2 v2.0.4 // indirect github.com/koding/cache v0.0.0-20161222233015-e8a81b0b3f20 github.com/minio/minio-go v6.0.14+incompatible diff --git a/code/go/0chain.net/validatorcore/storage/context.go b/code/go/0chain.net/validatorcore/storage/context.go index 79a977074..d033b5e03 100644 --- a/code/go/0chain.net/validatorcore/storage/context.go +++ b/code/go/0chain.net/validatorcore/storage/context.go @@ -5,12 +5,14 @@ import ( "net/http" "0chain.net/core/common" + "0chain.net/core/encryption" ) func SetupContext(handler common.JSONResponderF) common.JSONResponderF { return func(ctx context.Context, r *http.Request) (interface{}, error) { ctx = context.WithValue(ctx, CLIENT_CONTEXT_KEY, r.Header.Get(common.ClientHeader)) - ctx = context.WithValue(ctx, CLIENT_KEY_CONTEXT_KEY, r.Header.Get(common.ClientKeyHeader)) + ctx = context.WithValue(ctx, CLIENT_KEY_CONTEXT_KEY, + encryption.MiraclToHerumiPK(r.Header.Get(common.ClientKeyHeader))) res, err := handler(ctx, r) return res, err } From d95b7e0b21b8cd732e978516f88efdf820aad02d Mon Sep 17 00:00:00 2001 From: Alex Guo Date: Mon, 7 Jun 2021 21:16:33 +0000 Subject: [PATCH 2/5] for added safety, add MiraclToHerumiPK conversion to read the value is read from context --- .../0chain.net/blobbercore/handler/object_operation_handler.go | 3 ++- code/go/0chain.net/blobbercore/readmarker/protocol.go | 2 +- code/go/0chain.net/blobbercore/writemarker/protocol.go | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go index 59e6ddd26..608130845 100644 --- a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go +++ b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go @@ -416,7 +416,8 @@ func (fsh *StorageHandler) CommitWrite(ctx context.Context, r *http.Request) (*C } allocationTx := ctx.Value(constants.ALLOCATION_CONTEXT_KEY).(string) clientID := ctx.Value(constants.CLIENT_CONTEXT_KEY).(string) - clientKey := ctx.Value(constants.CLIENT_KEY_CONTEXT_KEY).(string) + clientKey := encryption.MiraclToHerumiPK( + (ctx.Value(constants.CLIENT_KEY_CONTEXT_KEY).(string)) clientKeyBytes, _ := hex.DecodeString(clientKey) allocationObj, err := fsh.verifyAllocation(ctx, allocationTx, false) diff --git a/code/go/0chain.net/blobbercore/readmarker/protocol.go b/code/go/0chain.net/blobbercore/readmarker/protocol.go index 1089a7dc9..9a5fa4653 100644 --- a/code/go/0chain.net/blobbercore/readmarker/protocol.go +++ b/code/go/0chain.net/blobbercore/readmarker/protocol.go @@ -35,7 +35,7 @@ func (rm *ReadMarkerEntity) VerifyMarker(ctx context.Context, sa *allocation.All return common.NewError("read_marker_validation_failed", "Read Marker is not for the blobber") } - clientPublicKey := ctx.Value(constants.CLIENT_KEY_CONTEXT_KEY).(string) + clientPublicKey := encryption.MiraclToHerumiPK(ctx.Value(constants.CLIENT_KEY_CONTEXT_KEY).(string)) if len(clientPublicKey) == 0 || clientPublicKey != rm.LatestRM.ClientPublicKey { return common.NewError("read_marker_validation_failed", "Could not get the public key of the client") } diff --git a/code/go/0chain.net/blobbercore/writemarker/protocol.go b/code/go/0chain.net/blobbercore/writemarker/protocol.go index c152adde2..c88d2de89 100644 --- a/code/go/0chain.net/blobbercore/writemarker/protocol.go +++ b/code/go/0chain.net/blobbercore/writemarker/protocol.go @@ -48,7 +48,7 @@ func (wm *WriteMarkerEntity) VerifyMarker(ctx context.Context, sa *allocation.Al return common.NewError("write_marker_validation_failed", "Write Marker size does not match the connection size") } - clientPublicKey := ctx.Value(constants.CLIENT_KEY_CONTEXT_KEY).(string) + clientPublicKey := encryption.MiraclToHerumiPK(ctx.Value(constants.CLIENT_KEY_CONTEXT_KEY).(string)) if len(clientPublicKey) == 0 { return common.NewError("write_marker_validation_failed", "Could not get the public key of the client") } From 5951f56decf10b47148a804afca7e4d60e7e59d9 Mon Sep 17 00:00:00 2001 From: Alex Guo Date: Mon, 7 Jun 2021 21:27:30 +0000 Subject: [PATCH 3/5] fix syntax error in build --- .../0chain.net/blobbercore/handler/object_operation_handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go index 608130845..1c092cdd7 100644 --- a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go +++ b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go @@ -417,7 +417,7 @@ func (fsh *StorageHandler) CommitWrite(ctx context.Context, r *http.Request) (*C allocationTx := ctx.Value(constants.ALLOCATION_CONTEXT_KEY).(string) clientID := ctx.Value(constants.CLIENT_CONTEXT_KEY).(string) clientKey := encryption.MiraclToHerumiPK( - (ctx.Value(constants.CLIENT_KEY_CONTEXT_KEY).(string)) + ctx.Value(constants.CLIENT_KEY_CONTEXT_KEY).(string)) clientKeyBytes, _ := hex.DecodeString(clientKey) allocationObj, err := fsh.verifyAllocation(ctx, allocationTx, false) From d08c18ed44af9a4b98ad6f4ae2243534022bee11 Mon Sep 17 00:00:00 2001 From: Alex Guo Date: Mon, 7 Jun 2021 21:36:41 +0000 Subject: [PATCH 4/5] fix lint error by checking the error return value --- code/go/0chain.net/core/encryption/keys.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/go/0chain.net/core/encryption/keys.go b/code/go/0chain.net/core/encryption/keys.go index c6436a99e..c3cb09d17 100644 --- a/code/go/0chain.net/core/encryption/keys.go +++ b/code/go/0chain.net/core/encryption/keys.go @@ -59,6 +59,9 @@ func MiraclToHerumiPK(pk string) string { n3 := pk[(66+64):(66+64+64)] n4 := pk[(66+64+64):(66+64+64+64)] var p bls.PublicKey - p.SetHexString("1 " + n2 + " " + n1 + " " + n4 + " " + n3) + err := p.SetHexString("1 " + n2 + " " + n1 + " " + n4 + " " + n3) + if err != nil { + return err.Error() + } return p.SerializeToHexStr() } From 4391ba7b0d8cb01ded207218132956c6e7a819de Mon Sep 17 00:00:00 2001 From: Alex Guo Date: Mon, 7 Jun 2021 21:46:26 +0000 Subject: [PATCH 5/5] ok, actually log out error instead of returning error string --- code/go/0chain.net/core/encryption/keys.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/go/0chain.net/core/encryption/keys.go b/code/go/0chain.net/core/encryption/keys.go index c3cb09d17..809259866 100644 --- a/code/go/0chain.net/core/encryption/keys.go +++ b/code/go/0chain.net/core/encryption/keys.go @@ -6,6 +6,7 @@ import ( "0chain.net/core/common" "0chain.net/core/config" + . "0chain.net/core/logging" "github.com/0chain/gosdk/core/zcncrypto" "github.com/herumi/bls-go-binary/bls" @@ -61,7 +62,7 @@ func MiraclToHerumiPK(pk string) string { var p bls.PublicKey err := p.SetHexString("1 " + n2 + " " + n1 + " " + n4 + " " + n3) if err != nil { - return err.Error() + Logger.Error("MiraclToHerumiPK: " + err.Error()) } return p.SerializeToHexStr() }