-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
design: Added initial versions for spec and API documents
Signed-off-by: artem.ivanov <[email protected]>
- Loading branch information
1 parent
d87d60a
commit 60d5079
Showing
4 changed files
with
1,048 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
{ | ||
"@context": { | ||
"@version": 1.1, | ||
"@protected": true, | ||
"ac": "https://anoncreds.example/2022/ns#", | ||
"xsd": "http://www.w3.org/2001/XMLSchema#", | ||
|
||
"AnonCredsCredential": "ac:AnonCredsCredential", | ||
|
||
"AnonCredsDefinition": { | ||
"@id": "ac:AnonCredsDefinition", | ||
"@context": { | ||
"@version": 1.1, | ||
"@protected": true, | ||
"definition": { | ||
"@id": "ac:definition", | ||
"@type": "@id" | ||
}, | ||
"schema": { | ||
"@id": "ac:schema", | ||
"@type": "@id" | ||
}, | ||
"revocation": { | ||
"@id": "ac:revocation", | ||
"@type": "@id" | ||
}, | ||
"encoding": { | ||
"@id": "ac:attributeEncoding", | ||
"@type": "@vocab", | ||
"@context": { | ||
"@version": 1.1, | ||
"@protected": true, | ||
"auto": "ac:autoEncoding" | ||
} | ||
} | ||
} | ||
}, | ||
|
||
"AnonCredsPresentation": "ac:AnonCredsPresentation", | ||
|
||
"AnonCredsPresentationProof2022": { | ||
"@id": "ac:AnonCredsPresentationProof2022", | ||
"@context": { | ||
"@version": 1.1, | ||
"@protected": true, | ||
"credential": { | ||
"@id": "ac:credentialProof", | ||
"@context": { | ||
"@version": 1.1, | ||
"@protected": true, | ||
"mapping": { | ||
"@id": "ac:attributeMapping", | ||
"@type": "@json" | ||
}, | ||
"proofValue": { | ||
"@id": "ac:proofValue", | ||
"@type": "xsd:string" | ||
} | ||
} | ||
}, | ||
"proofValue": { | ||
"@id": "ac:proofValue", | ||
"@type": "xsd:string" | ||
}, | ||
"challenge": { | ||
"@id": "ac:challenge", | ||
"@type": "xsd:string" | ||
} | ||
} | ||
}, | ||
|
||
"CLSignature2023": { | ||
"@id": "ac:CLSignature2023", | ||
"@context": { | ||
"@version": 1.1, | ||
"@protected": true, | ||
"signature": { | ||
"@id": "ac:signature", | ||
"@type": "xsd:string" | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
### Encoding | ||
|
||
As all fields of AnonCreds credential signature and proof objects are big numbers, the straight object JSON serialization and representing as bytes is not effective. | ||
Instead, we propose using of an alternative algorithm, providing more compact representation, consisting of the following steps: | ||
|
||
Also, due to the fact that fields order matters during serialization/deserialization process, encoding must be applied to attributes in alphabetic order. | ||
|
||
> TO DISCUSS: For simplicity we still can use straight object JSON serialization and representing as bytes but the size of encoded string will be almost 3 times bigger. | ||
##### Encoding steps | ||
|
||
1. Iterate over object `attributes` | ||
2. Get **size** (`number bytes`) required for each attribute value (`BigNumber`) and **value as bytes** (big-endian) | ||
3. Append `number bytes` (reserve 2 bytes for it) and `value as bytes` to resulting array | ||
4. After adding all attributes encode the resulting bytes array as base64 string | ||
|
||
**Value encoding rules:** | ||
* BigNumber: get value size and bytes | ||
* Nested object: apply the same steps to encode itself as bytes | ||
* Array: get count of elements and encode each element | ||
* Optional values: use zero as size and empty array for value | ||
* Map<String, BigNumber>: encode key and value as usual | ||
|
||
##### Decoding steps | ||
|
||
1. Read 2 bytes corresponding to the attribute value size | ||
2. Read next N bytes corresponding to the value size | ||
3. Restore value from bytes | ||
4. Repeat the process for the tail | ||
|
||
#### Credential Signature encoding | ||
|
||
Fields order: | ||
* `Signature: `[signature, signature_correctness_proof] | ||
* `CredentialSignature: `[a, e, m_2, v]` | ||
* `SignatureCorrectnessProof: `[c, se]` | ||
|
||
```rust | ||
/// Need to construct an object containing CredentialSignature and SignatureCorrectnessProof | ||
struct Signature { | ||
signature: CredentialSignature, | ||
signature_correctness_proof: SignatureCorrectnessProof, | ||
} | ||
|
||
/// Encoding fields order: [signature, signature_correctness_proof] | ||
impl Signature { | ||
fn to_bytes(&self) -> Vec<u8> { | ||
let (signature_size, signature_bytes) = self.signature.get_size_and_bytes(); | ||
let (signature_correctness_proof_size, signature_correctness_proof_bytes) = self.signature_correctness_proof.get_size_and_bytes(); | ||
vec![ | ||
..signature_size, | ||
..signature_bytes, | ||
..signature_correctness_proof_size, | ||
..signature_correctness_proof_bytes, | ||
] | ||
} | ||
|
||
fn from_bytes(bytes: &[u8]) -> SignatureCorrectnessProof { | ||
// set start and end | ||
let signature: CredentialSignature = CredentialSignature::from_bytes(&bytes[start..end]); | ||
// change start and end | ||
let signature_correctness_proof: SignatureCorrectnessProof = SignatureCorrectnessProof::from_bytes(&bytes[start..end]); | ||
Signature { | ||
signature, | ||
signature_correctness_proof, | ||
} | ||
} | ||
} | ||
|
||
/// Similar implementation for `CredentialSignature` and `SignatureCorrectnessProof` objects | ||
``` | ||
|
||
#### Presentation Proof encoding | ||
|
||
Fields coder: | ||
* `SubProof: `[non_revoc_proof, primary_proof] | ||
* `PrimaryProof: `[eq_proof, ge_proofs]` | ||
* because `ge_proofs` is an array we need to append elements count into the resulting array | ||
* `NonRevocProof: `[c_list, x_list]` | ||
|
||
```rust | ||
/// Need to construct an object containing CredentialSignature and SignatureCorrectnessProof | ||
struct SubProof { | ||
primary_proof: PrimaryProof, | ||
non_revoc_proof: Option<NonRevocProof>, | ||
} | ||
|
||
/// Encoding fields order: [non_revoc_proof, primary_proof] | ||
impl SubProof { | ||
fn to_bytes(&self) -> Vec<u8> { | ||
// use `0` for `non_revoc_proof_size` and empty array for `non_revoc_proof_bytes` (all Optional fields) | ||
let (non_revoc_proof_size, non_revoc_proof_bytes) = self.non_revoc_proof.get_size_and_bytes(); | ||
let (primary_proof_size, non_revoc_proof_bytes) = self.non_revoc_proof.get_size_and_bytes(); | ||
vec![ | ||
..non_revoc_proof_size, | ||
..non_revoc_proof_bytes, | ||
..primary_proof_size, | ||
..non_revoc_proof_bytes, | ||
] | ||
} | ||
|
||
fn from_bytes(bytes: &[u8]) -> SignatureCorrectnessProof { | ||
// set start and end | ||
let non_revoc_proof: NonRevocProof = NonRevocProof::from_bytes(&bytes[start..end]); | ||
// change start and end | ||
let primary_proof: PrimaryProof = PrimaryProof::from_bytes(&bytes[start..end]); | ||
SubProof { | ||
non_revoc_proof, | ||
primary_proof, | ||
} | ||
} | ||
} | ||
``` |
Oops, something went wrong.