Skip to content

Commit

Permalink
test: BSS+ signature proof (selective disclosure) interop tests with …
Browse files Browse the repository at this point in the history
…Mattr

closes hyperledger-archives#2223

Signed-off-by: Dmitriy Kinoshenko <[email protected]>
  • Loading branch information
kdimak authored and sudeshrshetty committed Jan 22, 2022
1 parent 1ab26df commit 9bd27a8
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 37 deletions.
25 changes: 13 additions & 12 deletions pkg/doc/verifiable/credential_ldp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,20 +536,15 @@ func TestParseCredentialFromLinkedDataProof_BbsBlsSignature2020(t *testing.T) {
func TestParseCredentialFromLinkedDataProof_BbsBlsSignatureProof2020(t *testing.T) {
r := require.New(t)

sigSuite := bbsblssignatureproof2020.New(
suite.WithCompactProof(),
suite.WithVerifier(bbsblssignatureproof2020.NewG2PublicKeyVerifier([]byte("nonce"))))

vcJSON := `
{
vcJSON := `{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/citizenship/v1",
"https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
],
"id": "https://issuer.oidp.uscis.gov/credentials/83627465",
"type": [
"VerifiableCredential",
"VerifiableCredential",
"PermanentResidentCard"
],
"description": "Government of Example Permanent Resident Card.",
Expand All @@ -570,14 +565,20 @@ func TestParseCredentialFromLinkedDataProof_BbsBlsSignatureProof2020(t *testing.
"issuer": "did:example:489398593",
"proof": {
"type": "BbsBlsSignatureProof2020",
"created": "2020-12-06T19:23:10Z",
"nonce": "bm9uY2U=",
"created": "2020-12-08T09:13:30Z",
"nonce": "X2qLaTxoyidu7Z/TOBRNgPhbcgeIcOGMAXQrM65vP/ehcop2wwCeV4/HTcnF70zANOc=",
"proofPurpose": "assertionMethod",
"proofValue": "ABkB/wbvi77V4fFx9Ewo4+52/X3Fdd79uRExQeet0PVrdP3wyExE5ib6fTVUGbnX6CK3UgNbli+RgYV21g9taTaIbS9g3HIX3csJRWm0sFNq2lxlXNF9I6skrRpJBt9VnjvXrFxTgEkuSbcrG4jaulj0mXLoZIuz8yrmXKBG+35TPiVXf1zh29RtXIKPHeZ7sWJ3RkKSAAAAdIx7On9kZkbGb9IECei4H4vjcZYJi7Q2Ywz4Bc/+4FCrMiu5C50T0nxScWFh4v2oHAAAAAI8/usecIohptQnf7ZO1UsTLH7u+NN5avFfxGTsmY9BVgS60Lbyzx89mmn2Ce5W3L9ZS4bkwS2CXeQXfl268oTWixysSv+L1q1+e6cdqlY/GA2LGWVCZoTli6mJ+EIDCNcSM75Hs8cTrDOfTuTmAwl9AAAACWyOb/UWrb1nWkbNTPpctXAUeuQjdbwogCTYKUiVK+LJbfpN+rU9WDpxRTjloBTrVttniuvb+mdatofrCCpFvKwowHK+W9/+AHSBteG0xfJoTvaa57PEsIm/Qf1N5WgB0ScpwyD1e6A0kPOqVI75+CkH5wa728ycOxS/upRp6GsMZgGP66yzZg7hIZrIj0LXWiP1nigcHzx3pImJHxwz3xhEB/4QGZwZB8VX1TlTrI5GSO3BuCIA5um/SJF09iPWAgF7KY0+XrcxXg808zDjuqMRgsD9gHlqomjVCeWUhzsFVAafbMJ9DsgcAKoaWg+0yJvvnTVEelS96uvwnKFrSTsmpQMsgEb9lRHKb+v/Xr4+0THjTn4n//uhCy51+tGU7g==",
"proofValue": "ABkB/wbvtko1Y9xNW55tg6AYrvZkJfcEGsTB3BDOJaDjfeUWtg0610W7IzPyWjy2BDX+9VLFo2KcVal2CPsRk0E98292Ocbotwby9hdStE1zFQrgrfeoiYNxTD0HrUa6DwZ4X9f/jhFHwvxEl681jjwcZJWHhbzLIzJf7ms68PgNpPG7saBOqi3IqK+pxg4bxG1dS8z2AAAAdK93JmDD/9JGPh6z+Ur5BenOfX6t9ineW1pFMg7kcwOFxHjQ6NOSk7UmwfVjunYk+QAAAAIjiRSXcTv/GBwgUDaUsFlLy5SZW91C9I1YiHwsIyTCxAhttkeWJzSaxq5ZhRaSfmzbfLZShkuXJmFTy/qRLYj5iNSGzPkS/AlRJU2MPr7MwViX3SHEmi/nejOSpxYn/oDc0c7TyFFpyshgEZxu2/S3AAAACQK2jcWuij0VZu7NvXEMnJ4LgnQPLH9IEiEhRD27+4FnHW4XOIvZSFyiMtyy+9FRJCO7RlabIhh2r9F8filWhcQxsm6iF2+fUmTykUzk8/rv0gdtbBy1/Oc3+yrsGlg4pByhm9Ze6mSns9caeosdWR6+A9kHy4aUlndXkV83pnrrKVmGcFxE03oxFHU6piwL1g2OCk3Qef1KV5QlIDjWKvk93zSh1QtPjvo8FKXMKF2DWxLSB9do874n2cW9Ae0qgh1vLRCp9Vf8Dh3EBApdxTTseiJ2Y97u+ktOJM/5qHOHP9sBRU+Y1W1HHC8dVl0QXedVdYk4uuKASD/zgpwjiSRIGRWpv6WRCioN+ItKtGQ55/aHCE8m9LpxpGAen/NnEg==",
"verificationMethod": "did:example:489398593#test"
}
}
`
}`

nonceBytes, err := base64.StdEncoding.DecodeString("X2qLaTxoyidu7Z/TOBRNgPhbcgeIcOGMAXQrM65vP/ehcop2wwCeV4/HTcnF70zANOc=")
require.NoError(t, err)

sigSuite := bbsblssignatureproof2020.New(
suite.WithCompactProof(),
suite.WithVerifier(bbsblssignatureproof2020.NewG2PublicKeyVerifier(nonceBytes)))

pkBase58 := "oqpWYKaZD9M1Kbe94BVXpr8WTdFBNZyKv48cziTiQUeuhm7sBhCABMyYG4kcMrseC68YTFFgyhiNeBKjzdKk9MiRWuLv5H4FFujQsQK2KTAtzU8qTBiZqBHMmnLF4PL7Ytu"
pubKeyBytes := base58.Decode(pkBase58)
Expand Down
15 changes: 15 additions & 0 deletions test/bbs/data/revealDocument.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/citizenship/v1",
"https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
],
"type": ["VerifiableCredential", "PermanentResidentCard"],
"credentialSubject": {
"@explicit": true,
"type": ["PermanentResident", "Person"],
"givenName": {},
"familyName": {},
"gender": {}
}
}
16 changes: 1 addition & 15 deletions test/bbs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

