Skip to content

Commit

Permalink
Processed review comments + renamed VDR library
Browse files Browse the repository at this point in the history
Signed-off-by: artem.ivanov <[email protected]>
  • Loading branch information
Artemkaaas committed Jan 30, 2024
1 parent dbf6e7c commit 7ea8326
Show file tree
Hide file tree
Showing 49 changed files with 4,711 additions and 272 deletions.
6 changes: 3 additions & 3 deletions docs/design/cl-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ Contract name: **SchemaRegistry**
#### Create a new schema
* Method: `createSchema`
* Description: Transaction to create a new AnonCreds Schema
* Description: Transaction to create a new AnonCreds Schema matching to the [specification](https://hyperledger.github.io/anoncreds-spec/#schema-publisher-publish-schema-object)
* Parameters:
* `identity` - Account address of schema issuer
* `id` - KECCAK256 hash of schema id to be created
* `schema` - AnonCreds schema object as bytes
* `schema` - AnonCreds Schema object as bytes
* Restrictions:
* Schema id must be unique.
* Corresponding issuer account must exist and owned by sender.
Expand Down Expand Up @@ -172,7 +172,7 @@ Contract name: **CredentialDefinitionRegistry**
#### Create a new credential definition
* Method: `createCredentialDefinition`
* Description: Transaction to create a new AnonCreds Credential Definition
* Description: Transaction to create a new AnonCreds Credential Definition matching to the [specification](https://hyperledger.github.io/anoncreds-spec/#generating-a-credential-definition-without-revocation-support)
* Parameters:
* `identity` - Account address of credential definition issuer
* `id` - KECCAK256 hash of credential definition id to be created
Expand Down
176 changes: 34 additions & 142 deletions docs/design/endorsement.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,103 +4,6 @@ Not all identity owners may have permissions for writing transactions on the led
The goal of this document to define a mechanism of doing transaction writes to the ledger by a special parties having an
Endorser role with preserving of original author as an entity owner.

### DID Indy registry

#### Flow

* Author steps:
* Step 1: Prepares a DID Document object
* Step 2: Queries `nonce` from the ledger: `IndyDidRegistry.nonce(identity)`
* Step 3: Execute VDR method to calculate hash need to be signed - contract signed data according
to [EIP](https://eips.ethereum.org/EIPS/eip-191).
```
keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), nonce[identity], identity, "createDid", did, document))
// Arguments when calculating hash to validate
// 1: byte(0x19) - the initial 0x19 byte
// 2: byte(0) - the version byte
// 3: address(this) - the validator address
// 4-8: Application specific data
// nonce - nonce to prevent reply attack
// identity - author account address
// `createDid` original contract method - added to be aligned with did:ethr contract
// did - DID to be created
// document - DID document as JSON string
```
* Step 4: Performs EcDSA signing using his ethereum identity account keys
* Step 5: Passes DID Document and Signature to Endorser
* Endorser steps:
* Step 1: Endorser builds transaction to endorse
DID: `endorseDid(address identity, string did, string document, uint8 sigV, bytes32 sigR, bytes32 sigS)`
> Optionally: `identity` can be derived from DidDocument.id instead of passing explicitly
* Step 2: Endorser does regular EcDSA signing of the **Transaction**
* Step 3: Endorser submit the signed transaction to the ledger which executes deployed `IndyDidRegistry.endorseDid`
contract method
* Ethereum:
* Checks the validity of the transaction level signature (Endorser's signature)
* Contract:
* Step 1: Get current nonce value of identity
* Step 2: Calculate the hash of signed data: same as for Author Step 3
* Step 3: Checks the validity of the provided signature against identity passed as the parameter `ecrecover(...);`
* `ecrecover` returns an account signed the message
#### Contracts
```
mapping(address => uint) public nonce;

// identity - ethereum address of DID owner
// document - did document
// identitySignature - identity owner signatures (EcDSA and optionally ED25519) ower serialized DID Document
function endorseDid(address identity, string calldata did, string calldata document, uint8 sigV, bytes32 sigR, bytes32 sigS) {
// sender is endorser when it's not equal to identity
if (msg.sender == identity) {
revert InvalidmethodExecution;
}

// calculate the hash of DiDocument
// this hash will be checked agains signatures to verify ownership
bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), nonce[identity], identity, "createDid", did, document));

// verify EcDSA identity owner signature ower DID + DidDocument
checkEcDsaSignature(identity, hash, identitySignature);

nonce[identity]++;
record[didDocument.did].didDocument = didDocument
record[didDocument.did].metadata.owner = identity
record[didDocument.did].metadata.sender = msg.sender
}

function checkEcDsaSignature(address identity, bytes32 hash, EcDSASignature signature) {
address signer = ecrecover(hash, signature.v, signature.r, signature.s);
if (signer == address(0)) {
revert InvalidSignature("Invalid signature provided");
}
if (identity != signer) {
revert InvalidSignature("Signature does not match to the target identity");
}
}
```
#### VDR
```rust
// Prepare endorsing bytes which need to be signed by an identity owner
fn prepare_endorse_did_data(
client: &LedgerClient,
identity: &Address,
did_doc: DidDocument
) -> Vec<u8>;
// Build transaction to endorse DID
fn build_endorse_did_transaction(
client: &LedgerClient,
sender: &Address,
identity: &Address,
did_doc: &DidDocument,
signature: &Signature
) -> VdrResult<Transaction> {}
```

### DID Ethr registry

`did:ethr` allows using Ethereum addresses as identifier without prior its registration on the network.
Expand Down Expand Up @@ -133,30 +36,31 @@ TO BE defined later.

**Schema endorsing steps**

Endorsing for schemas and credential definition is designed to match existing `did:ethr` API.

> In case of Schema and Credential Definition we do not need to add `nonce` as we do not have an update operation.
* Author steps:
* Step 1: Author prepares a Schema object
* Step 2: Execute VDR method to calculate hash need to be signed - contract signed data according
to [EIP](https://eips.ethereum.org/EIPS/eip-191).
```
keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, issuerId, schema))
keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, schema))
// Arguments when calculating hash to validate
// 1: byte(0x19) - the initial 0x19 byte
// 2: byte(0) - the version byte
// 3: address(this) - the validator address
// 4-8: Application specific data
// 4-7: Application specific data
// identity - author account address
// `createSchema` original contract method - added to be aligned with did:ethr contract
// id - id of schema to be created
// issuerId - id of schema issuer
// schema - schema as JSON string
```
* Step 3: Performs EcDSA signing using his ethereum identity account keys
* Step 4: Author passes Schema and Signature to Endorser
* Endorser steps:
* Step 1: Endorser builds transaction to endorse
DID: `endorseSchema(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, string id, string issuerId, string schema)`
DID: `endorseSchema(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 id, bytes schema)`
* Step 2: Endorser does regular EcDSA signing of the **Transaction**
* Step 3: Endorser submit the signed transaction to the ledger which executes
deployed `SchemaRegistry.endorseSchema`
Expand All @@ -178,16 +82,15 @@ TO BE defined later.
* Step 2: Execute VDR method to calculate hash need to be signed - contract signed data according
to [EIP](https://eips.ethereum.org/EIPS/eip-191).
```
keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, issuerId, schemaId, credDef))
keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, schemaId, credDef))
// Arguments when calculating hash to validate
// 1: byte(0x19) - the initial 0x19 byte
// 2: byte(0) - the version byte
// 3: address(this) - the validator address
// 4-9: Application specific data
// 4-8: Application specific data
// identity - author account address
// `createSchema` original contract method - added to be aligned with did:ethr contract
// id - id of schema to be created
// issuerId - id of issuer
// schemaId - id of schema
// credDef - credential definition as JSON string
```
Expand All @@ -198,85 +101,74 @@ TO BE defined later.
#### Contracts
```
function endorseSchema(
function createSchemaSigned(
address identity,
string calldata id,
string calldata issuerId,
string calldata schema,
uint8 sigV,
bytes32 sigR,
bytes32 sigS
bytes32 id,
bytes schema,

) public virtual {
// validate identity signature
bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, issuerId, schema));
bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, schema));
checkSignature(identity, hash, sigV, sigR, sigS);

// store schema
createSchema(identity, id, issuerId, schema);
createSchema(identity, id, schema);
}

function endorseCredentialDefinition(
address identity,
string memory id,
string calldata issuerId,
string calldata schemaId,
string memory credDef,
uint8 sigV,
bytes32 sigR,
bytes32 sigS
bytes32 sigS,
byets32 id,
byets32 schemaId,
byets credDef
) public virtual {
// validate identity signature
bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, issuerId, schemaId, credDef));
bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, schemaId, credDef));
checkSignature(identity, hash, sigV, sigR, sigS);

// store credential definition
createCredentialDefinition_(identity, id, issuerId, schemaId, credDef);
createCredentialDefinition_(identity, id, schemaId, credDef);
}
```
#### VDR
```rust
// Prepare schema endorsing bytes which need to be signed by an identity owner
fn prepare_endorse_schema_data(
pub async fn build_create_schema_endorsing_data(
client: &LedgerClient,
identity: &Address,
id: &SchemaId,
issuer_id: &DID,
schema: &Schema,
) -> Vec<u8>;
) -> VdrResult<TransactionEndorsingData>;
// Build transaction to endorse Schema
fn build_endorse_schema_transaction(
pub async fn build_create_schema_signed_transaction(
client: &LedgerClient,
sender: &Address,
identity: &Address,
id: &SchemaId,
issuer_id: &DID,
schema: &Schema,
signature: &Signature
) -> VdrResult<Transaction> {}
signature: &SignatureData,
) -> VdrResult<Transaction>;
// Prepare credential definition endorsing bytes which need to be signed by an identity owner
fn prepare_endorse_credential_definition_data(
pub async fn build_create_credential_definition_endorsing_data(
client: &LedgerClient,
identity: &Address,
id: &SchemaId,
issuer_id: &DID,
schema_id: &SchemaId,
cred_def: &CredentialDefinition,
) -> Vec<u8>;
id: &CredentialDefinitionId,
credential_definition: &CredentialDefinition,
) -> VdrResult<TransactionEndorsingData>;
// Build transaction to endorse CredentialDefinition
fn build_endorse_credential_definition_transaction(
pub async fn build_create_credential_definition_signed_transaction(
client: &LedgerClient,
sender: &Address,
identity: &Address,
id: &SchemaId,
issuer_id: &DID,
schema_id: &SchemaId,
cred_def: &CredentialDefinition,
signature: &Signature
) -> VdrResult<Transaction> {}
from: &Address,
id: &CredentialDefinitionId,
credential_definition: &CredentialDefinition,
signature: &SignatureData,
) -> VdrResult<Transaction>;
```

Loading

0 comments on commit 7ea8326

Please sign in to comment.