Sharing

Class Name Sharing
Extends Logger
Source sharing.ts
Examples sharing.spec.ts

For getting a better understanding about how Sharings and Multikeys work, have a look at Security in the evan.network wiki.

Following is a sample for a sharing info with these properties:

  • three users
    • 0x01 - owner of a contract
    • 0x02 - member of a contract
    • 0x03 - another member with differing permissions
  • two timestamps
    • block 82745 - first sharing
    • block 90000 - splitting data, update sharings
  • three sections
    • * generic “catch all” used in first sharing
    • secret area - available for all members
    • super secret area - available for 0x03
{
  "0x01": {
    "82745": {
      "*": {
        "private": "secret for 0x01, starting from block 82745 for all data",
        "cryptoInfo": {
          "originator": "0x01,0x01",
          "keyLength": 256,
          "algorithm": "aes-256-cbc"
        }
      }
    },
    "90000": {
      "secret area": {
        "private": "secret for 0x01, starting from block 90000 for 'secret area'",
        "cryptoInfo": {
          "originator": "0x01,0x01",
          "keyLength": 256,
          "algorithm": "aes-256-cbc"
        }
      },
      "super secret area": {
        "private": "secret for 0x01, starting from block 90000 for 'super secret area'",
        "cryptoInfo": {
          "originator": "0x01,0x01",
          "keyLength": 256,
          "algorithm": "aes-256-cbc"
        }
      }
    }
  },
  "0x02": {
    "82745": {
      "*": {
        "private": "secret for 0x02, starting from block 82745 for all data",
        "cryptoInfo": {
          "originator": "0x01,0x02",
          "keyLength": 256,
          "algorithm": "aes-256-cbc"
        }
      }
    },
    "90000": {
      "secret area": {
        "private": "secret for 0x02, starting from block 90000 for 'secret area'",
        "cryptoInfo": {
          "originator": "0x01,0x02",
          "keyLength": 256,
          "algorithm": "aes-256-cbc"
        }
      },
      "super secret area": {
        "private": "secret for 0x02, starting from block 90000 for 'super secret area'",
        "cryptoInfo": {
          "originator": "0x01,0x02",
          "keyLength": 256,
          "algorithm": "aes-256-cbc"
        }
      }
    },
  },
  "0x03": {
    "90000": {
      "secret area": {
        "private": "secret for 0x03, starting from block 90000 for 'secret area'",
        "cryptoInfo": {
          "originator": "0x01,0x03",
          "keyLength": 256,
          "algorithm": "aes-256-cbc"
        }
      }
    }
  }
}

More information about sharings can be fout at the evan.network wiki.


constructor

new Sharing(options);

Creates a new Sharing instance.

Parameters

  1. options - SharingOptions: options for Sharing constructor.

Returns

Sharing instance

Example

const sharing = new Sharing({
  contractLoader,
  cryptoProvider,
  description,
  executor,
  dfs,
  keyProvider,
  nameResolver,
  defaultCryptoAlgo: 'aes',
});

addSharing

sharing.addSharing(address, originator, partner, section, block, sharingKey[, context, isHashKey, sharingId]);

Add a sharing to a contract or an ENS address.

Parameters

  1. address - string: contract address or ENS address
  2. originator - string: Ethereum account id of the sharing user
  3. partner - string: Ethereum account id for which key shall be added
  4. section - string: data section the key is intended for or ‘*’
  5. block - number|string: starting with this block, the key is valid
  6. sharingKey - string: key to share
  7. context - string (optional): context to share key in
  8. isHashKey - bool (optional): indicates if given key already is a hash key, defaults to false
  9. sharingId - string (optional): id of a sharing (when multi-sharings is used)

Returns

Promise returns void: resolved when done

Example

// two sample users, user1 wants to share a key with user2
const user1 = '0x0000000000000000000000000000000000000001';
const user2 = '0x0000000000000000000000000000000000000002';
// create a sample contract
// usually you would have an existing contract, for which you want to manage the sharings
const contract = await executor.createContract('Shared', [], { from: user1, gas: 500000, });
// user1 shares the given key with user2
// this key is shared for all contexts ('*') and valid starting with block 0
await sharing.addSharing(contract.options.address, user1, user2, '*', 0, 'i am the secred that will be shared');

bumpSharings

sharing.bumpSharings(address, originator, partners, section, block, sharingKey);

Bump keys for given accounts by adding given key to their sharings. This is basically a shorthand version for adding the new key for every account in the partners array in a single transaction.

context, hashKeys and sharingId are currently not supported.