118 changes: 112 additions & 6 deletions test/bbs/src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ SPDX-License-Identifier: Apache-2.0
package main

import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
Expand All @@ -20,18 +21,21 @@ import (
"github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld"
"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite"
"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignature2020"
"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignatureproof2020"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
)

func main() {
js.Global().Set("signVCAsync", js.FuncOf(signVCJS))
js.Global().Set("verifyVCAsync", js.FuncOf(verifyVCJS))
js.Global().Set("deriveVCProofAsync", js.FuncOf(deriveVCProofJS))
js.Global().Set("verifyProofVCAsync", js.FuncOf(verifyProofVCJS))

select {}
}

func signVCJS(_ js.Value, args []js.Value) interface{} {
vcObj, privKeyObj, verificationMethodObj, callback := args[0], args[1], args[2], args[3]
privKeyObj, vcObj, verificationMethodObj, callback := args[0], args[1], args[2], args[3]

go func(privKeyB64, vcJSON, verificationMethod string, callback js.Value) {
vcSigned, err := signVC(privKeyB64, vcJSON, verificationMethod)
Expand All @@ -40,13 +44,13 @@ func signVCJS(_ js.Value, args []js.Value) interface{} {
} else {
callback.Invoke(js.Null(), string(vcSigned))
}
}(vcObj.String(), privKeyObj.String(), verificationMethodObj.String(), callback)
}(privKeyObj.String(), vcObj.String(), verificationMethodObj.String(), callback)

return nil
}

func verifyVCJS(_ js.Value, args []js.Value) interface{} {
vcObj, pubKeyObj, callback := args[0], args[1], args[2]
pubKeyObj, vcObj, callback := args[0], args[1], args[2]

go func(pubKeyB64, vcJSON string, callback js.Value) {
err := verifyVC(pubKeyB64, vcJSON)
Expand All @@ -55,7 +59,37 @@ func verifyVCJS(_ js.Value, args []js.Value) interface{} {
} else {
callback.Invoke(js.Null())
}
}(vcObj.String(), pubKeyObj.String(), callback)
}(pubKeyObj.String(), vcObj.String(), callback)

