github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/verifiable/credential_bbs_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  SPDX-License-Identifier: Apache-2.0
     4  */
     5  
     6  package verifiable
     7  
     8  import (
     9  	"crypto/sha256"
    10  	"encoding/base64"
    11  	"encoding/json"
    12  	"testing"
    13  
    14  	"github.com/stretchr/testify/require"
    15  
    16  	"github.com/hyperledger/aries-framework-go/pkg/crypto/primitive/bbs12381g2pub"
    17  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld"
    18  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite"
    19  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignature2020"
    20  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignatureproof2020"
    21  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/ed25519signature2018"
    22  	jsonutil "github.com/hyperledger/aries-framework-go/pkg/doc/util/json"
    23  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    24  )
    25  
    26  //nolint:lll
    27  func TestCredential_GenerateBBSSelectiveDisclosure(t *testing.T) {
    28  	s := "uBlesrb_p6VIl-DrJ4Kj7DJ2S45uDqq6cJSgwdw_tVXWazl1XnjQxKsIzrY1RqffBqqT1oFTPi5Nwb_3IGMTWvXeGU7xwZOP8K1jybjknN0ADhp3i8JjTDeuUWH_sixv8ydcx4Qpqq-mMOX7nEm7Dg"
    29  	_, err := base64.RawURLEncoding.DecodeString(s)
    30  	require.NoError(t, err)
    31  
    32  	vcJSON := `
    33  	{
    34  	 "@context": [
    35  	   "https://www.w3.org/2018/credentials/v1",
    36  	   "https://w3id.org/citizenship/v1",
    37  	   "https://w3id.org/security/bbs/v1"
    38  	 ],
    39  	 "id": "https://issuer.oidp.uscis.gov/credentials/83627465",
    40  	 "type": [
    41  	   "VerifiableCredential",
    42  	   "PermanentResidentCard"
    43  	 ],
    44  	 "issuer": "did:example:489398593",
    45  	 "identifier": "83627465",
    46  	 "name": "Permanent Resident Card",
    47  	 "description": "Government of Example Permanent Resident Card.",
    48  	 "issuanceDate": "2019-12-03T12:19:52Z",
    49  	 "expirationDate": "2029-12-03T12:19:52Z",
    50  	 "credentialSubject": {
    51  	   "id": "did:example:b34ca6cd37bbf23",
    52  	   "type": [
    53  	     "PermanentResident",
    54  	     "Person"
    55  	   ],
    56  	   "givenName": "JOHN",
    57  	   "familyName": "SMITH",
    58  	   "gender": "Male",
    59  	   "image": "data:image/png;base64,iVBORw0KGgokJggg==",
    60  	   "residentSince": "2015-01-01",
    61  	   "lprCategory": "C09",
    62  	   "lprNumber": "999-999-999",
    63  	   "commuterClassification": "C1",
    64  	   "birthCountry": "Bahamas",
    65  	   "birthDate": "1958-07-17"
    66  	 }
    67  	}
    68  	`
    69  
    70  	pubKey, privKey, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil)
    71  	require.NoError(t, err)
    72  
    73  	pubKeyBytes, err := pubKey.Marshal()
    74  	require.NoError(t, err)
    75  
    76  	vc, err := parseTestCredential(t, []byte(vcJSON))
    77  	require.NoError(t, err)
    78  	require.Len(t, vc.Proofs, 0)
    79  
    80  	signVCWithBBS(t, privKey, pubKeyBytes, vc)
    81  	signVCWithEd25519(t, vc)
    82  
    83  	revealJSON := `
    84  {
    85    "@context": [
    86      "https://www.w3.org/2018/credentials/v1",
    87      "https://w3id.org/citizenship/v1",
    88      "https://w3id.org/security/bbs/v1"
    89    ],
    90    "type": ["VerifiableCredential", "PermanentResidentCard"],
    91    "@explicit": true,
    92    "identifier": {},
    93    "issuer": {},
    94    "issuanceDate": {},
    95    "credentialSubject": {
    96      "@explicit": true,
    97      "type": ["PermanentResident", "Person"],
    98      "givenName": {},
    99      "familyName": {},
   100      "gender": {}
   101    }
   102  }
   103  `
   104  
   105  	revealDoc, err := jsonutil.ToMap(revealJSON)
   106  	require.NoError(t, err)
   107  
   108  	nonce := []byte("nonce")
   109  
   110  	vcOptions := []CredentialOpt{WithJSONLDDocumentLoader(createTestDocumentLoader(t)), WithPublicKeyFetcher(
   111  		SingleKey(pubKeyBytes, "Bls12381G2Key2020"))}
   112  
   113  	vcWithSelectiveDisclosure, err := vc.GenerateBBSSelectiveDisclosure(revealDoc, nonce, vcOptions...)
   114  	require.NoError(t, err)
   115  	require.NotNil(t, vcWithSelectiveDisclosure)
   116  	require.Len(t, vcWithSelectiveDisclosure.Proofs, 1)
   117  
   118  	vcSelectiveDisclosureBytes, err := json.Marshal(vcWithSelectiveDisclosure)
   119  	require.NoError(t, err)
   120  
   121  	sigSuite := bbsblssignatureproof2020.New(
   122  		suite.WithCompactProof(),
   123  		suite.WithVerifier(bbsblssignatureproof2020.NewG2PublicKeyVerifier(nonce)))
   124  
   125  	vcVerified, err := parseTestCredential(t, vcSelectiveDisclosureBytes,
   126  		WithEmbeddedSignatureSuites(sigSuite),
   127  		WithPublicKeyFetcher(SingleKey(pubKeyBytes, "Bls12381G2Key2020")),
   128  	)
   129  	require.NoError(t, err)
   130  	require.NotNil(t, vcVerified)
   131  
   132  	// error cases
   133  	t.Run("failed generation of selective disclosure", func(t *testing.T) {
   134  		var (
   135  			anotherPubKey      *bbs12381g2pub.PublicKey
   136  			anotherPubKeyBytes []byte
   137  		)
   138  
   139  		anotherPubKey, _, err = bbs12381g2pub.GenerateKeyPair(sha256.New, nil)
   140  		require.NoError(t, err)
   141  
   142  		anotherPubKeyBytes, err = anotherPubKey.Marshal()
   143  		require.NoError(t, err)
   144  
   145  		vcWithSelectiveDisclosure, err = vc.GenerateBBSSelectiveDisclosure(revealDoc, nonce,
   146  			WithJSONLDDocumentLoader(createTestDocumentLoader(t)),
   147  			WithPublicKeyFetcher(SingleKey(anotherPubKeyBytes, "Bls12381G2Key2020")))
   148  		require.Error(t, err)
   149  		require.Contains(t, err.Error(), "create VC selective disclosure")
   150  		require.Empty(t, vcWithSelectiveDisclosure)
   151  	})
   152  
   153  	t.Run("public key fetcher is not passed", func(t *testing.T) {
   154  		vcWithSelectiveDisclosure, err = vc.GenerateBBSSelectiveDisclosure(revealDoc, nonce)
   155  		require.Error(t, err)
   156  		require.EqualError(t, err, "public key fetcher is not defined")
   157  		require.Empty(t, vcWithSelectiveDisclosure)
   158  	})
   159  
   160  	t.Run("Reveal document with hidden VC mandatory field", func(t *testing.T) {
   161  		revealJSONWithMissingIssuer := `
   162  {
   163    "@context": [
   164      "https://www.w3.org/2018/credentials/v1",
   165      "https://w3id.org/citizenship/v1",
   166      "https://w3id.org/security/bbs/v1"
   167    ],
   168    "type": ["VerifiableCredential", "PermanentResidentCard"],
   169    "@explicit": true,
   170    "identifier": {},
   171    "issuanceDate": {},
   172    "credentialSubject": {
   173      "@explicit": true,
   174      "type": ["PermanentResident", "Person"],
   175      "givenName": {},
   176      "familyName": {},
   177      "gender": {}
   178    }
   179  }
   180  `
   181  
   182  		revealDoc, err = jsonutil.ToMap(revealJSONWithMissingIssuer)
   183  		require.NoError(t, err)
   184  
   185  		vcWithSelectiveDisclosure, err = vc.GenerateBBSSelectiveDisclosure(revealDoc, nonce, vcOptions...)
   186  		require.Error(t, err)
   187  		require.Contains(t, err.Error(), "issuer is required")
   188  		require.Nil(t, vcWithSelectiveDisclosure)
   189  	})
   190  
   191  	t.Run("VC with no embedded proof", func(t *testing.T) {
   192  		vc.Proofs = nil
   193  		vcWithSelectiveDisclosure, err = vc.GenerateBBSSelectiveDisclosure(revealDoc, nonce, vcOptions...)
   194  		require.Error(t, err)
   195  		require.EqualError(t, err, "expected at least one proof present")
   196  		require.Empty(t, vcWithSelectiveDisclosure)
   197  	})
   198  }
   199  
   200  func signVCWithBBS(t *testing.T, privKey *bbs12381g2pub.PrivateKey, pubKeyBytes []byte, vc *Credential) {
   201  	t.Helper()
   202  
   203  	bbsSigner, err := newBBSSigner(privKey)
   204  	require.NoError(t, err)
   205  
   206  	sigSuite := bbsblssignature2020.New(
   207  		suite.WithSigner(bbsSigner),
   208  		suite.WithVerifier(bbsblssignature2020.NewG2PublicKeyVerifier()))
   209  
   210  	ldpContext := &LinkedDataProofContext{
   211  		SignatureType:           "BbsBlsSignature2020",
   212  		SignatureRepresentation: SignatureProofValue,
   213  		Suite:                   sigSuite,
   214  		VerificationMethod:      "did:example:123456#key1",
   215  	}
   216  
   217  	err = vc.AddLinkedDataProof(ldpContext, jsonld.WithDocumentLoader(createTestDocumentLoader(t)))
   218  	require.NoError(t, err)
   219  
   220  	vcSignedBytes, err := json.Marshal(vc)
   221  	require.NoError(t, err)
   222  	require.NotEmpty(t, vcSignedBytes)
   223  
   224  	vcVerified, err := parseTestCredential(t, vcSignedBytes,
   225  		WithEmbeddedSignatureSuites(sigSuite),
   226  		WithPublicKeyFetcher(SingleKey(pubKeyBytes, "Bls12381G2Key2020")),
   227  	)
   228  	require.NoError(t, err)
   229  	require.NotEmpty(t, vcVerified)
   230  }
   231  
   232  func signVCWithEd25519(t *testing.T, vc *Credential) {
   233  	t.Helper()
   234  
   235  	signer, err := newCryptoSigner(kms.ED25519Type)
   236  	require.NoError(t, err)
   237  
   238  	sigSuite := ed25519signature2018.New(
   239  		suite.WithSigner(signer),
   240  		suite.WithVerifier(ed25519signature2018.NewPublicKeyVerifier()))
   241  
   242  	ldpContext := &LinkedDataProofContext{
   243  		SignatureType:           "Ed25519Signature2018",
   244  		SignatureRepresentation: SignatureProofValue,
   245  		Suite:                   sigSuite,
   246  		VerificationMethod:      "did:example:123456#key1",
   247  	}
   248  
   249  	err = vc.AddLinkedDataProof(ldpContext, jsonld.WithDocumentLoader(createTestDocumentLoader(t)))
   250  	require.NoError(t, err)
   251  }