Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
feat: Improvements to ECDSA2019 DI API
Browse files Browse the repository at this point in the history
The existing API required an interface that defines many more methods than what are actually required, which forces consumers of the API to implement many methods that won't ever be called. The API has now been changed to make use of two minimal interfaces instead, making it easier to use and understand. Note that implementations of the larger crypto interface can still be used since the minimal interface method signatures match.

Signed-off-by: Derek Trider <[email protected]>
  • Loading branch information
Derek Trider committed Aug 14, 2023
1 parent 71e132b commit d99960f
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 40 deletions.
21 changes: 15 additions & 6 deletions component/models/dataintegrity/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,27 @@ const (
)

func TestIntegration(t *testing.T) {
signerOpts := suiteOptions(t)
suiteOpts := suiteOptions(t)

signerInit := ecdsa2019.NewSigner(signerOpts)
signerInit := ecdsa2019.NewSignerInitializer(&ecdsa2019.SignerInitializerOptions{
LDDocumentLoader: suiteOpts.LDDocumentLoader,
Signer: suiteOpts.Signer,
KMS: nil,
})

verifierInit := ecdsa2019.NewVerifier(suiteOptions(t))
verifierInit := ecdsa2019.NewVerifierInitializer(&ecdsa2019.VerifierInitializerOptions{
LDDocumentLoader: suiteOpts.LDDocumentLoader,
Verifier: suiteOpts.Verifier,
KMS: nil,
})

_, p256Bytes, err := signerOpts.KMS.CreateAndExportPubKeyBytes(kmsapi.ECDSAP256IEEEP1363)
_, p256Bytes, err := suiteOpts.KMS.CreateAndExportPubKeyBytes(kmsapi.ECDSAP256IEEEP1363)
require.NoError(t, err)

p256JWK, err := jwkkid.BuildJWK(p256Bytes, kmsapi.ECDSAP256IEEEP1363)
require.NoError(t, err)

_, p384Bytes, err := signerOpts.KMS.CreateAndExportPubKeyBytes(kmsapi.ECDSAP384IEEEP1363)
_, p384Bytes, err := suiteOpts.KMS.CreateAndExportPubKeyBytes(kmsapi.ECDSAP384IEEEP1363)
require.NoError(t, err)

p384JWK, err := jwkkid.BuildJWK(p384Bytes, kmsapi.ECDSAP384IEEEP1363)
Expand Down Expand Up @@ -193,7 +201,8 @@ func suiteOptions(t *testing.T) *ecdsa2019.Options {

return &ecdsa2019.Options{
LDDocumentLoader: docLoader,
Crypto: cr,
Signer: cr,
Verifier: cr,
KMS: kms,
}
}
Expand Down
78 changes: 60 additions & 18 deletions component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"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"
cryptoapi "github.com/hyperledger/aries-framework-go/spi/crypto"
)