Parameters

  1. address - string: contract address or ENS address
  2. originator - string: Ethereum account id of the sharing user
  3. partner - string: Ethereum account id for which key shall be added
  4. section - string: data section the key is intended for or ‘*’
  5. block - number|string: starting with this block, the key is valid
  6. sharingKey - string: key to share

Returns

Promise returns void: resolved when done

Example

// two sample users, user1 wants to bump keys for user2 and user3
const user1 = '0x0000000000000000000000000000000000000001';
const user2 = '0x0000000000000000000000000000000000000002';
const user3 = '0x0000000000000000000000000000000000000003';
// assume we have a contract with sharings for those accounts
const contractId = '0x00000000000000000000000000000000c027rac7';
await sharing.bumpSharings(contractId, user1, [ user2, user3 ], '*', 0, 'i am a bump key');

extendSharing

sharing.extendSharing(address, originator, partner, section, block, sharingKey[, context, isHashKey]);

Extend an existing sharing info with given key; this is done on a sharings object and does not perform a transaction on its own.

Parameters

  1. sharings - any: object with sharings info
  2. originator - string: Ethereum account id of the sharing user
  3. partner - string: Ethereum account id for which key shall be added
  4. section - string: data section the key is intended for or ‘*’
  5. block - number|string: starting with this block, the key is valid
  6. sharingKey - string: key to share
  7. context - string (optional): context to share key in

Returns

Promise returns any: updated sharings info

Example

const sharings =  {};
await this.options.sharing.extendSharings(sharings, accountId, accountId, '*', blockNr, contentKey);
await this.options.sharing.extendSharings(sharings, accountId, accountId, '*', 'hashKey', hashKey);

getKey

sharing.getKey(address, partner, section[, block, sharingId]);

Get a content key from the sharing of a contract.

Parameters

  1. address - string: contract address or ENS address
  2. partner - string: Ethereum account id for which key shall be retrieved
  3. section - string: data section the key is intended for or ‘*’
  4. block - number|string (optional): starting with this block, the key is valid, defaults to Number.MAX_SAFE_INTEGER
  5. sharingId - string (optional): id of a sharing (when multi-sharings is used), defaults to null

Returns

Promise returns string: matching key

Example

// a sample user
const user2 = '0x0000000000000000000000000000000000000002';
// user2 wants to read a key after receiving a sharing
// the key requested should be valid for all contexts ('*') and valid up to and including block 100
const key = await sharing.getKey(contract.options.address, user2, '*', 100);

getKeyHistory

sharing.getKeyHistory(address, partner, section[, sharingId]);

Get history of keys for an account and a section.

Parameters

  1. address - string: contract address or ENS address
  2. partner - string: Ethereum account id for which key shall be retrieved
  3. section - string: data section the key is intended for or ‘*’
  4. sharingId - string (optional): id of a sharing (when multi-sharings is used), defaults to null

Returns

Promise returns any: object with key: blockNr, value: key

Example

// a sample user
const user2 = '0x0000000000000000000000000000000000000002';
// user2 wants to retrieve all keys for '*'
const keyHistory = await sharing.getKeyHistory(contract.options.address, user2, '*');

ensureHashKey

sharing.ensureHashKey(address, originator, partner, hashKey[, context, sharingId]);

Give hash key “hashKey” to account “partner”, if this account does not have a hash key already.

Parameters

  1. address - string: contract address or ENS address
  2. originator - string: Ethereum account id of the sharing user
  3. partner - string: Ethereum account id for which key shall be added
  4. hashKey - string: key for DFS hashes
  5. context - string (optional): context to share key in
  6. sharingId - string (optional): id of a sharing (when multi-sharings is used)

Returns

Promise returns void: resolved when done

Example

const hashCryptor = cryptoProvider.getCryptorByCryptoAlgo('aesEcb');
const hashKey = await hashCryptor.generateKey();
await sharing.ensureHashKey(contract.options.address, accounts[0], accounts[1], hashKey);

getHashKey

sharing.getHashKey(address, partner[, sharingid]);

Function description

Parameters

  1. address - string: contract address or ENS address
  2. partner - string: Ethereum account id for which key shall be retrieved
  3. sharingId - string (optional): id of a sharing (when multi-sharings is used)

Returns

Promise returns string: matching key

Example

const hashCryptor = cryptoProvider.getCryptorByCryptoAlgo('aesEcb');
const hashKey = await hashCryptor.generateKey();
await sharing.ensureHashKey(contract.options.address, accounts[0], accounts[1], hashKey);
const rerieved = sharing.ensureHashKey(contract.options.address, accounts[1]);
console.log(hashKey === retrieved);
// Output:
// true

