Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: bjj-signature (add docProof to jsonld-merkelization) #390

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The Hypersign Identity Network is a permissionless blockchain network to manage
- Stake `$HID` tokens
- Submit Governance Proposals
- Transfer `$HID` tokens within and across different Tendermint-based blockchains using IBC
- Deploy CosmWasm Smart Contracts (Governance Based)
- Deploy CosmWasm Smart Contracts

## Prerequisite

Expand Down
2 changes: 1 addition & 1 deletion cmd/hid-noded/cmd/debug_extensions_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func getDocumentSignature(doc types.SsiMsg, docProof *types.DocumentProof, priva
}
case types.BJJSignature2021:
var docBytes []byte
docBytes, err := ldcontext.BJJSignature2021Normalize(doc)
docBytes, err := ldcontext.BJJSignature2021Normalize(doc, docProof)
if err != nil {
return "", err
}
Expand Down
97 changes: 97 additions & 0 deletions x/ssi/ld-context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const X25519KeyAgreementKeyEIP5630Context string = "https://raw.githubuserconten
const CredentialStatusContext string = "https://raw.githubusercontent.com/hypersign-protocol/hypersign-contexts/main/CredentialStatus.jsonld"
const CredentialSchemaContext string = "https://raw.githubusercontent.com/hypersign-protocol/hypersign-contexts/main/CredentialSchema.jsonld"
const BabyJubJubKey2021Context string = "https://raw.githubusercontent.com/hypersign-protocol/hypersign-contexts/main/BabyJubJubKey2021.jsonld"
const BJJSignature2021Context string = "https://raw.githubusercontent.com/hypersign-protocol/hypersign-contexts/main/BJJSignature2021.jsonld"

// As hid-node is not supposed to perform any GET request, the complete Context body of their
// respective Context urls has been maintained below.
Expand Down Expand Up @@ -745,4 +746,100 @@ var ContextUrlMap map[string]contextObject = map[string]contextObject{
},
},
},