return nil
}

func deriveVCProofJS(_ js.Value, args []js.Value) interface{} {
pubKeyObj, vcObj, revealJSON, nonce, callback := args[0], args[1], args[2], args[3], args[4]

go func(pubKeyB64, vcJSON, revealJSON, nonce string, callback js.Value) {
vcSigned, err := deriveProofVC(pubKeyB64, vcJSON, revealJSON, nonce)
if err != nil {
callback.Invoke(err.Error(), js.Null())
} else {
callback.Invoke(js.Null(), string(vcSigned))
}
}(pubKeyObj.String(), vcObj.String(), revealJSON.String(), nonce.String(), callback)

return nil
}

func verifyProofVCJS(_ js.Value, args []js.Value) interface{} {
pubKeyObj, vcObj, callback := args[0], args[1], args[2]

go func(pubKeyB64, vcJSON string, callback js.Value) {
err := verifyProofVC(pubKeyB64, vcJSON)
if err != nil {
callback.Invoke(err.Error())
} else {
callback.Invoke(js.Null())
}
}(pubKeyObj.String(), vcObj.String(), callback)

return nil
}
Expand All @@ -68,12 +102,12 @@ func signVC(privKeyB64, vcJSON, verificationMethod string) ([]byte, error) {
return nil, errors.New("invalid private key")
}

bbsSigner, err := newBBSSigner(privKey)
signer, err := newBBSSigner(privKey)
if err != nil {
return nil, fmt.Errorf("create BBS signer: %w", err)
}

sigSuite := bbsblssignature2020.New(suite.WithSigner(bbsSigner))
sigSuite := bbsblssignature2020.New(suite.WithSigner(signer))

ldpContext := &verifiable.LinkedDataProofContext{
SignatureType: "BbsBlsSignature2020",
Expand Down Expand Up @@ -118,3 +152,75 @@ func verifyVC(pubKeyB64, vcJSON string) error {

return err
}

func verifyProofVC(pubKeyB64, vcJSON string) error {
pubKeyBytes := base58.Decode(pubKeyB64)

var vcDoc map[string]interface{}

err := json.Unmarshal([]byte(vcJSON), &vcDoc)
if err != nil {
return fmt.Errorf("parse VC doc: %w", err)
}

proof, ok := vcDoc["proof"].(map[string]interface{})
if !ok {
return fmt.Errorf("unexpected \"proof\" format: %w", err)
}

nonce, ok := proof["nonce"].(string)
if !ok {
return fmt.Errorf("unexpected \"nonce\" format: %w", err)
}

nonceBytes, err := base64.StdEncoding.DecodeString(nonce)
if err != nil {
return fmt.Errorf("nonce base64 format: %w", err)
}

sigSuite := bbsblssignatureproof2020.New(
suite.WithCompactProof(),
suite.WithVerifier(bbsblssignatureproof2020.NewG2PublicKeyVerifier(nonceBytes)))

jsonldDocLoader := createLDPBBS2020DocumentLoader()

_, err = verifiable.ParseCredential([]byte(vcJSON),
verifiable.WithJSONLDDocumentLoader(jsonldDocLoader),
verifiable.WithEmbeddedSignatureSuites(sigSuite),
verifiable.WithPublicKeyFetcher(verifiable.SingleKey(pubKeyBytes, "Bls12381G2Key2020")),
)

return err
}

func deriveProofVC(pubKeyB64, vcJSON, revealJSON, nonce string) ([]byte, error) {
pubKeyBytes := base58.Decode(pubKeyB64)

jsonldLoader := createLDPBBS2020DocumentLoader()

vc, err := verifiable.ParseUnverifiedCredential([]byte(vcJSON), verifiable.WithJSONLDDocumentLoader(jsonldLoader))
if err != nil {
return nil, err
}

var revealDoc map[string]interface{}

err = json.Unmarshal([]byte(revealJSON), &revealDoc)
if err != nil {
return nil, fmt.Errorf("unmarshal reveal doc: %w", err)
}

withJSONLDDocLoader := jsonld.WithDocumentLoader(jsonldLoader)

vcSD, err := vc.GenerateBBSSelectiveDisclosure(revealDoc, pubKeyBytes, []byte(nonce), withJSONLDDocLoader)
if err != nil {
return nil, fmt.Errorf("create selective disclosure: %w", err)
}

vcSDBytes, err := json.Marshal(vcSD)
if err != nil {
return nil, err
}

return vcSDBytes, nil
}
26 changes: 26 additions & 0 deletions test/bbs/src/vc.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,29 @@ exports.verifyAries = function verifyAries(publicKey, vc) {
});
});
}

