Skip to content

Commit

Permalink
fix: Leave BBS+ Selective Disclosure proofs only
Browse files Browse the repository at this point in the history
closes hyperledger-archives#2440

Signed-off-by: Dmitriy Kinoshenko <[email protected]>
  • Loading branch information
kdimak authored and sudeshrshetty committed Jan 22, 2022
1 parent 75a087c commit 7fc59cc
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 140 deletions.
1 change: 1 addition & 0 deletions cmd/aries-agent-mobile/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/gval v1.1.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw=
Expand Down
1 change: 1 addition & 0 deletions cmd/aries-agent-rest/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/gval v1.1.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw=
Expand Down
1 change: 1 addition & 0 deletions cmd/aries-js-worker/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/gval v1.1.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw=
Expand Down
1 change: 0 additions & 1 deletion component/storage/jsindexeddb/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+q
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw=
Expand Down
1 change: 0 additions & 1 deletion component/storage/leveldb/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+q
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw=
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
module github.com/hyperledger/aries-framework-go

require (
github.com/PaesslerAG/gval v1.0.0
github.com/PaesslerAG/gval v1.1.0
github.com/PaesslerAG/jsonpath v0.1.1
github.com/VictoriaMetrics/fastcache v1.5.7
github.com/bluele/gcache v0.0.0-20190518031135-bc40bd653833
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/PaesslerAG/gval v1.0.0 h1:GEKnRwkWDdf9dOmKcNrar9EA1bz1z9DqPIO1+iLzhd8=
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/gval v1.1.0 h1:k3RuxeZDO3eejD4cMPSt+74tUSvTnbGvLx0df4mdwFc=
github.com/PaesslerAG/gval v1.1.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk=
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
Expand Down
6 changes: 3 additions & 3 deletions pkg/doc/signature/suite/bbsblssignature2020/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite"
)

