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

Commit b1d78bb

Browse files
author
Firas Qutishat
authored
Merge pull request #2384 from kdimak/issue-2295-ldp
feat: BbsBlsSignatureProof2020 LDP suite for VC
2 parents f648795 + 8301ac0 commit b1d78bb

23 files changed

+1782
-13
lines changed

pkg/doc/signature/jsonld/processor.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,36 @@ func (p *Processor) Compact(input, context map[string]interface{},
187187
return proc.Compact(input, context, options)
188188
}
189189

190+
// Frame makes a frame from the input view using frameDoc.
191+
func (p *Processor) Frame(view []string, frameDoc map[string]interface{},
192+
opts ...ProcessorOpts) (map[string]interface{}, error) {
193+
proc := ld.NewJsonLdProcessor()
194+
options := ld.NewJsonLdOptions("")
195+
options.ProcessingMode = ld.JsonLd_1_1
196+
options.Format = format
197+
options.ProduceGeneralizedRdf = true
198+
199+
procOptions := prepareOpts(opts)
200+
201+
useDocumentLoader(options, procOptions.documentLoader, procOptions.documentLoaderCache)
202+
203+
filteredJSONLd, err := proc.FromRDF(strings.Join(view, "\n"), options)
204+
if err != nil {
205+
return nil, err
206+
}
207+
208+
options.OmitGraph = true
209+
210+
frame, err := proc.Frame(filteredJSONLd, frameDoc, options)
211+
if err != nil {
212+
return nil, err
213+
}
214+
215+
frame["@context"] = frameDoc["@context"]
216+
217+
return frame, err
218+
}
219+
190220
// removeMatchingInvalidRDFs validates normalized view to find any invalid RDF and
191221
// returns filtered view after removing all invalid data except the ones given in rdfMatches argument.
192222
// [Note : handling invalid RDF data, by following pattern https://github.com/digitalbazaar/jsonld.js/issues/199]

pkg/doc/signature/jsonld/processor_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,3 +1490,45 @@ const trustblocExampleDoc = `
14901490
}
14911491
}
14921492
`
1493+
1494+
func TestProcessor_Frame(t *testing.T) {
1495+
processor := Default()
1496+
1497+
var doc map[string]interface{}
1498+
1499+
err := json.Unmarshal([]byte(jsonLdSample1), &doc)
1500+
require.NoError(t, err)
1501+
1502+
canonizedDoc, err := processor.GetCanonicalDocument(doc)
1503+
require.NoError(t, err)
1504+
1505+
t.Logf("canonizedDoc=\n%v", string(canonizedDoc))
1506+
1507+
frameJSON := `
1508+
{
1509+
"@context": [
1510+
"https://www.w3.org/2018/credentials/v1",
1511+
"https://www.w3.org/2018/credentials/examples/v1"
1512+
],
1513+
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
1514+
"credentialSubject": {
1515+
"@explicit": true,
1516+
"spouse": {}
1517+
}
1518+
}
1519+
`
1520+
1521+
var frameDoc map[string]interface{}
1522+
1523+
err = json.Unmarshal([]byte(frameJSON), &frameDoc)
1524+
require.NoError(t, err)
1525+
1526+
view := strings.Split(string(canonizedDoc), "\n")
1527+
framedView, err := processor.Frame(view, frameDoc)
1528+
require.NoError(t, err)
1529+
1530+
require.Equal(t, map[string]interface{}{
1531+
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
1532+
"spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1",
1533+
}, framedView["credentialSubject"])
1534+
}

pkg/doc/signature/proof/data.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,13 @@ const (
130130
proofID excludedKey = iota + 1
131131
proofValue
132132
jws
133+
nonce
133134
)
134135

135136
//nolint:gochecknoglobals
136137
var (
137-
excludedKeysStr = [...]string{"id", "proofValue", "jws"}
138-
excludedKeys = [...]excludedKey{proofID, proofValue, jws}
138+
excludedKeysStr = [...]string{"id", "proofValue", "jws", "nonce"}
139+
excludedKeys = [...]excludedKey{proofID, proofValue, jws, nonce}
139140
)
140141

