diff --git a/json-ld/parser.go b/json-ld/parser.go index ac70cef..e3d2828 100644 --- a/json-ld/parser.go +++ b/json-ld/parser.go @@ -3,12 +3,13 @@ package jsonld import ( "encoding/json" "fmt" + "sort" + core "github.com/iden3/go-iden3-core" "github.com/iden3/go-schema-processor/processor" "github.com/iden3/go-schema-processor/utils" "github.com/iden3/go-schema-processor/verifiable" "github.com/pkg/errors" - "sort" ) // Parser can parse claim data according to specification @@ -97,11 +98,6 @@ func (p Parser) ParseClaim(credential *verifiable.Iden3Credential, schemaBytes [ claim.SetIndexID(id) } - err = utils.VerifyClaimHash(credential, claim) - if err != nil { - return nil, err - } - return claim, nil } diff --git a/json/parser.go b/json/parser.go index 86363e1..fc80a67 100644 --- a/json/parser.go +++ b/json/parser.go @@ -3,6 +3,7 @@ package json import ( "encoding/json" "fmt" + core "github.com/iden3/go-iden3-core" "github.com/iden3/go-schema-processor/processor" "github.com/iden3/go-schema-processor/utils" @@ -66,11 +67,6 @@ func (s Parser) ParseClaim(credential *verifiable.Iden3Credential, schemaBytes [ claim.SetIndexID(id) } - err = utils.VerifyClaimHash(credential, claim) - if err != nil { - return nil, err - } - return claim, nil } diff --git a/processor/json-ld/processor_ipfs_test.go b/processor/json-ld/processor_ipfs_test.go index f194931..15401d3 100644 --- a/processor/json-ld/processor_ipfs_test.go +++ b/processor/json-ld/processor_ipfs_test.go @@ -3,7 +3,6 @@ package jsonld import ( "context" commonJSON "encoding/json" - schemaUtils "github.com/iden3/go-schema-processor/utils" "math/big" "os" "testing" @@ -350,7 +349,4 @@ func TestParserParseClaimWithSubjectIDPFSLoader(t *testing.T) { updatable := coreClaim.GetFlagUpdatable() assert.Equal(t, vc.Updatable, updatable) - - err = schemaUtils.VerifyClaimHash(&vc, coreClaim) - assert.Nil(t, err) } diff --git a/processor/json-ld/processor_test.go b/processor/json-ld/processor_test.go index ae734a4..b96c886 100644 --- a/processor/json-ld/processor_test.go +++ b/processor/json-ld/processor_test.go @@ -11,7 +11,6 @@ import ( jsonld "github.com/iden3/go-schema-processor/json-ld" "github.com/iden3/go-schema-processor/loaders" "github.com/iden3/go-schema-processor/processor" - schemaUtils "github.com/iden3/go-schema-processor/utils" "github.com/iden3/go-schema-processor/verifiable" "github.com/stretchr/testify/assert" ) @@ -335,14 +334,89 @@ func TestParserParseClaimWithoutSubjectID(t *testing.T) { updatable := coreClaim.GetFlagUpdatable() assert.Equal(t, vc.Updatable, updatable) - - err = schemaUtils.VerifyClaimHash(&vc, coreClaim) - assert.Nil(t, err) - } func TestParserParseClaimWithSubjectID(t *testing.T) { - jsonLDDocument := `{"id":"4102dcf4-9382-443a-8108-959e631b5d2f","@context":["https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/iden3credential.json-ld","https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v2.json-ld"],"@type":["Iden3Credential"],"expiration":"2361-03-21T21:14:48+02:00","updatable":false,"version":0,"rev_nonce":2761125786,"credentialSubject":{"birthday":19960424,"documentType":1,"id":"118akjaAsZ2i3bSSYEaM88mCMpXAcL6WvpZH68fKZn","type":"KYCAgeCredential"},"credentialStatus":{"id":"http://localhost:8001/api/v1/identities/1129q213BgoVEnnvUGB4TsmNuScS1icbiN2C1RBpPF/claims/revocation/status/2761125786","type":"SparseMerkleTreeProof"},"credentialSchema":{"@id":"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v2.json-ld","type":"KYCAgeCredential"},"proof":[{"@type":"BJJSignature2021","issuer":"1129q213BgoVEnnvUGB4TsmNuScS1icbiN2C1RBpPF","h_index":"2c3a63fb838bbc1809c1e80a19139019fe37b24b1623ce2daba44183872cc41d","h_value":"463b48e77f0661d31a56f61681c97b6223b1412505e3b04c7a4e0b08f3181819","created":1650898533,"issuer_mtp":{"@type":"Iden3SparseMerkleProof","issuer":"1129q213BgoVEnnvUGB4TsmNuScS1icbiN2C1RBpPF","h_index":"b530c7ed22879305e899914ba8a378c713bd023144cb79808a1d2adf4947a517","h_value":"46993eb76d20c1880406798b1b9237092515c2d9949620510ec7196e43fd3205","state":{"claims_tree_root":"f93fd2d63e1961711b996de149efe0a5297e8651203eb42f6a90245e82fa9500","value":"a4b6b022a2b95f34ad63b4ef589ea60282af283e833f26a456588e9b563b1e1e","status":"created"},"mtp":{"existence":true,"siblings":[]}},"verification_method":"93f822075aefe096f69a66e1623bdbf907230c49950ef41738c00f6b91682425","proof_value":"842a7044245669d898bb42106573469fa3e56805eaeab78cbd06ecda0cd82490a1c03d3438705a764b5cef11d764c16d17dd86d9463966c703286ccb80139d00","proof_purpose":"Authentication"},{"@type":"Iden3SparseMerkleProof","issuer":"1129q213BgoVEnnvUGB4TsmNuScS1icbiN2C1RBpPF","h_index":"2c3a63fb838bbc1809c1e80a19139019fe37b24b1623ce2daba44183872cc41d","h_value":"463b48e77f0661d31a56f61681c97b6223b1412505e3b04c7a4e0b08f3181819","state":{"tx_id":"0x7482579da9942ce9c218174fb509ab15fa9f94e70cb29d63cb7072b306b3b866","block_timestamp":1650900717,"block_number":26082637,"root_of_roots":"ffa2d0eec32ee4588b5fdac7aaa2d136d5d3ab96bb25d8507570a391dfd14922","claims_tree_root":"682409da4fdaf072f30314e0578848662975d2d3aa967a46b0b678745368e12b","revocation_tree_root":"0000000000000000000000000000000000000000000000000000000000000000","value":"0d3a999d58f26f1ccc21bbe745ee9d62efdc618613caf930009c533e2e56831f","status":"confirmed"},"mtp":{"existence":true,"siblings":["264989163946140659119067438613111086251856808194270247179339188846199980025","0","0","412703772382477972262931479259998079304255691105270144442886052862988158651"]}}]}` + jsonLDDocument := `{ + "id": "4102dcf4-9382-443a-8108-959e631b5d2f", + "@context": [ + "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/iden3credential.json-ld", + "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v2.json-ld" + ], + "@type": [ + "Iden3Credential" + ], + "expiration": "2361-03-21T21:14:48+02:00", + "updatable": false, + "version": 0, + "rev_nonce": 2761125786, + "credentialSubject": { + "birthday": 19960424, + "documentType": 1, + "id": "118akjaAsZ2i3bSSYEaM88mCMpXAcL6WvpZH68fKZn", + "type": "KYCAgeCredential" + }, + "credentialStatus": { + "id": "http://localhost:8001/api/v1/identities/1129q213BgoVEnnvUGB4TsmNuScS1icbiN2C1RBpPF/claims/revocation/status/2761125786", + "type": "SparseMerkleTreeProof" + }, + "credentialSchema": { + "@id": "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v2.json-ld", + "type": "KYCAgeCredential" + }, + "proof": [ + { + "@type": "BJJSignature2021", + "issuer": "1129q213BgoVEnnvUGB4TsmNuScS1icbiN2C1RBpPF", + "h_index": "2c3a63fb838bbc1809c1e80a19139019fe37b24b1623ce2daba44183872cc41d", + "h_value": "463b48e77f0661d31a56f61681c97b6223b1412505e3b04c7a4e0b08f3181819", + "created": 1650898533, + "issuer_mtp": { + "@type": "Iden3SparseMerkleProof", + "issuer": "1129q213BgoVEnnvUGB4TsmNuScS1icbiN2C1RBpPF", + "h_index": "b530c7ed22879305e899914ba8a378c713bd023144cb79808a1d2adf4947a517", + "h_value": "46993eb76d20c1880406798b1b9237092515c2d9949620510ec7196e43fd3205", + "state": { + "claims_tree_root": "f93fd2d63e1961711b996de149efe0a5297e8651203eb42f6a90245e82fa9500", + "value": "a4b6b022a2b95f34ad63b4ef589ea60282af283e833f26a456588e9b563b1e1e", + "status": "created" + }, + "mtp": { + "existence": true, + "siblings": [] + } + }, + "verification_method": "93f822075aefe096f69a66e1623bdbf907230c49950ef41738c00f6b91682425", + "proof_value": "842a7044245669d898bb42106573469fa3e56805eaeab78cbd06ecda0cd82490a1c03d3438705a764b5cef11d764c16d17dd86d9463966c703286ccb80139d00", + "proof_purpose": "Authentication" + }, + { + "@type": "Iden3SparseMerkleProof", + "issuer": "1129q213BgoVEnnvUGB4TsmNuScS1icbiN2C1RBpPF", + "h_index": "2c3a63fb838bbc1809c1e80a19139019fe37b24b1623ce2daba44183872cc41d", + "h_value": "463b48e77f0661d31a56f61681c97b6223b1412505e3b04c7a4e0b08f3181819", + "state": { + "tx_id": "0x7482579da9942ce9c218174fb509ab15fa9f94e70cb29d63cb7072b306b3b866", + "block_timestamp": 1650900717, + "block_number": 26082637, + "root_of_roots": "ffa2d0eec32ee4588b5fdac7aaa2d136d5d3ab96bb25d8507570a391dfd14922", + "claims_tree_root": "682409da4fdaf072f30314e0578848662975d2d3aa967a46b0b678745368e12b", + "revocation_tree_root": "0000000000000000000000000000000000000000000000000000000000000000", + "value": "0d3a999d58f26f1ccc21bbe745ee9d62efdc618613caf930009c533e2e56831f", + "status": "confirmed" + }, + "mtp": { + "existence": true, + "siblings": [ + "264989163946140659119067438613111086251856808194270247179339188846199980025", + "0", + "0", + "412703772382477972262931479259998079304255691105270144442886052862988158651" + ] + } + } + ] +}` var vc verifiable.Iden3Credential err := commonJSON.Unmarshal([]byte(jsonLDDocument), &vc) @@ -365,7 +439,4 @@ func TestParserParseClaimWithSubjectID(t *testing.T) { id, err := coreClaim.GetID() assert.Nil(t, err) assert.Equal(t, subjectID, id.String()) - - err = schemaUtils.VerifyClaimHash(&vc, coreClaim) - assert.Nil(t, err) } diff --git a/utils/claims.go b/utils/claims.go index 3afb86e..e1b6c1b 100644 --- a/utils/claims.go +++ b/utils/claims.go @@ -7,9 +7,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" core "github.com/iden3/go-iden3-core" - "github.com/iden3/go-merkletree-sql" "github.com/iden3/go-schema-processor/processor" - "github.com/iden3/go-schema-processor/verifiable" "github.com/pkg/errors" ) @@ -62,9 +60,6 @@ func CheckDataInField(data []byte) bool { return a.Cmp(q) == -1 } -var errIndexHashNotEqual = errors.New("claim index hash in credential and in resulted claim are not equal") -var errValueHashNotEqual = errors.New("claim value hash in credential and in resulted claim are not equal") - // FillClaimSlots fullfils index and value fields to iden3 slots func FillClaimSlots(content []byte, indexFields, valueFields []string) (processor.ParsedSlots, error) { @@ -158,71 +153,3 @@ func CreateSchemaHash(schemaBytes []byte, copy(sHash[:], h[len(h)-16:]) return sHash } - -// VerifyClaimHash verifies that hashes of index and value of claim are equal to proof in credential -func VerifyClaimHash(credential *verifiable.Iden3Credential, - claim *core.Claim) error { - - hi, hv, err := claim.HiHv() - if err != nil { - return err - } - switch proof := credential.Proof.(type) { - case []interface{}: - for _, p := range proof { - var basicProof verifiable.BasicProof - proofBytes, err := json.Marshal(p) - if err != nil { - return err - } - err = json.Unmarshal(proofBytes, &basicProof) - if err != nil { - return err - } - indexHash, err := merkletree.NewHashFromBigInt(hi) - if err != nil { - return err - } - if basicProof.HIndex != indexHash.Hex() { - return errIndexHashNotEqual - } - valueHash, err := merkletree.NewHashFromBigInt(hv) - if err != nil { - return err - } - if basicProof.HValue != valueHash.Hex() { - return errValueHashNotEqual - } - } - case interface{}: - var basicProof verifiable.BasicProof - proofBytes, err := json.Marshal(proof) - if err != nil { - return err - } - err = json.Unmarshal(proofBytes, &basicProof) - if err != nil { - return err - } - - indexHash, err := merkletree.NewHashFromBigInt(hi) - if err != nil { - return err - } - if basicProof.HIndex != indexHash.Hex() { - return errIndexHashNotEqual - } - valueHash, err := merkletree.NewHashFromBigInt(hv) - if err != nil { - return err - } - if basicProof.HValue != valueHash.Hex() { - return errValueHashNotEqual - } - default: - return errors.New("proof can't be parsed") - } - - return nil - -} diff --git a/verifiable/credential.go b/verifiable/credential.go index 2c4d565..8d3bbc0 100644 --- a/verifiable/credential.go +++ b/verifiable/credential.go @@ -2,6 +2,8 @@ package verifiable import ( "time" + + mt "github.com/iden3/go-merkletree-sql" ) // Iden3Credential is struct that represents claim json-ld document @@ -41,10 +43,10 @@ const JSONSchemaValidator2018 = "JsonSchemaValidator2018" // RevocationStatus status of revocation nonce. Info required to check revocation state of claim in circuits type RevocationStatus struct { Issuer struct { - State *string `json:"state"` + State *string `json:"state,omitempty"` RootOfRoots *string `json:"root_of_roots,omitempty"` ClaimsTreeRoot *string `json:"claims_tree_root,omitempty"` RevocationTreeRoot *string `json:"revocation_tree_root,omitempty"` } `json:"issuer"` - MTP `json:"mtp"` + MTP mt.Proof `json:"mtp"` } diff --git a/verifiable/proof.go b/verifiable/proof.go index 91ced39..e769e29 100644 --- a/verifiable/proof.go +++ b/verifiable/proof.go @@ -1,66 +1,56 @@ package verifiable import ( - mt "github.com/iden3/go-merkletree-sql" "math/big" + + core "github.com/iden3/go-iden3-core" + mt "github.com/iden3/go-merkletree-sql" ) -// MTPProof JSON-LD merkle tree proof -type MTPProof struct { - BasicProof - State struct { - TxID *string `json:"tx_id,omitempty"` - BlockTimestamp *int `json:"block_timestamp,omitempty"` - BlockNumber *int `json:"block_number,omitempty"` - RootOfRoots *string `json:"root_of_roots,omitempty"` - ClaimsTreeRoot *string `json:"claims_tree_root,omitempty"` - RevocationTreeRoot *string `json:"revocation_tree_root,omitempty"` - Value *string `json:"value,omitempty"` - Status string `json:"status,omitempty"` - } `json:"state"` - - Mtp MTP `json:"mtp"` +// IssuerData is the data that is used to create a proof +type IssuerData struct { + ID *core.ID `json:"id,omitempty"` + State State `json:"state,omitempty"` + AuthClaim *core.Claim `json:"auth_claim,omitempty"` + MTP *mt.Proof `json:"mtp,omitempty"` + RevocationStatus string `json:"revocation_status,omitempty"` } -// SignatureProof is proof that contains signature of content -type SignatureProof struct { - BasicProof - - Created int64 `json:"created"` - IssuerMTP MTPProof `json:"issuer_mtp"` - VerificationMethod string `json:"verification_method"` - ProofValue string `json:"proof_value"` - ProofPurpose string `json:"proof_purpose"` +// State represents the state of the issuer +type State struct { + TxID *string `json:"tx_id,omitempty"` + BlockTimestamp *int `json:"block_timestamp,omitempty"` + BlockNumber *int `json:"block_number,omitempty"` + RootOfRoots *string `json:"root_of_roots,omitempty"` + ClaimsTreeRoot *string `json:"claims_tree_root,omitempty"` + RevocationTreeRoot *string `json:"revocation_tree_root,omitempty"` + Value *string `json:"value,omitempty"` + Status string `json:"status,omitempty"` } -// BasicProof is basic proof for Iden3Claim -type BasicProof struct { - Type string `json:"@type"` - Issuer string `json:"issuer"` - HIndex string `json:"h_index"` - HValue string `json:"h_value"` +// BJJSignatureProofType schema type +const BJJSignatureProofType = "BJJSignature2021" + +// BJJSignatureProof2021 JSON-LD BBJJSignatureProof +type BJJSignatureProof2021 struct { + Type string `json:"@type"` + IssuerData IssuerData `json:"issuer_data"` + Signature string `json:"signature"` } -// MTP is merkle tree mtp but in lower case and with type -type MTP struct { - Type string `json:"@type,omitempty"` - Existence bool `json:"existence"` - Siblings []*mt.Hash `json:"siblings"` - NodeAux *struct { - HIndex string `json:"h_index,omitempty"` - HValue string `json:"h_value,omitempty"` - } `json:"node_aux,omitempty"` +// Iden3SparseMerkleProof JSON-LD structure +type Iden3SparseMerkleProof struct { + Type string `json:"@type"` + IssuerData IssuerData `json:"issuer_data"` + MTP *mt.Proof `json:"mtp"` } -// Iden3SparseMerkleProof schema -const Iden3SparseMerkleProof = "Iden3SparseMerkleProof" +// Iden3SparseMerkleProofType schema +const Iden3SparseMerkleProofType = "Iden3SparseMerkleProof" // SparseMerkleProof schema const SparseMerkleProof = "SparseMerkleProof" -// BJJSignatureProof schema -const BJJSignatureProof = "BJJSignature2021" - // ProofPurpose is alias for string, represents proof purpose type ProofPurpose string