// Suite implements EcdsaSecp256k1Signature2019 signature suite.
// Suite implements BbsBlsSignature2020 signature suite.
type Suite struct {
suite.SignatureSuite
jsonldProcessor *jsonld.Processor
Expand All @@ -40,7 +40,7 @@ func New(opts ...suite.Opt) *Suite {
}

// GetCanonicalDocument will return normalized/canonical version of the document.
// EcdsaSecp256k1Signature2019 signature suite uses RDF Dataset Normalization as canonicalization algorithm.
// BbsBlsSignature2020 signature suite uses RDF Dataset Normalization as canonicalization algorithm.
func (s *Suite) GetCanonicalDocument(doc map[string]interface{}, opts ...jsonld.ProcessorOpts) ([]byte, error) {
return s.jsonldProcessor.GetCanonicalDocument(doc, opts...)
}
Expand All @@ -50,7 +50,7 @@ func (s *Suite) GetDigest(doc []byte) []byte {
return doc
}

// Accept will accept only EcdsaSecp256k1Signature2019 signature type.
// Accept will accept only BbsBlsSignature2020 signature type.
func (s *Suite) Accept(t string) bool {
return t == signatureType
}
192 changes: 104 additions & 88 deletions pkg/doc/signature/suite/bbsblssignatureproof2020/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import (
)

const (
securityContext = "https://w3id.org/security/v2"
securityContext = "https://w3id.org/security/v2"
bbsBlsSignature2020 = "BbsBlsSignature2020"
)

// keyResolver encapsulates key resolution.
Expand All @@ -35,7 +36,7 @@ func (s *Suite) SelectiveDisclosure(doc map[string]interface{}, revealDoc map[st
nonce []byte, resolver keyResolver, opts ...jsonld.ProcessorOpts) (map[string]interface{}, error) {
docCompacted, err := getCompactedWithSecuritySchema(doc, opts...)
if err != nil {
return nil, err
return nil, fmt.Errorf("compact doc with security schema: %w", err)
}

rawProofs := docCompacted["proof"]
Expand All @@ -45,53 +46,76 @@ func (s *Suite) SelectiveDisclosure(doc map[string]interface{}, revealDoc map[st

delete(docCompacted, "proof")

proofInfo, err := getBlsProof(rawProofs)
blsSignatures, err := getBlsProofs(rawProofs)
if err != nil {
return nil, err
return nil, fmt.Errorf("get BLS proofs: %w", err)
}

blsProof := proofInfo.blsProof
if len(blsSignatures) == 0 {
return nil, errors.New("no BbsBlsSignature2020 proof present")
}

pubKeyBytes, signatureBytes, err := getPublicKeyAndSignature(blsProof, resolver)
if err != nil {
return nil, err
docVerData, pErr := buildDocVerificationData(docCompacted, revealDoc, opts...)
if pErr != nil {
return nil, fmt.Errorf("build document verification data: %w", pErr)
}

verData, err := buildVerificationData(docCompacted, blsProof, revealDoc, opts...)
if err != nil {
return nil, err
proofs := make([]map[string]interface{}, len(blsSignatures))

for i, blsSignature := range blsSignatures {
verData, dErr := buildVerificationData(blsSignature, docVerData, opts...)
if dErr != nil {
return nil, fmt.Errorf("build verification data: %w", dErr)
}

derivedProof, dErr := generateSignatureProof(blsSignature, resolver, nonce, verData)
if dErr != nil {
return nil, fmt.Errorf("generate signature proof: %w", dErr)
}

proofs[i] = derivedProof
}

revealDocumentResult := docVerData.revealDocumentResult
revealDocumentResult["proof"] = proofs

return revealDocumentResult, nil
}

func generateSignatureProof(blsSignature map[string]interface{}, resolver keyResolver, nonce []byte,
verData *verificationData) (map[string]interface{}, error) {
bls := bbs12381g2pub.New()

pubKeyBytes, signatureBytes, pErr := getPublicKeyAndSignature(blsSignature, resolver)
if pErr != nil {
return nil, fmt.Errorf("get public key and signature: %w", pErr)
}

signatureProofBytes, err := bls.DeriveProof(verData.blsMessages, signatureBytes,
nonce, pubKeyBytes, verData.revealIndexes)
if err != nil {
return nil, fmt.Errorf("derive BBS+ proof: %w", err)
}

derivedProof := map[string]interface{}{
"type": signatureType,
"type": signatureProofType,
"nonce": base64.StdEncoding.EncodeToString(nonce),
"verificationMethod": blsProof["verificationMethod"],
"proofPurpose": blsProof["proofPurpose"],
"created": blsProof["created"],
"verificationMethod": blsSignature["verificationMethod"],
"proofPurpose": blsSignature["proofPurpose"],
"created": blsSignature["created"],
"proofValue": base64.StdEncoding.EncodeToString(signatureProofBytes),
}

allProofs := insertProof(proofInfo.allOtherProofs, proofInfo.blsProofInd, derivedProof)
verData.revealDocumentResult["proof"] = allProofs

return verData.revealDocumentResult, nil
return derivedProof, nil
}

func getPublicKeyAndSignature(blsProofMap map[string]interface{}, resolver keyResolver) ([]byte, []byte, error) {
blsProof, err := proof.NewProof(blsProofMap)
func getPublicKeyAndSignature(blsSignatureMap map[string]interface{}, resolver keyResolver) ([]byte, []byte, error) {
blsSignature, err := proof.NewProof(blsSignatureMap)
if err != nil {
return nil, nil, fmt.Errorf("parse BBS+ signature: %w", err)
}

keyID, err := blsProof.PublicKeyID()
keyID, err := blsSignature.PublicKeyID()
if err != nil {
return nil, nil, fmt.Errorf("get public KID from BBS+ signature: %w", err)
}
Expand All @@ -101,67 +125,76 @@ func getPublicKeyAndSignature(blsProofMap map[string]interface{}, resolver keyRe
return nil, nil, fmt.Errorf("resolve public key of BBS+ signature: %w", err)
}

return publicKey.Value, blsProof.ProofValue, nil
}

type blsProofInfo struct {
blsProof map[string]interface{}
allOtherProofs []map[string]interface{}
blsProofInd int
return publicKey.Value, blsSignature.ProofValue, nil
}

func getBlsProof(rawProofs interface{}) (*blsProofInfo, error) {
func getBlsProofs(rawProofs interface{}) ([]map[string]interface{}, error) {
allProofs, err := getProofs(rawProofs)
if err != nil {
return nil, err
return nil, fmt.Errorf("read document proofs: %w", err)
}

blsProofInd := -1

var blsProof map[string]interface{}
blsProofs := make([]map[string]interface{}, 0)

for i, proof := range allProofs {
if proof["type"] == "https://w3c-ccg.github.io/ldp-bbs2020/context/v1#BbsBlsSignature2020" {
blsProofInd = i
allProofs = deleteProof(allProofs, i)
blsProof = proof
blsProof["@context"] = securityContext
for _, p := range allProofs {
proofType, ok := p["type"].(string)
if ok && strings.HasSuffix(proofType, bbsBlsSignature2020) {
p["@context"] = securityContext
blsProofs = append(blsProofs, p)
}
}

if blsProofInd == -1 {
return nil, errors.New("no BbsBlsSignature2020 proof present")
}

return &blsProofInfo{
blsProof: blsProof,
allOtherProofs: allProofs,
blsProofInd: blsProofInd,
}, nil
return blsProofs, nil
}

type verificationData struct {
blsMessages [][]byte
type docVerificationData struct {
revealIndexes []int
revealDocumentResult map[string]interface{}
documentStatements []string
}

func buildVerificationData(docCompacted, blsProof, revealDoc map[string]interface{},
type verificationData struct {
blsMessages [][]byte
revealIndexes []int
}

func buildVerificationData(blsProof map[string]interface{}, docVerData *docVerificationData,
opts ...jsonld.ProcessorOpts) (*verificationData, error) {
documentStatements, err := createVerifyDocumentData(docCompacted, opts...)
proofStatements, err := createVerifyProofData(blsProof, opts...)
if err != nil {
return nil, err
return nil, fmt.Errorf("create verify proof data: %w", err)
}

proofStatements, err := createVerifyProofData(blsProof, opts...)
numberOfProofStatements := len(proofStatements)
revealIndexes := make([]int, numberOfProofStatements+len(docVerData.documentStatements))

for i := 0; i < numberOfProofStatements; i++ {
revealIndexes[i] = i
}

for i := range docVerData.revealIndexes {
revealIndexes[i+numberOfProofStatements] = numberOfProofStatements + docVerData.revealIndexes[i]
}

allInputStatements := append(proofStatements, docVerData.documentStatements...)
blsMessages := toArrayOfBytes(allInputStatements)

return &verificationData{
blsMessages: blsMessages,
revealIndexes: revealIndexes,
}, nil
}

func buildDocVerificationData(docCompacted, revealDoc map[string]interface{},
opts ...jsonld.ProcessorOpts) (*docVerificationData, error) {
documentStatements, err := createVerifyDocumentData(docCompacted, opts...)
if err != nil {
return nil, err
return nil, fmt.Errorf("create verify document data: %w", err)
}

transformedInputDocumentStatements := make([]string, len(documentStatements))

for i, element := range documentStatements {
// todo this can be simplified by just check of prefix _:c14n
nodeIdentifier := strings.Split(element, " ")[0]
if strings.HasPrefix(nodeIdentifier, "_:c14n") {
transformedInputDocumentStatements[i] = "urn:bnid:" + nodeIdentifier
Expand All @@ -173,20 +206,15 @@ func buildVerificationData(docCompacted, blsProof, revealDoc map[string]interfac

revealDocumentResult, err := jsonld.Default().Frame(documentStatements, revealDoc, opts...)
if err != nil {
return nil, err
return nil, fmt.Errorf("frame doc with reveal doc: %w", err)
}

revealDocumentStatements, err := createVerifyDocumentData(revealDocumentResult, opts...)
if err != nil {
return nil, err
return nil, fmt.Errorf("create verify reveal document data: %w", err)
}

numberOfProofStatements := len(proofStatements)
revealIndexes := make([]int, numberOfProofStatements+len(revealDocumentStatements))

for i := 0; i < numberOfProofStatements; i++ {
revealIndexes[i] = i
}
revealIndexes := make([]int, len(revealDocumentStatements))

transformedInputDocumentStatementsMap := make(map[string]int)
for i, statement := range transformedInputDocumentStatements {
Expand All @@ -196,14 +224,11 @@ func buildVerificationData(docCompacted, blsProof, revealDoc map[string]interfac
for i := range revealDocumentStatements {
statement := revealDocumentStatements[i]
statementInd := transformedInputDocumentStatementsMap[statement]
revealIndexes[i+numberOfProofStatements] = numberOfProofStatements + statementInd
revealIndexes[i] = statementInd
}

allInputStatements := append(proofStatements, documentStatements...)
blsMessages := toArrayOfBytes(allInputStatements)

return &verificationData{
blsMessages: blsMessages,
return &docVerificationData{
documentStatements: documentStatements,
revealIndexes: revealIndexes,
revealDocumentResult: revealDocumentResult,
}, nil
Expand Down Expand Up @@ -264,9 +289,15 @@ func splitMessageIntoLines(msg string) []string {
}

func createVerifyProofData(proofMap map[string]interface{}, opts ...jsonld.ProcessorOpts) ([]string, error) {
delete(proofMap, "proofValue")
proofMapCopy := make(map[string]interface{}, len(proofMap)-1)

proofBytes, err := jsonld.Default().GetCanonicalDocument(proofMap, opts...)
for k, v := range proofMap {
if k != "proofValue" {
proofMapCopy[k] = v
}
}

proofBytes, err := jsonld.Default().GetCanonicalDocument(proofMapCopy, opts...)
if err != nil {
return nil, err
}
Expand All @@ -283,18 +314,3 @@ func toArrayOfBytes(messages []string) [][]byte {

return res
}

func insertProof(proofs []map[string]interface{}, index int, proofMap map[string]interface{}) []map[string]interface{} {
if len(proofs) == index {
return append(proofs, proofMap)
}

proofs = append(proofs[:index+1], proofs[index:]...) // index < len(a)
proofs[index] = proofMap

return proofs
}

func deleteProof(proofs []map[string]interface{}, index int) []map[string]interface{} {
return append(proofs[:index], proofs[index+1:]...)
}
Loading

0 comments on commit 7fc59cc

Please sign in to comment.