getSharings

sharing.getSharings(address[, _partner, _section, _block, sharingId]);

Get sharing from a contract, if _partner, _section, _block matches.

Parameters

  1. address - string: contract address or ENS address
  2. _partner - string (optional): Ethereum account id for which key shall be retrieved
  3. _section - string (optional): data section the key is intended for or ‘*’
  4. _block - number (optional): starting with this block, the key is valid
  5. sharingId - string (optional): id of a sharing (when multi-sharings is used)

Returns

Promise returns void: resolved when done

Example

const randomSecret = `super secret; ${Math.random()}`;
await sharing.addSharing(testAddress, accounts[1], accounts[0], '*', 0, randomSecret);
const sharings = await sharing.getSharings(testAddress);

removeSharing

sharing.removeSharing(address, originator, partner, section[, sharingId]);

Remove a sharing key from a contract with sharing info.

Parameters

  1. address - string: contract address or ENS address
  2. originator - string: Ethereum account id of the sharing user
  3. partner - string: Ethereum account id for which key shall be removed
  4. section - string: data section of the key
  5. sharingId - string (optional): id of a sharing (when multi-sharings is used), defaults to null

Returns

Promise returns void: resolved when done

Example

await sharing.addSharing(contract.options.address, accounts[0], accounts[1], '*', 0, randomSecret);

let sharings = await sharing.getSharings(contract.options.address);
console.log(Object.keys(sharings[nameResolver.soliditySha3(accounts[1])]).length);
// Output:
// 1

await sharing.removeSharing(contract.options.address, accounts[0], accounts[1], '*');

let sharings = await sharing.getSharings(contract.options.address);
console.log(Object.keys(sharings[nameResolver.soliditySha3(accounts[1])]).length);
// Output:
// 0

getSharingsFromContract

sharing.getSharingsFromContract(contract[, sharingId]);

Get encrypted sharings from smart contract.

This can be used in combination with getSharingsFromContract to bulk editing sharing info.

Parameters

  1. contact - any: contract with sharing info
  2. sharingId - string (optional): id of a sharing in mutlisharings, defaults to null

Returns

Promise returns void: resolved when done

Example

// get sharings (encrypted)
const sharings = await sharing.getSharingsFromContract(serviceContract, callIdHash);

// make changes to sharing
await sharing.extendSharings(sharings, accountId, target, section, 0, contentKeyToShare, null);
await sharing.extendSharings(sharings, accountId, target, '*', 'hashKey', hashKeyToShare, null);

// commit changes
await sharing.saveSharingsToContract(serviceContract.options.address, sharings, accountId, callIdHash);

saveSharingsToContract

sharing.saveSharingsToContract(contract, sharings, originator[, sharingId]);

Save sharings object with encrypted keys to contract.

This can be used to pull sharings, edit them offline and commit changes in a bulk. See example section for usage.

Parameters

  1. contract - string|any: contract address or instance
  2. sharings - any: sharings object with encrypted keys
  3. originator - string: Ethereum account id of the sharing user
  4. sharingId - string (optional): id of a sharing (when multi-sharings is used)

Returns

Promise returns void: resolved when done

Example

// get sharings (encrypted)
const sharings = await sharing.getSharingsFromContract(serviceContract, callIdHash);

// make changes to sharing
await sharing.extendSharings(sharings, accountId, target, section, 0, contentKeyToShare, null);
await sharing.extendSharings(sharings, accountId, target, '*', 'hashKey', hashKeyToShare, null);

// commit changes
await sharing.saveSharingsToContract(serviceContract.options.address, sharings, accountId, callIdHash);

addHashToCache

sharing.addHashToCache(address, sharingHash[, sharingId]);

Add a hash to to cache, can be used to speed up sharing key retrieval, when sharings hash is already known.

Parameters

  1. address - string: contract address
  2. sharingHash - string: bytes32 hash of a sharing
  3. sharingId - string (optional): id of a multisharing, defaults to null

Example

sharing.addHashToCache(contract.options.address, sharingHash, sharingId);

clearCache

sharing.clearCache();

Clear caches and fetch new hashes and sharing on next request.

When sharings are fetched and not all results could be read, the result would stay the same in following requests due to the internal caching mechanism, even if a proper key has been shared with the user later on. To prevent such old values from showing up, the cache can be cleared.

Example

sharing.clearCache();