BJJSignature2021Context: {
"@version": 1.1,
"id": "@id",
"type": "@type",
"proof": map[string]interface{}{
"@id": "https://w3id.org/security#proof",
"@type": "@id",
"@container": "@graph",
},
"BJJSignature2021": map[string]interface{}{
"@id": "https://w3id.org/security#BJJSignature2021",
"@context": map[string]interface{}{
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"challenge": "https://w3id.org/security#challenge",
"created": map[string]interface{}{
"@id": "http://purl.org/dc/terms/created",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
},
"domain": "https://w3id.org/security#domain",
"proofValue": "https://w3id.org/security#proofValue",
"credentialRoot": "https://w3id.org/security#credentialRoot",
"nonce": "https://w3id.org/security#nonce",
"proofPurpose": map[string]interface{}{
"@id": "https://w3id.org/security#proofPurpose",
"@type": "@vocab",
"@context": map[string]interface{}{
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"assertionMethod": map[string]interface{}{
"@id": "https://w3id.org/security#assertionMethod",
"@type": "@id",
"@container": "@set",
},
"authentication": map[string]interface{}{
"@id": "https://w3id.org/security#authenticationMethod",
"@type": "@id",
"@container": "@set",
},
},
},
"verificationMethod": map[string]interface{}{
"@id": "https://w3id.org/security#verificationMethod",
"@type": "@id",
},
},
},
"BabyJubJubSignatureProof2021": map[string]interface{}{
"@id": "https://w3id.org/security#BabyJubJubSignatureProof2021",
"@context": map[string]interface{}{
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"challenge": "https://w3id.org/security#challenge",
"created": map[string]interface{}{
"@id": "http://purl.org/dc/terms/created",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
},
"domain": "https://w3id.org/security#domain",
"nonce": "https://w3id.org/security#nonce",
"proofPurpose": map[string]interface{}{
"@id": "https://w3id.org/security#proofPurpose",
"@type": "@vocab",
"@context": map[string]interface{}{
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"sec": "https://w3id.org/security#",
"assertionMethod": map[string]interface{}{
"@id": "https://w3id.org/security#assertionMethod",
"@type": "@id",
"@container": "@set",
},
"authentication": map[string]interface{}{
"@id": "https://w3id.org/security#authenticationMethod",
"@type": "@id",
"@container": "@set",
},
},
},
"proofValue": "https://w3id.org/security#proofValue",
"credentialRoot": "https://w3id.org/security#credentialRoot",
"verificationMethod": map[string]interface{}{
"@id": "https://w3id.org/security#verificationMethod",
"@type": "@id",
},
},
},
},
}
10 changes: 6 additions & 4 deletions x/ssi/ld-context/cryptosuite.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,23 +129,25 @@ func EcdsaSecp256k1Signature2019Normalize(ssiMsg types.SsiMsg, docProof *types.D

// BJJSignature2021Normalize performs canonization of SSI documents
// based on the spec: https://iden3-communication.io/BJJSignature2021/
func BJJSignature2021Normalize(ssiMsg types.SsiMsg) ([]byte, error) {
func BJJSignature2021Normalize(ssiMsg types.SsiMsg, docProof *types.DocumentProof) ([]byte, error) {
var jsonLDString string
switch doc := ssiMsg.(type) {
case *types.DidDocument:
jsonLDBytes, err := json.Marshal(NewJsonLdDidDocumentWithoutVM(doc))
jsonLDBytes, err := json.Marshal(NewJsonLdDidDocumentWithoutVM(doc, docProof))
if err != nil {
return nil, err
}
jsonLDString = string(jsonLDBytes)
case *types.CredentialSchemaDocument:
jsonLDBytes, err := json.Marshal(NewJsonLdCredentialSchema(doc))
credentialSchemaDocument := NewJsonLdCredentialSchemaBJJ(doc, docProof)
jsonLDBytes, err := json.Marshal(credentialSchemaDocument)
if err != nil {
return nil, err
}
jsonLDString = string(jsonLDBytes)
case *types.CredentialStatusDocument:
jsonLDBytes, err := json.Marshal(NewJsonLdCredentialStatus(doc))
credentialStatusDocument := NewJsonLdCredentialStatusBJJ(doc, docProof)
jsonLDBytes, err := json.Marshal(credentialStatusDocument)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion x/ssi/ld-context/normalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func NormalizeByProofType(ssiMsg types.SsiMsg, didDocumentProof *types.DocumentP
}
return msgBytes, nil
case types.BJJSignature2021:
msgBytes, err := BJJSignature2021Normalize(ssiMsg)
msgBytes, err := BJJSignature2021Normalize(ssiMsg, didDocumentProof)
if err != nil {
return nil, err
}
Expand Down
101 changes: 100 additions & 1 deletion x/ssi/ld-context/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,22 @@ func (doc *JsonLdCredentialStatus) GetContext() []contextObject {
return doc.Context
}

type JsonLdCredentialStatusBJJ struct {
Context []contextObject `json:"@context,omitempty"`
Id string `json:"id,omitempty"`
Revoked bool `json:"revoked,omitempty"`
Suspended bool `json:"suspended,omitempty"`
Remarks string `json:"remarks,omitempty"`
Issuer string `json:"issuer,omitempty"`
IssuanceDate string `json:"issuanceDate,omitempty"`
CredentialMerkleRootHash string `json:"credentialMerkleRootHash,omitempty"`
Proof JsonLdDocumentProof `json:"proof,omitempty"`
}

func (doc *JsonLdCredentialStatusBJJ) GetContext() []contextObject {
return doc.Context
}

// NewJsonLdCredentialStatus returns a new JsonLdCredentialStatus struct from input Credential Status
func NewJsonLdCredentialStatus(credStatusDoc *types.CredentialStatusDocument) *JsonLdCredentialStatus {
if len(credStatusDoc.Context) == 0 {
Expand Down Expand Up @@ -108,6 +124,37 @@ func NewJsonLdCredentialStatus(credStatusDoc *types.CredentialStatusDocument) *J
return jsonLdCredentialStatus
}

func NewJsonLdCredentialStatusBJJ(credStatusDoc *types.CredentialStatusDocument, docProof *types.DocumentProof) *JsonLdCredentialStatusBJJ {
if len(credStatusDoc.Context) == 0 {
panic("atleast one context url must be provided in the Credential Status Document for Canonization")
}

var jsonLdCredentialStatus *JsonLdCredentialStatusBJJ = &JsonLdCredentialStatusBJJ{}

for _, url := range credStatusDoc.Context {
contextObj, ok := ContextUrlMap[url]
if !ok {
panic(fmt.Sprintf("invalid or unsupported context url: %v", url))
}
jsonLdCredentialStatus.Context = append(jsonLdCredentialStatus.Context, contextObj)
}

jsonLdCredentialStatus.Id = credStatusDoc.Id
jsonLdCredentialStatus.Revoked = credStatusDoc.Revoked
jsonLdCredentialStatus.Remarks = credStatusDoc.Remarks
jsonLdCredentialStatus.Suspended = credStatusDoc.Suspended
jsonLdCredentialStatus.Issuer = credStatusDoc.Issuer
jsonLdCredentialStatus.IssuanceDate = credStatusDoc.IssuanceDate
jsonLdCredentialStatus.CredentialMerkleRootHash = credStatusDoc.CredentialMerkleRootHash

jsonLdCredentialStatus.Proof.Type = docProof.Type
jsonLdCredentialStatus.Proof.Created = docProof.Created
jsonLdCredentialStatus.Proof.ProofPurpose = docProof.ProofPurpose
jsonLdCredentialStatus.Proof.VerificationMethod = docProof.VerificationMethod

return jsonLdCredentialStatus
}

// Document Proof

type JsonLdDocumentProof struct {
Expand Down Expand Up @@ -163,6 +210,22 @@ func (doc *JsonLdCredentialSchema) GetContext() []contextObject {
return doc.Context
}

type JsonLdCredentialSchemaBJJ struct {
Context []contextObject `json:"@context,omitempty"`
Type string `json:"type,omitempty"`
ModelVersion string `json:"modelVersion,omitempty"`
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Author string `json:"author,omitempty"`
Authored string `json:"authored,omitempty"`
Schema *types.CredentialSchemaProperty `json:"schema,omitempty"`
Proof JsonLdDocumentProof `json:"proof,omitempty"`
}

func (doc *JsonLdCredentialSchemaBJJ) GetContext() []contextObject {
return doc.Context
}

func NewJsonLdCredentialSchema(credSchema *types.CredentialSchemaDocument) *JsonLdCredentialSchema {
if len(credSchema.Context) == 0 {
panic("atleast one context url must be provided for DID Document for Canonization")
Expand All @@ -189,6 +252,37 @@ func NewJsonLdCredentialSchema(credSchema *types.CredentialSchemaDocument) *Json
return jsonLdDoc
}

func NewJsonLdCredentialSchemaBJJ(credSchema *types.CredentialSchemaDocument, docProof *types.DocumentProof) *JsonLdCredentialSchemaBJJ {
if len(credSchema.Context) == 0 {
panic("atleast one context url must be provided for DID Document for Canonization")
}

var jsonLdDoc *JsonLdCredentialSchemaBJJ = &JsonLdCredentialSchemaBJJ{}

for _, url := range credSchema.Context {
contextObj, ok := ContextUrlMap[url]
if !ok {
panic(fmt.Sprintf("invalid or unsupported context url: %v", url))
}
jsonLdDoc.Context = append(jsonLdDoc.Context, contextObj)
}

jsonLdDoc.Type = credSchema.Type
jsonLdDoc.ModelVersion = credSchema.ModelVersion
jsonLdDoc.Id = credSchema.Id
jsonLdDoc.Name = credSchema.Name
jsonLdDoc.Author = credSchema.Author
jsonLdDoc.Authored = credSchema.Authored
jsonLdDoc.Schema = credSchema.Schema

jsonLdDoc.Proof.Type = docProof.Type
jsonLdDoc.Proof.Created = docProof.Created
jsonLdDoc.Proof.ProofPurpose = docProof.ProofPurpose
jsonLdDoc.Proof.VerificationMethod = docProof.VerificationMethod

return jsonLdDoc
}

// It is a similar to `Did` struct, with the exception that the `context` attribute is of type
// `contextObject` instead of `[]string`, which is meant for accomodating Context JSON body
// having arbritrary attributes. It should be used for performing Canonization.
Expand All @@ -199,14 +293,15 @@ type JsonLdDidDocumentWithoutVM struct {
AlsoKnownAs []string `json:"alsoKnownAs,omitempty"`
Authentication []verificationMethodWithoutController `json:"authentication,omitempty"`
AssertionMethod []verificationMethodWithoutController `json:"assertionMethod,omitempty"`
Proof JsonLdDocumentProof `json:"proof,omitempty"`
}

func (doc *JsonLdDidDocumentWithoutVM) GetContext() []contextObject {
return doc.Context
}

// NewJsonLdDidDocument returns a new JsonLdDid struct from input Did
func NewJsonLdDidDocumentWithoutVM(didDoc *types.DidDocument) *JsonLdDidDocumentWithoutVM {
func NewJsonLdDidDocumentWithoutVM(didDoc *types.DidDocument, docProof *types.DocumentProof) *JsonLdDidDocumentWithoutVM {
if len(didDoc.Context) == 0 {
panic("atleast one context url must be provided for DID Document for Canonization")
}
Expand Down Expand Up @@ -252,6 +347,10 @@ func NewJsonLdDidDocumentWithoutVM(didDoc *types.DidDocument) *JsonLdDidDocument
}
}

jsonLdDoc.Proof.Type = docProof.Type
jsonLdDoc.Proof.Created = docProof.Created
jsonLdDoc.Proof.ProofPurpose = docProof.ProofPurpose
jsonLdDoc.Proof.VerificationMethod = docProof.VerificationMethod + docProof.ProofPurpose
return jsonLdDoc
}

Expand Down
4 changes: 2 additions & 2 deletions x/ssi/tests/crypto/signature.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package crypto

import (
ldcontext "github.com/hypersign-protocol/hid-node/x/ssi/ld-context"
cli "github.com/hypersign-protocol/hid-node/x/ssi/client/cli"
ldcontext "github.com/hypersign-protocol/hid-node/x/ssi/ld-context"
"github.com/hypersign-protocol/hid-node/x/ssi/types"
)

Expand Down Expand Up @@ -70,7 +70,7 @@ func GetDocumentSignature(doc types.SsiMsg, docProof *types.DocumentProof, priva
}
case types.BJJSignature2021:
var docBytes []byte
docBytes, err := ldcontext.BJJSignature2021Normalize(doc)
docBytes, err := ldcontext.BJJSignature2021Normalize(doc, docProof)
if err != nil {
return "", err
}
Expand Down
6 changes: 3 additions & 3 deletions x/ssi/tests/ssi/credential_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ import (

func GenerateSchema(keyPair testcrypto.IKeyPair, authorId string) *types.CredentialSchemaDocument {
var schemaId = "sch:" + testconstants.DidMethod + ":" + testconstants.ChainNamespace + ":" + strings.Split(authorId, ":")[3] + ":" + "1.0"
var vmContextUrl = GetContextFromKeyPair(keyPair)
var vmContextUrls = GetContextFromKeyPair(keyPair)

var credentialSchema *types.CredentialSchemaDocument = &types.CredentialSchemaDocument{
Context: []string{
Context: []string{
ldcontext.CredentialSchemaContext,
vmContextUrl,
},
Type: "https://w3c-ccg.github.io/vc-json-schemas/v1/schema/1.0/schema.json",
ModelVersion: "1.0",
Expand All @@ -34,6 +33,7 @@ func GenerateSchema(keyPair testcrypto.IKeyPair, authorId string) *types.Credent
AdditionalProperties: false,
},
}
credentialSchema.Context = append(credentialSchema.Context, vmContextUrls...)

return credentialSchema
}
Expand Down
4 changes: 2 additions & 2 deletions x/ssi/tests/ssi/credential_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ import (
func GenerateCredentialStatus(keyPair testcrypto.IKeyPair, issuerId string) *types.CredentialStatusDocument {
var credentialId = "vc:" + testconstants.DidMethod + ":" + testconstants.ChainNamespace + ":" + strings.Split(issuerId, ":")[3]
var credHash = sha256.Sum256([]byte("Hash1234"))
var vmContextUrl = GetContextFromKeyPair(keyPair)
var vmContextUrls = GetContextFromKeyPair(keyPair)

var credentialStatus *types.CredentialStatusDocument = &types.CredentialStatusDocument{
Context: []string{
ldcontext.CredentialStatusContext,
vmContextUrl,
},
Id: credentialId,
Remarks: "Live",
Expand All @@ -29,6 +28,7 @@ func GenerateCredentialStatus(keyPair testcrypto.IKeyPair, issuerId string) *typ
IssuanceDate: "2022-04-10T04:07:12Z",
CredentialMerkleRootHash: hex.EncodeToString(credHash[:]),
}
credentialStatus.Context = append(credentialStatus.Context, vmContextUrls...)
return credentialStatus
}

Expand Down
Loading
Loading