diff --git a/component/models/dataintegrity/integration_test.go b/component/models/dataintegrity/integration_test.go index 969f1d661..22c7968d4 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,16 +53,17 @@ 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, - Verifier: suiteOpts.Verifier, - KMS: suiteOpts.KMS, + LDDocumentLoader: docLoader, + Verifier: cr, }) _, p256Bytes, err := kms.CreateAndExportPubKeyBytes(kmsapi.ECDSAP256IEEEP1363) @@ -223,22 +225,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, - Verifier: 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 35187d516..dbba958a5 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 @@ -53,18 +96,16 @@ type Verifier interface { // 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 + signerGetter SignerGetter + verifier Verifier } // Options provides initialization options for Suite. type Options struct { LDDocumentLoader ld.DocumentLoader - Signer Signer + SignerGetter SignerGetter Verifier Verifier - KMS models.KeyManager } // SuiteInitializer is the initializer for Suite. @@ -74,10 +115,9 @@ 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, + signerGetter: options.SignerGetter, + verifier: options.Verifier, }, nil } } @@ -103,8 +143,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 @@ -112,8 +151,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, })) } @@ -121,7 +159,6 @@ func NewSignerInitializer(options *SignerInitializerOptions) suite.SignerInitial type VerifierInitializerOptions struct { LDDocumentLoader ld.DocumentLoader Verifier Verifier - KMS models.KeyManager } // NewVerifierInitializer returns a suite.VerifierInitializer that initializes an @@ -130,7 +167,6 @@ func NewVerifierInitializer(options *VerifierInitializerOptions) suite.VerifierI return initializer(New(&Options{ LDDocumentLoader: options.LDDocumentLoader, Verifier: options.Verifier, - KMS: options.KMS, })) } @@ -146,7 +182,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 } @@ -294,18 +330,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 1b827d405..23ac771a5 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go +++ b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go @@ -48,11 +48,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() @@ -65,7 +66,6 @@ func TestNew(t *testing.T) { verInit := NewVerifierInitializer(&VerifierInitializerOptions{ LDDocumentLoader: docLoader, Verifier: cryp, - KMS: kms, }) verifier, err := verInit.Verifier() @@ -137,8 +137,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() @@ -167,7 +166,6 @@ func testVerify(t *testing.T, tc *testCase) { verInit := NewVerifierInitializer(&VerifierInitializerOptions{ LDDocumentLoader: tc.docLoader, Verifier: tc.crypto, - KMS: tc.kms, }) verifier, err := verInit.Verifier() diff --git a/component/models/dataintegrity/suite/ecdsa2019/integration_test.go b/component/models/dataintegrity/suite/ecdsa2019/integration_test.go index 3bd35ccd3..0627250f9 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() @@ -51,7 +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..3aa83dc30 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, }) @@ -93,7 +92,6 @@ func Test_DataIntegrity_SignVerify(t *testing.T) { } verifySuite := ecdsa2019.NewVerifierInitializer(&ecdsa2019.VerifierInitializerOptions{ - KMS: kms, Verifier: cr, LDDocumentLoader: docLoader, })