const (
Expand All @@ -35,17 +34,37 @@ const (
SuiteType = "ecdsa-2019"
)

// A Signer is able to sign messages.
type Signer interface {
// Sign will sign msg using a matching signature primitive in kh key handle of a private key
// returns:
// signature in []byte
// error in case of errors
Sign(msg []byte, kh interface{}) ([]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
// a public key
// returns:
// error in case of errors or nil if signature verification was successful
Verify(signature, msg []byte, kh interface{}) error
}

// Suite implements the ecdsa-2019 data integrity cryptographic suite.
type Suite struct {
ldLoader ld.DocumentLoader
crypto cryptoapi.Crypto
signer Signer
verifier Verifier
kms kmsapi.KeyManager
}

// Options provides initialization options for Suite.
type Options struct {
LDDocumentLoader ld.DocumentLoader
Crypto cryptoapi.Crypto
Signer Signer
Verifier Verifier
KMS kmsapi.KeyManager
}

Expand All @@ -57,7 +76,8 @@ func New(options *Options) SuiteInitializer {
return func() (suite.Suite, error) {
return &Suite{
ldLoader: options.LDDocumentLoader,
crypto: options.Crypto,
signer: options.Signer,
verifier: options.Verifier,
kms: options.KMS,
}, nil
}
Expand All @@ -81,16 +101,38 @@ func (i initializer) Type() string {
return SuiteType
}

// NewSigner returns a suite.SignerInitializer that initializes an ecdsa-2019
// signing Suite with the given Options.
func NewSigner(options *Options) suite.SignerInitializer {
return initializer(New(options))
// SignerInitializerOptions provides options for a SignerInitializer.
type SignerInitializerOptions struct {
LDDocumentLoader ld.DocumentLoader
Signer Signer
KMS kmsapi.KeyManager
}

// NewSignerInitializer returns a suite.SignerInitializer that initializes an ecdsa-2019
// signing Suite with the given SignerInitializerOptions.
func NewSignerInitializer(options *SignerInitializerOptions) suite.SignerInitializer {
return initializer(New(&Options{
LDDocumentLoader: options.LDDocumentLoader,
Signer: options.Signer,
KMS: options.KMS,
}))
}

// VerifierInitializerOptions provides options for a VerifierInitializer.
type VerifierInitializerOptions struct {
LDDocumentLoader ld.DocumentLoader
Verifier Verifier
KMS kmsapi.KeyManager
}

// NewVerifier returns a suite.VerifierInitializer that initializes an
// ecdsa-2019 verification Suite with the given Options.
func NewVerifier(options *Options) suite.VerifierInitializer {
return initializer(New(options))
// NewVerifierInitializer returns a suite.VerifierInitializer that initializes an
// ecdsa-2019 verification Suite with the given VerifierInitializerOptions.
func NewVerifierInitializer(options *VerifierInitializerOptions) suite.VerifierInitializer {
return initializer(New(&Options{
LDDocumentLoader: options.LDDocumentLoader,
Verifier: options.Verifier,
KMS: options.KMS,
}))
}

const (
Expand All @@ -105,7 +147,7 @@ func (s *Suite) CreateProof(doc []byte, opts *models.ProofOptions) (*models.Proo
return nil, err
}

sig, err := sign(docHash, vmKey, s.crypto, s.kms)
sig, err := sign(docHash, vmKey, s.signer, s.kms)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -189,7 +231,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.crypto, s.kms)
err = verify(sigBase, sig, vmKey, s.verifier, s.kms)
if err != nil {
return fmt.Errorf("failed to verify ecdsa-2019 DI proof: %w", err)
}
Expand Down Expand Up @@ -252,7 +294,7 @@ func kmsKID(key *jwk.JWK) (string, error) {
return base64.RawURLEncoding.EncodeToString(tp), nil
}

func sign(sigBase []byte, key *jwk.JWK, cr cryptoapi.Crypto, kms kmsapi.KeyManager) ([]byte, error) {
func sign(sigBase []byte, key *jwk.JWK, signer Signer, kms kmsapi.KeyManager) ([]byte, error) {
kid, err := kmsKID(key)
if err != nil {
return nil, err
Expand All @@ -263,15 +305,15 @@ func sign(sigBase []byte, key *jwk.JWK, cr cryptoapi.Crypto, kms kmsapi.KeyManag
return nil, err
}

sig, err := cr.Sign(sigBase, kh)
sig, err := signer.Sign(sigBase, kh)
if err != nil {
return nil, err
}

return sig, nil
}

func verify(sigBase, sig []byte, key *jwk.JWK, cr cryptoapi.Crypto, kms kmsapi.KeyManager) error {
func verify(sigBase, sig []byte, key *jwk.JWK, verifier Verifier, kms kmsapi.KeyManager) error {
pkBytes, err := key.PublicKeyBytes()
if err != nil {
return fmt.Errorf("getting verification key bytes: %w", err)
Expand All @@ -287,7 +329,7 @@ func verify(sigBase, sig []byte, key *jwk.JWK, cr cryptoapi.Crypto, kms kmsapi.K
return err
}

err = cr.Verify(sig, sigBase, kh)
err = verifier.Verify(sig, sigBase, kh)
if err != nil {
return err
}
Expand Down
16 changes: 8 additions & 8 deletions component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ func TestNew(t *testing.T) {
kms := &mockkms.KeyManager{}

t.Run("signer success", func(t *testing.T) {
sigInit := NewSigner(&Options{
sigInit := NewSignerInitializer(&SignerInitializerOptions{
LDDocumentLoader: docLoader,
Crypto: cryp,
Signer: cryp,
KMS: kms,
})

Expand All @@ -62,9 +62,9 @@ func TestNew(t *testing.T) {
})

t.Run("verifier success", func(t *testing.T) {
verInit := NewVerifier(&Options{
verInit := NewVerifierInitializer(&VerifierInitializerOptions{
LDDocumentLoader: docLoader,
Crypto: cryp,
Verifier: cryp,
KMS: kms,
})

Expand Down Expand Up @@ -135,9 +135,9 @@ func successCase(t *testing.T) *testCase {
}

func testSign(t *testing.T, tc *testCase) {
sigInit := NewSigner(&Options{
sigInit := NewSignerInitializer(&SignerInitializerOptions{
LDDocumentLoader: tc.docLoader,
Crypto: tc.crypto,
Signer: tc.crypto,
KMS: tc.kms,
})

Expand All @@ -164,9 +164,9 @@ func testSign(t *testing.T, tc *testCase) {
}

func testVerify(t *testing.T, tc *testCase) {
verInit := NewVerifier(&Options{
verInit := NewVerifierInitializer(&VerifierInitializerOptions{
LDDocumentLoader: tc.docLoader,
Crypto: tc.crypto,
Verifier: tc.crypto,
KMS: tc.kms,
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@ func TestIntegration(t *testing.T) {
cr, err := tinkcrypto.New()
require.NoError(t, err)

signerInit := NewSigner(&Options{
signerInit := NewSignerInitializer(&SignerInitializerOptions{
LDDocumentLoader: docLoader,
Crypto: cr,
Signer: cr,
KMS: kms,
})

signer, err := signerInit.Signer()
require.NoError(t, err)

verifierInit := NewVerifier(&Options{
verifierInit := NewVerifierInitializer(&VerifierInitializerOptions{
LDDocumentLoader: docLoader,
Crypto: cr,
Verifier: cr,
KMS: kms,
})

Expand Down
8 changes: 4 additions & 4 deletions component/models/verifiable/data_integrity_proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ func Test_DataIntegrity_SignVerify(t *testing.T) {
return makeMockDIDResolution(signingDID, vm, did.AssertionMethod), nil
})

signerSuite := ecdsa2019.NewSigner(&ecdsa2019.Options{
signerSuite := ecdsa2019.NewSignerInitializer(&ecdsa2019.SignerInitializerOptions{
KMS: kms,
Crypto: cr,
Signer: cr,
LDDocumentLoader: docLoader,
})

Expand All @@ -91,9 +91,9 @@ func Test_DataIntegrity_SignVerify(t *testing.T) {
Challenge: "mock-challenge",
}

verifySuite := ecdsa2019.NewVerifier(&ecdsa2019.Options{
verifySuite := ecdsa2019.NewVerifierInitializer(&ecdsa2019.VerifierInitializerOptions{
KMS: kms,
Crypto: cr,
Verifier: cr,
LDDocumentLoader: docLoader,
})

Expand Down

0 comments on commit d99960f

Please sign in to comment.