From 25cbbcb14f19f1a46abc759e4c788b22e04ced06 Mon Sep 17 00:00:00 2001 From: mishasizov-SK <109598497+mishasizov-SK@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:57:34 +0300 Subject: [PATCH] feat: change KMS interface for Data Integrity (#3621) Signed-off-by: Mykhailo Sizov --- component/kmscrypto/kms/localkms/localkms.go | 2 +- .../kms/localkms/pubkey_export_import_test.go | 18 +++++++-------- .../kmscrypto/kms/localkms/pubkey_reader.go | 6 ++++- .../models/dataintegrity/integration_test.go | 23 +++++++++---------- .../models/dataintegrity/models/models.go | 9 ++++++++ .../suite/ecdsa2019/ecdsa2019.go | 15 ++++++------ .../suite/ecdsa2019/ecdsa2019_test.go | 11 --------- component/models/go.mod | 2 ++ 8 files changed, 45 insertions(+), 41 deletions(-) diff --git a/component/kmscrypto/kms/localkms/localkms.go b/component/kmscrypto/kms/localkms/localkms.go index 15ab042d7..cd12f51c8 100644 --- a/component/kmscrypto/kms/localkms/localkms.go +++ b/component/kmscrypto/kms/localkms/localkms.go @@ -311,7 +311,7 @@ func (l *LocalKMS) CreateAndExportPubKeyBytes(kt kmsapi.KeyType, opts ...kmsapi. // Note: The key handle created is not stored in the KMS, it's only useful to execute the crypto primitive // associated with it. func (l *LocalKMS) PubKeyBytesToHandle(pubKey []byte, kt kmsapi.KeyType, opts ...kmsapi.KeyOpts) (interface{}, error) { - return publicKeyBytesToHandle(pubKey, kt, opts...) + return PublicKeyBytesToHandle(pubKey, kt, opts...) } // ImportPrivateKey will import privKey into the KMS storage for the given keyType then returns the new key id and diff --git a/component/kmscrypto/kms/localkms/pubkey_export_import_test.go b/component/kmscrypto/kms/localkms/pubkey_export_import_test.go index 5159f8fd1..0b0168e0f 100644 --- a/component/kmscrypto/kms/localkms/pubkey_export_import_test.go +++ b/component/kmscrypto/kms/localkms/pubkey_export_import_test.go @@ -94,7 +94,7 @@ func TestPubKeyExportAndRead(t *testing.T) { t.Run(tt.tcName, func(t *testing.T) { exportedKeyBytes, origKH := exportRawPublicKeyBytes(t, tt.keyTemplate, false) - kh, err := publicKeyBytesToHandle(exportedKeyBytes, tt.keyType) + kh, err := PublicKeyBytesToHandle(exportedKeyBytes, tt.keyType) require.NoError(t, err) require.NotEmpty(t, kh) @@ -179,49 +179,49 @@ func exportRawPublicKeyBytes(t *testing.T, keyTemplate *tinkpb.KeyTemplate, expe func TestNegativeCases(t *testing.T) { t.Run("test publicKeyBytesToHandle with empty pubKey", func(t *testing.T) { - kh, err := publicKeyBytesToHandle([]byte{}, kms.ECDSAP256TypeIEEEP1363) + kh, err := PublicKeyBytesToHandle([]byte{}, kms.ECDSAP256TypeIEEEP1363) require.EqualError(t, err, "pubKey is empty") require.Empty(t, kh) }) t.Run("test publicKeyBytesToHandle with empty KeyType", func(t *testing.T) { - kh, err := publicKeyBytesToHandle([]byte{1}, "") + kh, err := PublicKeyBytesToHandle([]byte{1}, "") require.EqualError(t, err, "error getting marshalled proto key: invalid key type") require.Empty(t, kh) }) t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP256TypeDER", func(t *testing.T) { - kh, err := publicKeyBytesToHandle([]byte{1}, kms.ECDSAP256TypeDER) + kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP256TypeDER) require.EqualError(t, err, "error getting marshalled proto key: asn1: syntax error: truncated tag or length") require.Empty(t, kh) }) t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP256TypeIEEEP1363", func(t *testing.T) { - kh, err := publicKeyBytesToHandle([]byte{1}, kms.ECDSAP256TypeIEEEP1363) + kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP256TypeIEEEP1363) require.EqualError(t, err, "error getting marshalled proto key: failed to unamrshal public ecdsa key") require.Empty(t, kh) }) t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP384TypeDER", func(t *testing.T) { - kh, err := publicKeyBytesToHandle([]byte{1}, kms.ECDSAP384TypeDER) + kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP384TypeDER) require.EqualError(t, err, "error getting marshalled proto key: asn1: syntax error: truncated tag or length") require.Empty(t, kh) }) t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP384TypeIEEEP1363", func(t *testing.T) { - kh, err := publicKeyBytesToHandle([]byte{1}, kms.ECDSAP384TypeIEEEP1363) + kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP384TypeIEEEP1363) require.EqualError(t, err, "error getting marshalled proto key: failed to unamrshal public ecdsa key") require.Empty(t, kh) }) t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP521TypeDER", func(t *testing.T) { - kh, err := publicKeyBytesToHandle([]byte{1}, kms.ECDSAP521TypeDER) + kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP521TypeDER) require.EqualError(t, err, "error getting marshalled proto key: asn1: syntax error: truncated tag or length") require.Empty(t, kh) }) t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP521TypeIEEEP1363", func(t *testing.T) { - kh, err := publicKeyBytesToHandle([]byte{1}, kms.ECDSAP521TypeIEEEP1363) + kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP521TypeIEEEP1363) require.EqualError(t, err, "error getting marshalled proto key: failed to unamrshal public ecdsa key") require.Empty(t, kh) }) diff --git a/component/kmscrypto/kms/localkms/pubkey_reader.go b/component/kmscrypto/kms/localkms/pubkey_reader.go index 8f59fa644..4c6085a6a 100644 --- a/component/kmscrypto/kms/localkms/pubkey_reader.go +++ b/component/kmscrypto/kms/localkms/pubkey_reader.go @@ -29,7 +29,11 @@ import ( secp256k1subtle "github.com/hyperledger/aries-framework-go/component/kmscrypto/crypto/tinkcrypto/primitive/secp256k1/subtle" ) -func publicKeyBytesToHandle(pubKey []byte, kt kms.KeyType, opts ...kms.KeyOpts) (*keyset.Handle, error) { +// PublicKeyBytesToHandle will create and return a key handle for pubKey of type kt +// it returns an error if it failed creating the key handle +// Note: The key handle created is not stored in the KMS, it's only useful to execute the crypto primitive +// associated with it. +func PublicKeyBytesToHandle(pubKey []byte, kt kms.KeyType, opts ...kms.KeyOpts) (*keyset.Handle, error) { if len(pubKey) == 0 { return nil, fmt.Errorf("pubKey is empty") } diff --git a/component/models/dataintegrity/integration_test.go b/component/models/dataintegrity/integration_test.go index 2cdad552f..d273b9413 100644 --- a/component/models/dataintegrity/integration_test.go +++ b/component/models/dataintegrity/integration_test.go @@ -43,10 +43,18 @@ const ( func TestIntegration(t *testing.T) { suiteOpts := suiteOptions(t) + storeProv := mockstorage.NewMockStoreProvider() + + kmsProv, err := mockkms.NewProviderForKMS(storeProv, &noop.NoLock{}) + require.NoError(t, err) + + kms, err := localkms.New("local-lock://custom/master/key/", kmsProv) + require.NoError(t, err) + signerInit := ecdsa2019.NewSignerInitializer(&ecdsa2019.SignerInitializerOptions{ LDDocumentLoader: suiteOpts.LDDocumentLoader, Signer: suiteOpts.Signer, - KMS: suiteOpts.KMS, + KMS: kms, }) verifierInit := ecdsa2019.NewVerifierInitializer(&ecdsa2019.VerifierInitializerOptions{ @@ -55,13 +63,13 @@ func TestIntegration(t *testing.T) { KMS: suiteOpts.KMS, }) - _, p256Bytes, err := suiteOpts.KMS.CreateAndExportPubKeyBytes(kmsapi.ECDSAP256IEEEP1363) + _, p256Bytes, err := kms.CreateAndExportPubKeyBytes(kmsapi.ECDSAP256IEEEP1363) require.NoError(t, err) p256JWK, err := jwkkid.BuildJWK(p256Bytes, kmsapi.ECDSAP256IEEEP1363) require.NoError(t, err) - _, p384Bytes, err := suiteOpts.KMS.CreateAndExportPubKeyBytes(kmsapi.ECDSAP384IEEEP1363) + _, p384Bytes, err := kms.CreateAndExportPubKeyBytes(kmsapi.ECDSAP384IEEEP1363) require.NoError(t, err) p384JWK, err := jwkkid.BuildJWK(p384Bytes, kmsapi.ECDSAP384IEEEP1363) @@ -188,14 +196,6 @@ func suiteOptions(t *testing.T) *ecdsa2019.Options { docLoader, err := documentloader.NewDocumentLoader(createMockProvider()) require.NoError(t, err) - storeProv := mockstorage.NewMockStoreProvider() - - kmsProv, err := mockkms.NewProviderForKMS(storeProv, &noop.NoLock{}) - require.NoError(t, err) - - kms, err := localkms.New("local-lock://custom/master/key/", kmsProv) - require.NoError(t, err) - cr, err := tinkcrypto.New() require.NoError(t, err) @@ -203,7 +203,6 @@ func suiteOptions(t *testing.T) *ecdsa2019.Options { LDDocumentLoader: docLoader, Signer: cr, Verifier: cr, - KMS: kms, } } diff --git a/component/models/dataintegrity/models/models.go b/component/models/dataintegrity/models/models.go index 2e2b5b318..55550ad84 100644 --- a/component/models/dataintegrity/models/models.go +++ b/component/models/dataintegrity/models/models.go @@ -18,6 +18,15 @@ const ( DataIntegrityProof = "DataIntegrityProof" ) +// KeyManager manages keys and their storage for the aries framework. +type KeyManager interface { + // Get key handle for the given keyID + // Returns: + // - handle instance (to private key) + // - error if failure + Get(keyID string) (interface{}, error) +} + // VerificationMethod implements the data integrity verification method model: // https://www.w3.org/TR/vc-data-integrity/#verification-methods type VerificationMethod = did.VerificationMethod diff --git a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go index fb7101a8f..614a13b23 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go +++ b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go @@ -22,6 +22,7 @@ import ( kmsapi "github.com/hyperledger/aries-framework-go/spi/kms" "github.com/hyperledger/aries-framework-go/component/kmscrypto/doc/jose/jwk" + "github.com/hyperledger/aries-framework-go/component/kmscrypto/kms/localkms" "github.com/hyperledger/aries-framework-go/component/models/dataintegrity/models" "github.com/hyperledger/aries-framework-go/component/models/dataintegrity/suite" "github.com/hyperledger/aries-framework-go/component/models/ld/processor" @@ -57,7 +58,7 @@ type Suite struct { ldLoader ld.DocumentLoader signer Signer verifier Verifier - kms kmsapi.KeyManager + kms models.KeyManager } // Options provides initialization options for Suite. @@ -65,7 +66,7 @@ type Options struct { LDDocumentLoader ld.DocumentLoader Signer Signer Verifier Verifier - KMS kmsapi.KeyManager + KMS models.KeyManager } // SuiteInitializer is the initializer for Suite. @@ -122,7 +123,7 @@ func NewSignerInitializer(options *SignerInitializerOptions) suite.SignerInitial type VerifierInitializerOptions struct { LDDocumentLoader ld.DocumentLoader Verifier Verifier - KMS kmsapi.KeyManager + KMS models.KeyManager } // NewVerifierInitializer returns a suite.VerifierInitializer that initializes an @@ -231,7 +232,7 @@ func (s *Suite) VerifyProof(doc []byte, proof *models.Proof, opts *models.ProofO return fmt.Errorf("decoding proofValue: %w", err) } - err = verify(sigBase, sig, vmKey, s.verifier, s.kms) + err = verify(sigBase, sig, vmKey, s.verifier) if err != nil { return fmt.Errorf("failed to verify ecdsa-2019 DI proof: %w", err) } @@ -294,7 +295,7 @@ func kmsKID(key *jwk.JWK) (string, error) { return base64.RawURLEncoding.EncodeToString(tp), nil } -func sign(sigBase []byte, key *jwk.JWK, signer Signer, kms kmsapi.KeyManager) ([]byte, error) { +func sign(sigBase []byte, key *jwk.JWK, signer Signer, kms models.KeyManager) ([]byte, error) { kid, err := kmsKID(key) if err != nil { return nil, err @@ -313,7 +314,7 @@ func sign(sigBase []byte, key *jwk.JWK, signer Signer, kms kmsapi.KeyManager) ([ return sig, nil } -func verify(sigBase, sig []byte, key *jwk.JWK, verifier Verifier, kms kmsapi.KeyManager) error { +func verify(sigBase, sig []byte, key *jwk.JWK, verifier Verifier) error { pkBytes, err := key.PublicKeyBytes() if err != nil { return fmt.Errorf("getting verification key bytes: %w", err) @@ -324,7 +325,7 @@ func verify(sigBase, sig []byte, key *jwk.JWK, verifier Verifier, kms kmsapi.Key return fmt.Errorf("getting key type of verification key: %w", err) } - kh, err := kms.PubKeyBytesToHandle(pkBytes, kt) + kh, err := localkms.PublicKeyBytesToHandle(pkBytes, kt) if err != nil { return err } diff --git a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go index 42edcdcd8..1b827d405 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go +++ b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go @@ -285,17 +285,6 @@ func TestSuite_VerifyProof(t *testing.T) { testVerify(t, tc) }) - t.Run("get kms key handle", func(t *testing.T) { - tc := successCase(t) - - errExpected := errors.New("expected error") - - tc.kms.PubKeyBytesToHandleErr = errExpected - tc.errIs = errExpected - - testVerify(t, tc) - }) - t.Run("crypto verify", func(t *testing.T) { tc := successCase(t) diff --git a/component/models/go.mod b/component/models/go.mod index abbe9c57e..f6e51eb76 100644 --- a/component/models/go.mod +++ b/component/models/go.mod @@ -61,3 +61,5 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) + +replace github.com/hyperledger/aries-framework-go/component/kmscrypto => ../kmscrypto \ No newline at end of file