From 5f00b6be8572949637538a2732378ec699e4b3a5 Mon Sep 17 00:00:00 2001 From: mishasizov-SK <109598497+mishasizov-SK@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:24:56 +0300 Subject: [PATCH] feat: DI - change verifier interface (#3626) Signed-off-by: Mykhailo Sizov --- .../models/dataintegrity/integration_test.go | 3 - .../suite/ecdsa2019/ecdsa2019.go | 102 +++++++++--------- .../suite/ecdsa2019/ecdsa2019_test.go | 53 ++++----- .../suite/ecdsa2019/integration_test.go | 2 - .../verifiable/data_integrity_proof_test.go | 2 - 5 files changed, 75 insertions(+), 87 deletions(-) diff --git a/component/models/dataintegrity/integration_test.go b/component/models/dataintegrity/integration_test.go index 969f1d661..952d7ea99 100644 --- a/component/models/dataintegrity/integration_test.go +++ b/component/models/dataintegrity/integration_test.go @@ -60,8 +60,6 @@ func TestIntegration(t *testing.T) { verifierInit := ecdsa2019.NewVerifierInitializer(&ecdsa2019.VerifierInitializerOptions{ LDDocumentLoader: suiteOpts.LDDocumentLoader, - Verifier: suiteOpts.Verifier, - KMS: suiteOpts.KMS, }) _, p256Bytes, err := kms.CreateAndExportPubKeyBytes(kmsapi.ECDSAP256IEEEP1363) @@ -235,7 +233,6 @@ func suiteOptions(t *testing.T) *ecdsa2019.Options { return &ecdsa2019.Options{ LDDocumentLoader: docLoader, Signer: cr, - Verifier: cr, } } diff --git a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go index 35187d516..b3a6995a7 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go +++ b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go @@ -20,10 +20,10 @@ import ( "github.com/piprate/json-gold/ld" "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" + signatureverifier "github.com/hyperledger/aries-framework-go/component/models/signature/verifier" ) const ( @@ -48,22 +48,24 @@ type Verifier interface { // a public key // returns: // error in case of errors or nil if signature verification was successful - Verify(signature, msg []byte, kh interface{}) error + Verify(pubKey *signatureverifier.PublicKey, msg, signature []byte) error } // Suite implements the ecdsa-2019 data integrity cryptographic suite. type Suite struct { - ldLoader ld.DocumentLoader - signer Signer - verifier Verifier - kms models.KeyManager + ldLoader ld.DocumentLoader + signer Signer + p256Verifier Verifier + p384Verifier Verifier + kms models.KeyManager } // Options provides initialization options for Suite. type Options struct { LDDocumentLoader ld.DocumentLoader Signer Signer - Verifier Verifier + P256Verifier Verifier + P384Verifier Verifier KMS models.KeyManager } @@ -74,10 +76,11 @@ type SuiteInitializer func() (suite.Suite, error) func New(options *Options) SuiteInitializer { return func() (suite.Suite, error) { return &Suite{ - ldLoader: options.LDDocumentLoader, - signer: options.Signer, - verifier: options.Verifier, - kms: options.KMS, + ldLoader: options.LDDocumentLoader, + signer: options.Signer, + p256Verifier: options.P256Verifier, + p384Verifier: options.P384Verifier, + kms: options.KMS, }, nil } } @@ -119,18 +122,28 @@ func NewSignerInitializer(options *SignerInitializerOptions) suite.SignerInitial // VerifierInitializerOptions provides options for a VerifierInitializer. type VerifierInitializerOptions struct { - LDDocumentLoader ld.DocumentLoader - Verifier Verifier - KMS models.KeyManager + LDDocumentLoader ld.DocumentLoader // required + P256Verifier Verifier // optional + P384Verifier Verifier // optional } // NewVerifierInitializer returns a suite.VerifierInitializer that initializes an // ecdsa-2019 verification Suite with the given VerifierInitializerOptions. func NewVerifierInitializer(options *VerifierInitializerOptions) suite.VerifierInitializer { + p256Verifier, p384Verifier := options.P256Verifier, options.P384Verifier + + if p256Verifier == nil { + p256Verifier = signatureverifier.NewECDSAES256SignatureVerifier() + } + + if p384Verifier == nil { + p384Verifier = signatureverifier.NewECDSAES384SignatureVerifier() + } + return initializer(New(&Options{ LDDocumentLoader: options.LDDocumentLoader, - Verifier: options.Verifier, - KMS: options.KMS, + P256Verifier: p256Verifier, + P384Verifier: p384Verifier, })) } @@ -141,7 +154,7 @@ const ( // CreateProof implements the ecdsa-2019 cryptographic suite for Add Proof: // https://www.w3.org/TR/vc-di-ecdsa/#add-proof-ecdsa-2019 func (s *Suite) CreateProof(doc []byte, opts *models.ProofOptions) (*models.Proof, error) { - docHash, vmKey, err := s.transformAndHash(doc, opts) + docHash, vmKey, _, err := s.transformAndHash(doc, opts) if err != nil { return nil, err } @@ -170,68 +183,73 @@ func (s *Suite) CreateProof(doc []byte, opts *models.ProofOptions) (*models.Proo return p, nil } -func (s *Suite) transformAndHash(doc []byte, opts *models.ProofOptions) ([]byte, *jwk.JWK, error) { +func (s *Suite) transformAndHash(doc []byte, opts *models.ProofOptions) ([]byte, *jwk.JWK, Verifier, error) { docData := make(map[string]interface{}) err := json.Unmarshal(doc, &docData) if err != nil { - return nil, nil, fmt.Errorf("ecdsa-2019 suite expects JSON-LD payload: %w", err) + return nil, nil, nil, fmt.Errorf("ecdsa-2019 suite expects JSON-LD payload: %w", err) } vmKey := opts.VerificationMethod.JSONWebKey() if vmKey == nil { - return nil, nil, errors.New("verification method needs JWK") + return nil, nil, nil, errors.New("verification method needs JWK") } - var h hash.Hash + var ( + h hash.Hash + verifier Verifier + ) switch vmKey.Crv { case "P-256": h = sha256.New() + verifier = s.p256Verifier case "P-384": h = sha512.New384() + verifier = s.p384Verifier default: - return nil, nil, errors.New("unsupported ECDSA curve") + return nil, nil, nil, errors.New("unsupported ECDSA curve") } confData, err := proofConfig(docData[ldCtxKey], opts) if err != nil { - return nil, nil, err + return nil, nil, nil, err } if opts.ProofType != "DataIntegrityProof" || opts.SuiteType != SuiteType { - return nil, nil, suite.ErrProofTransformation + return nil, nil, nil, suite.ErrProofTransformation } canonDoc, err := canonicalize(docData, s.ldLoader) if err != nil { - return nil, nil, err + return nil, nil, nil, err } canonConf, err := canonicalize(confData, s.ldLoader) if err != nil { - return nil, nil, err + return nil, nil, nil, err } docHash := hashData(canonDoc, canonConf, h) - return docHash, vmKey, nil + return docHash, vmKey, verifier, nil } // VerifyProof implements the ecdsa-2019 cryptographic suite for Verify Proof: // https://www.w3.org/TR/vc-di-ecdsa/#verify-proof-ecdsa-2019 func (s *Suite) VerifyProof(doc []byte, proof *models.Proof, opts *models.ProofOptions) error { - sigBase, vmKey, err := s.transformAndHash(doc, opts) + message, vmKey, verifier, err := s.transformAndHash(doc, opts) if err != nil { return err } - _, sig, err := multibase.Decode(proof.ProofValue) + _, signature, err := multibase.Decode(proof.ProofValue) if err != nil { return fmt.Errorf("decoding proofValue: %w", err) } - err = verify(sigBase, sig, vmKey, s.verifier) + err = verifier.Verify(&signatureverifier.PublicKey{JWK: vmKey}, message, signature) if err != nil { return fmt.Errorf("failed to verify ecdsa-2019 DI proof: %w", err) } @@ -312,27 +330,3 @@ func sign(sigBase []byte, key *jwk.JWK, signer Signer, kms models.KeyManager) ([ return sig, nil } - -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) - } - - kt, err := key.KeyType() - if err != nil { - return fmt.Errorf("getting key type of verification key: %w", err) - } - - kh, err := localkms.PublicKeyBytesToHandle(pkBytes, kt) - if err != nil { - return err - } - - err = verifier.Verify(sig, sigBase, kh) - if err != nil { - return err - } - - return nil -} diff --git a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go index 1b827d405..c66af8f6b 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go +++ b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go @@ -28,6 +28,7 @@ import ( "github.com/hyperledger/aries-framework-go/component/models/ld/documentloader" mockldstore "github.com/hyperledger/aries-framework-go/component/models/ld/mock" "github.com/hyperledger/aries-framework-go/component/models/ld/store" + signatureverifier "github.com/hyperledger/aries-framework-go/component/models/signature/verifier" ) var ( @@ -64,8 +65,6 @@ func TestNew(t *testing.T) { t.Run("verifier success", func(t *testing.T) { verInit := NewVerifierInitializer(&VerifierInitializerOptions{ LDDocumentLoader: docLoader, - Verifier: cryp, - KMS: kms, }) verifier, err := verInit.Verifier() @@ -76,14 +75,16 @@ func TestNew(t *testing.T) { } type testCase struct { - crypto *mockcrypto.Crypto - kms *mockkms.KeyManager - docLoader *documentloader.DocumentLoader - proofOpts *models.ProofOptions - proof *models.Proof - document []byte - errIs error - errStr string + crypto *mockcrypto.Crypto + kms *mockkms.KeyManager + docLoader *documentloader.DocumentLoader + proofOpts *models.ProofOptions + proof *models.Proof + p256Verifier Verifier + p384Verifier Verifier + document []byte + errIs error + errStr string } func successCase(t *testing.T) *testCase { @@ -163,11 +164,19 @@ func testSign(t *testing.T, tc *testCase) { } } +type mockVerifier struct { + err error +} + +func (mv *mockVerifier) Verify(_ *signatureverifier.PublicKey, _, _ []byte) error { + return mv.err +} + func testVerify(t *testing.T, tc *testCase) { verInit := NewVerifierInitializer(&VerifierInitializerOptions{ LDDocumentLoader: tc.docLoader, - Verifier: tc.crypto, - KMS: tc.kms, + P256Verifier: tc.p256Verifier, + P384Verifier: tc.p384Verifier, }) verifier, err := verInit.Verifier() @@ -250,6 +259,9 @@ func TestSuite_VerifyProof(t *testing.T) { t.Run("P-256 key", func(t *testing.T) { tc := successCase(t) + tc.p256Verifier = &mockVerifier{} + tc.p384Verifier = &mockVerifier{err: errors.New("some error")} + testVerify(t, tc) }) @@ -257,6 +269,8 @@ func TestSuite_VerifyProof(t *testing.T) { tc := successCase(t) tc.proofOpts.VerificationMethod = getP384VM(t) + tc.p256Verifier = &mockVerifier{err: errors.New("some error")} + tc.p384Verifier = &mockVerifier{} testVerify(t, tc) }) @@ -272,25 +286,12 @@ func TestSuite_VerifyProof(t *testing.T) { testVerify(t, tc) }) - t.Run("get verification key bytes", func(t *testing.T) { - tc := successCase(t) - - badKey, vm := getVMWithJWK(t) - - badKey.Key = fooBar - - tc.proofOpts.VerificationMethod = vm - tc.errStr = "getting verification key bytes" - - testVerify(t, tc) - }) - t.Run("crypto verify", func(t *testing.T) { tc := successCase(t) errExpected := errors.New("expected error") - tc.crypto.VerifyErr = errExpected + tc.p256Verifier = &mockVerifier{err: errExpected} tc.errIs = errExpected testVerify(t, tc) diff --git a/component/models/dataintegrity/suite/ecdsa2019/integration_test.go b/component/models/dataintegrity/suite/ecdsa2019/integration_test.go index 3bd35ccd3..8be9fa9b5 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/integration_test.go +++ b/component/models/dataintegrity/suite/ecdsa2019/integration_test.go @@ -50,8 +50,6 @@ func TestIntegration(t *testing.T) { verifierInit := NewVerifierInitializer(&VerifierInitializerOptions{ LDDocumentLoader: docLoader, - Verifier: cr, - KMS: kms, }) verifier, err := verifierInit.Verifier() diff --git a/component/models/verifiable/data_integrity_proof_test.go b/component/models/verifiable/data_integrity_proof_test.go index 24b4e08e1..f4da13a4b 100644 --- a/component/models/verifiable/data_integrity_proof_test.go +++ b/component/models/verifiable/data_integrity_proof_test.go @@ -93,8 +93,6 @@ func Test_DataIntegrity_SignVerify(t *testing.T) { } verifySuite := ecdsa2019.NewVerifierInitializer(&ecdsa2019.VerifierInitializerOptions{ - KMS: kms, - Verifier: cr, LDDocumentLoader: docLoader, })