141142
func (ek excludedKey) String() string {

pkg/doc/signature/proof/proof.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func NewProof(emap map[string]interface{}) (*Proof, error) {
7171
)
7272

7373
if generalProof, ok := emap[jsonldProofValue]; ok {
74-
proofValue, err = decodeProofValue(stringEntry(generalProof))
74+
proofValue, err = decodeBase64(stringEntry(generalProof))
7575
if err != nil {
7676
return nil, err
7777
}
@@ -86,7 +86,7 @@ func NewProof(emap map[string]interface{}) (*Proof, error) {
8686
return nil, errors.New("signature is not defined")
8787
}
8888

89-
nonce, err := base64.RawURLEncoding.DecodeString(stringEntry(emap[jsonldNonce]))
89+
nonce, err := decodeBase64(stringEntry(emap[jsonldNonce]))
9090
if err != nil {
9191
return nil, err
9292
}
@@ -128,19 +128,19 @@ func decodeCapabilityChain(proof map[string]interface{}) ([]interface{}, error)
128128
return capabilityChain, nil
129129
}
130130

131-
func decodeProofValue(proofStr string) ([]byte, error) {
131+
func decodeBase64(s string) ([]byte, error) {
132132
allEncodings := []*base64.Encoding{
133133
base64.RawURLEncoding, base64.StdEncoding,
134134
}
135135

136136
for _, encoding := range allEncodings {
137-
proofValue, err := encoding.DecodeString(proofStr)
137+
value, err := encoding.DecodeString(s)
138138
if err == nil {
139-
return proofValue, nil
139+
return value, nil
140140
}
141141
}
142142

143-
return nil, errors.New("unsupported proof encoding")
143+
return nil, errors.New("unsupported encoding")
144144
}
145145

146146
// stringEntry.

pkg/doc/signature/proof/proof_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func TestInvalidProofValue(t *testing.T) {
134134
})
135135
require.Error(t, err)
136136
require.Nil(t, p)
137-
require.EqualError(t, err, "unsupported proof encoding")
137+
require.EqualError(t, err, "unsupported encoding")
138138

139139
// proof is not defined (neither "proofValue" nor "jws" is defined)
140140
p, err = NewProof(map[string]interface{}{
@@ -158,7 +158,7 @@ func TestInvalidNonce(t *testing.T) {
158158
require.Error(t, err)
159159

160160
require.Nil(t, p)
161-
require.Contains(t, err.Error(), "illegal base64 data")
161+
require.Contains(t, err.Error(), "unsupported encoding")
162162
}
163163

164164
func TestProof_JSONLdObject(t *testing.T) {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package bbsblssignatureproof2020
8+
9+
import "github.com/hyperledger/aries-framework-go/pkg/doc/signature/verifier"
10+
11+
const g2PubKeyType = "Bls12381G2Key2020"
12+
13+
// NewG2PublicKeyVerifier creates a signature verifier that verifies a BbsBlsSignatureProof2020 signature
14+
// taking Bls12381G2Key2020 public key bytes as input.
15+
func NewG2PublicKeyVerifier(nonce []byte) *verifier.PublicKeyVerifier {
16+
return verifier.NewPublicKeyVerifier(verifier.NewBBSG2SignatureProofVerifier(nonce),
17+
verifier.WithExactPublicKeyType(g2PubKeyType))
18+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package bbsblssignatureproof2020_test
8+
9+
import (
10+
"encoding/base64"
11+
"testing"
12+
13+
"github.com/stretchr/testify/require"
14+
15+
"github.com/hyperledger/aries-framework-go/pkg/doc/jose"
16+
"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignatureproof2020"
17+
sigverifier "github.com/hyperledger/aries-framework-go/pkg/doc/signature/verifier"
18+
)
19+
20+
//nolint:lll
21+
func TestNewG2PublicKeyVerifier(t *testing.T) {
22+
verifier := bbsblssignatureproof2020.NewG2PublicKeyVerifier([]byte("nonce"))
23+
24+
pkBase64 := "sVEbbh9jDPGSBK/oT/EeXQwFvNuC+47rgq9cxXKrwo6G7k4JOY/vEcfgZw9Vf/TpArbIdIAJCFMDyTd7l2atS5zExAKX0B/9Z3E/mgIZeQJ81iZ/1HUnUCT2Om239KFx"
25+
pkBytes, err := base64.RawStdEncoding.DecodeString(pkBase64)
26+
require.NoError(t, err)
27+
28+
sigBase64 := "AAIBiN4EL9psRsIUlwQah7a5VROD369PPt09Z+jfzamP+/114a5RfWVMju3NCUl2Yv6ahyIdHGdEfxhC985ShlGQrRPLa+crFRiu2pfnAk+L6QMNooVMQhzJc2yYgktHen4QhsKV3IGoRRUs42zqPTP3BdqIPQeLgjDVi1d1LXEnP+WFQGEQmTKWTja4u1MsERdmAAAAdIb6HuFznhE3OByXN0Xp3E4hWQlocCdpExyNlSLh3LxK5duCI/WMM7ETTNS0Ozxe3gAAAAIuALkiwplgKW6YmvrEcllWSkG3H+uHEZzZGL6wq6Ac0SuktQ4n84tZPtMtR9vC1Rsu8f7Kwtbq1Kv4v02ct9cvj7LGcitzg3u/ZO516qLz+iitKeGeJhtFB8ggALcJOEsebPFl12cYwkieBbIHCBt4AAAAAxgEHt3iqKIyIQbTYJvtrMjGjT4zuimiZbtE3VXnqFmGaxVTeR7dh89PbPtsBI8LLMrCvFFpks9D/oTzxnw13RBmMgMlc1bcfQOmE9DZBGB7NCdwOnT7q4TVKhswOITKTQ=="
29+
sigBytes, err := base64.StdEncoding.DecodeString(sigBase64)
30+
require.NoError(t, err)
31+
32+
msg := `
33+
message1
34+
message2
35+
`
36+
37+
err = verifier.Verify(&sigverifier.PublicKey{
38+
Type: "Bls12381G2Key2020",
39+
Value: pkBytes,
40+
}, []byte(msg), sigBytes)
41+
require.NoError(t, err)
42+
43+
err = verifier.Verify(&sigverifier.PublicKey{
44+
Type: "NotBls12381G2Key2020",
45+
Value: pkBytes,
46+
}, []byte(msg), sigBytes)
47+
require.Error(t, err)
48+
require.EqualError(t, err, "a type of public key is not 'Bls12381G2Key2020'")
49+
50+
// Failed as we do not support JWK for Bls12381G2Key2020.
51+
err = verifier.Verify(&sigverifier.PublicKey{
52+
Type: "Bls12381G2Key2020",
53+
JWK: &jose.JWK{
54+
Kty: "EC",
55+
Crv: "BLS12381_G2",
56+
},
57+
}, []byte(msg), sigBytes)
58+
require.Error(t, err)
59+
require.EqualError(t, err, "verifier does not match JSON Web Key")
60+
}

0 commit comments

Comments
 (0)