exports.deriveProofAries = function deriveProofAries(publicKey, vc, revealDoc, nonce) {
return new Promise((resolve, reject) => {
deriveVCProofAsync(publicKey, vc, revealDoc, nonce, (err, vcWithDerivedProof) => {
if (err) {
reject(err);
return;
}

resolve(vcWithDerivedProof);
});
});
}

exports.verifyProofAries = function verifyProofAries(publicKey, vc) {
return new Promise((resolve, reject) => {
verifyProofVCAsync(publicKey, vc, (err) => {
if (err) {
reject(err);
return;
}

resolve();
});
});
}
45 changes: 41 additions & 4 deletions test/bbs/test/bbs.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ SPDX-License-Identifier: Apache-2.0
const fs = require("fs");
const assert = require('chai').assert;

const {signAries, verifyAries} = require("../src/vc.js");
const {signAries, verifyAries, deriveProofAries, verifyProofAries} = require("../src/vc.js");

const {Bls12381G2KeyPair, BbsBlsSignature2020} = require("@mattrglobal/jsonld-signatures-bbs");
const {extendContextLoader, sign: signMattr, verify: verifyMattr, purposes} = require("jsonld-signatures");
const {Bls12381G2KeyPair, BbsBlsSignature2020, BbsBlsSignatureProof2020, deriveProof: deriveProofMattr} = require("@mattrglobal/jsonld-signatures-bbs");
const {extendContextLoader, sign: signMattr, verify: verifyMattr, purposes,} = require("jsonld-signatures");
const {documentLoaders} = require("jsonld");

const bbsContext = JSON.parse(fs.readFileSync("data/context/ldp-bbs2020.jsonld", 'utf-8'));
const citizenVocab = JSON.parse(fs.readFileSync("data/context/citizenship.jsonld", 'utf-8'));
const vc = JSON.parse(fs.readFileSync("data/inputDocument.json", 'utf-8'));
const keyPairOptions = JSON.parse(fs.readFileSync("data/keyPair.json", 'utf-8'));
const revealDocument = JSON.parse(fs.readFileSync("data/revealDocument.json", 'utf-8'));

const documents = {
"did:example:489398593#test": keyPairOptions,
Expand Down Expand Up @@ -60,6 +60,8 @@ describe("BBS+ interop fixtures", function () {
})

it('sign with Aries and verify with Mattr', async function () {
const vc = JSON.parse(fs.readFileSync("data/inputDocument.json", 'utf-8'));

let signedVC = await signAries(keyPairOptions.privateKeyBase58, JSON.stringify(vc), "did:example:489398593#test");

let verified = await verifyMattr(JSON.parse(signedVC), {
Expand All @@ -72,6 +74,7 @@ describe("BBS+ interop fixtures", function () {
})

it('sign with Mattr and verify with Aries', async function () {
const vc = JSON.parse(fs.readFileSync("data/inputDocument.json", 'utf-8'));
const keyPair = await new Bls12381G2KeyPair(keyPairOptions);

const signedDocument = await signMattr(vc, {
Expand All @@ -82,6 +85,40 @@ describe("BBS+ interop fixtures", function () {

await verifyAries(keyPairOptions.publicKeyBase58, JSON.stringify(signedDocument));
})

it('derive signature proof with Aries and verify with Mattr', async function () {
const vc = JSON.parse(fs.readFileSync("data/inputDocument.json", 'utf-8'));

let signedVC = await signAries(keyPairOptions.privateKeyBase58, JSON.stringify(vc), "did:example:489398593#test");

const nonce = "nonce";
let derivedProof = await deriveProofAries(keyPairOptions.publicKeyBase58, signedVC, JSON.stringify(revealDocument), nonce);

let verified = await verifyMattr(JSON.parse(derivedProof), {
suite: new BbsBlsSignatureProof2020(),
purpose: new purposes.AssertionProofPurpose(),
documentLoader
});
assert.isTrue(verified.verified);
})

it('derive signature proof with Mattr and verify with Aries', async function () {
const vc = JSON.parse(fs.readFileSync("data/inputDocument.json", 'utf-8'));
const keyPair = await new Bls12381G2KeyPair(keyPairOptions);

const signedDocument = await signMattr(vc, {
suite: new BbsBlsSignature2020({key: keyPair}),
purpose: new purposes.AssertionProofPurpose(),
documentLoader
});

const derivedProof = await deriveProofMattr(signedDocument, revealDocument, {
suite: new BbsBlsSignatureProof2020(),
documentLoader,
});

await verifyProofAries(keyPairOptions.publicKeyBase58, JSON.stringify(derivedProof));
})
})

function sleep(ms) {
Expand Down

0 comments on commit 9bd27a8

Please sign in to comment.