From 984699876d288b92836aff3bfd046de48e66018e Mon Sep 17 00:00:00 2001 From: Filip Burlacu Date: Mon, 28 Aug 2023 11:15:43 -0400 Subject: [PATCH] fix: data-integrity ecdsa2019 signer uses common signer interface (#3627) Signed-off-by: Filip Burlacu --- .../models/dataintegrity/integration_test.go | 28 ++----- .../suite/ecdsa2019/ecdsa2019.go | 83 ++++++++++++++----- .../suite/ecdsa2019/ecdsa2019_test.go | 8 +- .../suite/ecdsa2019/integration_test.go | 3 +- .../verifiable/data_integrity_proof_test.go | 3 +- 5 files changed, 77 insertions(+), 48 deletions(-) diff --git a/component/models/dataintegrity/integration_test.go b/component/models/dataintegrity/integration_test.go index 952d7ea99..a5cf5ca96 100644 --- a/component/models/dataintegrity/integration_test.go +++ b/component/models/dataintegrity/integration_test.go @@ -42,7 +42,8 @@ const ( ) func TestIntegration(t *testing.T) { - suiteOpts := suiteOptions(t) + docLoader, err := documentloader.NewDocumentLoader(createMockProvider()) + require.NoError(t, err) storeProv := mockstorage.NewMockStoreProvider() @@ -52,14 +53,16 @@ func TestIntegration(t *testing.T) { kms, err := localkms.New("local-lock://custom/master/key/", kmsProv) require.NoError(t, err) + cr, err := tinkcrypto.New() + require.NoError(t, err) + signerInit := ecdsa2019.NewSignerInitializer(&ecdsa2019.SignerInitializerOptions{ - LDDocumentLoader: suiteOpts.LDDocumentLoader, - Signer: suiteOpts.Signer, - KMS: kms, + LDDocumentLoader: docLoader, + SignerGetter: ecdsa2019.WithLocalKMSSigner(kms, cr), }) verifierInit := ecdsa2019.NewVerifierInitializer(&ecdsa2019.VerifierInitializerOptions{ - LDDocumentLoader: suiteOpts.LDDocumentLoader, + LDDocumentLoader: docLoader, }) _, p256Bytes, err := kms.CreateAndExportPubKeyBytes(kmsapi.ECDSAP256IEEEP1363) @@ -221,21 +224,6 @@ func TestIntegration(t *testing.T) { }) } -func suiteOptions(t *testing.T) *ecdsa2019.Options { - t.Helper() - - docLoader, err := documentloader.NewDocumentLoader(createMockProvider()) - require.NoError(t, err) - - cr, err := tinkcrypto.New() - require.NoError(t, err) - - return &ecdsa2019.Options{ - LDDocumentLoader: docLoader, - Signer: cr, - } -} - type provider struct { ContextStore store.ContextStore RemoteProviderStore store.RemoteProviderStore diff --git a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go index b3a6995a7..909a488a5 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go +++ b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go @@ -33,8 +33,42 @@ const ( SuiteType = "ecdsa-2019" ) -// A Signer is able to sign messages. -type Signer interface { +// SignerGetter returns a Signer, which must sign with the private key matching +// the public key provided in models.ProofOptions.VerificationMethod. +type SignerGetter func(pub *jwk.JWK) (Signer, error) + +// WithStaticSigner sets the Suite to use a fixed Signer, with externally-chosen signing key. +// +// Use when a signing Suite is initialized for a single signature, then thrown away. +func WithStaticSigner(signer Signer) SignerGetter { + return func(*jwk.JWK) (Signer, error) { + return signer, nil + } +} + +// WithLocalKMSSigner returns a SignerGetter that will sign using the given localkms, using the private key matching +// the given public key. +func WithLocalKMSSigner(kms models.KeyManager, kmsSigner KMSSigner) SignerGetter { + return func(pub *jwk.JWK) (Signer, error) { + kid, err := kmsKID(pub) + if err != nil { + return nil, err + } + + kh, err := kms.Get(kid) + if err != nil { + return nil, err + } + + return &wrapSigner{ + kmsSigner: kmsSigner, + kh: kh, + }, nil + } +} + +// A KMSSigner is able to sign messages. +type KMSSigner interface { // Sign will sign msg using a matching signature primitive in kh key handle of a private key // returns: // signature in []byte @@ -42,6 +76,15 @@ type Signer interface { Sign(msg []byte, kh interface{}) ([]byte, error) } +// A Signer is able to sign messages. +type Signer interface { + // Sign will sign msg using a private key internal to the Signer. + // returns: + // signature in []byte + // error in case of errors + Sign(msg []byte) ([]byte, error) +} + // A Verifier is able to verify messages. type Verifier interface { // Verify will verify a signature for the given msg using a matching signature primitive in kh key handle of @@ -54,19 +97,17 @@ type Verifier interface { // Suite implements the ecdsa-2019 data integrity cryptographic suite. type Suite struct { ldLoader ld.DocumentLoader - signer Signer p256Verifier Verifier p384Verifier Verifier - kms models.KeyManager + signerGetter SignerGetter } // Options provides initialization options for Suite. type Options struct { LDDocumentLoader ld.DocumentLoader - Signer Signer P256Verifier Verifier P384Verifier Verifier - KMS models.KeyManager + SignerGetter SignerGetter } // SuiteInitializer is the initializer for Suite. @@ -77,10 +118,9 @@ func New(options *Options) SuiteInitializer { return func() (suite.Suite, error) { return &Suite{ ldLoader: options.LDDocumentLoader, - signer: options.Signer, p256Verifier: options.P256Verifier, p384Verifier: options.P384Verifier, - kms: options.KMS, + signerGetter: options.SignerGetter, }, nil } } @@ -106,8 +146,7 @@ func (i initializer) Type() string { // SignerInitializerOptions provides options for a SignerInitializer. type SignerInitializerOptions struct { LDDocumentLoader ld.DocumentLoader - Signer Signer - KMS models.KeyManager + SignerGetter SignerGetter } // NewSignerInitializer returns a suite.SignerInitializer that initializes an ecdsa-2019 @@ -115,8 +154,7 @@ type SignerInitializerOptions struct { func NewSignerInitializer(options *SignerInitializerOptions) suite.SignerInitializer { return initializer(New(&Options{ LDDocumentLoader: options.LDDocumentLoader, - Signer: options.Signer, - KMS: options.KMS, + SignerGetter: options.SignerGetter, })) } @@ -159,7 +197,7 @@ func (s *Suite) CreateProof(doc []byte, opts *models.ProofOptions) (*models.Proo return nil, err } - sig, err := sign(docHash, vmKey, s.signer, s.kms) + sig, err := sign(docHash, vmKey, s.signerGetter) if err != nil { return nil, err } @@ -312,18 +350,23 @@ func kmsKID(key *jwk.JWK) (string, error) { return base64.RawURLEncoding.EncodeToString(tp), nil } -func sign(sigBase []byte, key *jwk.JWK, signer Signer, kms models.KeyManager) ([]byte, error) { - kid, err := kmsKID(key) - if err != nil { - return nil, err - } +type wrapSigner struct { + kmsSigner KMSSigner + kh interface{} +} + +// Sign signs using wrapped kms and key handle. +func (s *wrapSigner) Sign(msg []byte) ([]byte, error) { + return s.kmsSigner.Sign(msg, s.kh) +} - kh, err := kms.Get(kid) +func sign(sigBase []byte, key *jwk.JWK, signerGetter SignerGetter) ([]byte, error) { + signer, err := signerGetter(key) if err != nil { return nil, err } - sig, err := signer.Sign(sigBase, kh) + sig, err := signer.Sign(sigBase) if err != nil { return nil, err } diff --git a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go index c66af8f6b..e180f92ad 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go +++ b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go @@ -49,11 +49,12 @@ func TestNew(t *testing.T) { cryp := &mockcrypto.Crypto{} kms := &mockkms.KeyManager{} + signerGetter := WithLocalKMSSigner(kms, cryp) + t.Run("signer success", func(t *testing.T) { sigInit := NewSignerInitializer(&SignerInitializerOptions{ LDDocumentLoader: docLoader, - Signer: cryp, - KMS: kms, + SignerGetter: signerGetter, }) signer, err := sigInit.Signer() @@ -138,8 +139,7 @@ func successCase(t *testing.T) *testCase { func testSign(t *testing.T, tc *testCase) { sigInit := NewSignerInitializer(&SignerInitializerOptions{ LDDocumentLoader: tc.docLoader, - Signer: tc.crypto, - KMS: tc.kms, + SignerGetter: WithLocalKMSSigner(tc.kms, tc.crypto), }) signer, err := sigInit.Signer() diff --git a/component/models/dataintegrity/suite/ecdsa2019/integration_test.go b/component/models/dataintegrity/suite/ecdsa2019/integration_test.go index 8be9fa9b5..392006c8d 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/integration_test.go +++ b/component/models/dataintegrity/suite/ecdsa2019/integration_test.go @@ -41,8 +41,7 @@ func TestIntegration(t *testing.T) { signerInit := NewSignerInitializer(&SignerInitializerOptions{ LDDocumentLoader: docLoader, - Signer: cr, - KMS: kms, + SignerGetter: WithLocalKMSSigner(kms, cr), }) signer, err := signerInit.Signer() diff --git a/component/models/verifiable/data_integrity_proof_test.go b/component/models/verifiable/data_integrity_proof_test.go index f4da13a4b..78c550d67 100644 --- a/component/models/verifiable/data_integrity_proof_test.go +++ b/component/models/verifiable/data_integrity_proof_test.go @@ -73,8 +73,7 @@ func Test_DataIntegrity_SignVerify(t *testing.T) { }) signerSuite := ecdsa2019.NewSignerInitializer(&ecdsa2019.SignerInitializerOptions{ - KMS: kms, - Signer: cr, + SignerGetter: ecdsa2019.WithLocalKMSSigner(kms, cr), LDDocumentLoader: docLoader, })