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

Commit

Permalink
feat: DI - change verifier interface (#3626)
Browse files Browse the repository at this point in the history
Signed-off-by: Mykhailo Sizov <mykhailo.sizov@securekey.com>
  • Loading branch information
mishasizov-SK committed Aug 28, 2023
1 parent 917ccf5 commit 5f00b6b
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 87 deletions.
3 changes: 0 additions & 3 deletions component/models/dataintegrity/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -235,7 +233,6 @@ func suiteOptions(t *testing.T) *ecdsa2019.Options {
return &ecdsa2019.Options{
LDDocumentLoader: docLoader,
Signer: cr,
Verifier: cr,
}
}

Expand Down
102 changes: 48 additions & 54 deletions component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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
}

Expand All @@ -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
}
}
Expand Down Expand Up @@ -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,
}))
}

Expand All @@ -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
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
}
53 changes: 27 additions & 26 deletions component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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()
Expand All @@ -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 {
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -250,13 +259,18 @@ 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)
})

t.Run("P-384 key", func(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)
})
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ func TestIntegration(t *testing.T) {

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

verifier, err := verifierInit.Verifier()
Expand Down
2 changes: 0 additions & 2 deletions component/models/verifiable/data_integrity_proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ func Test_DataIntegrity_SignVerify(t *testing.T) {
}

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

Expand Down

0 comments on commit 5f00b6b

Please sign in to comment.