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 contract0x02
- member of a contract0x03
- 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 sharingsecret area
- available for all memberssuper secret area
- available for0x03
{
"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"
}
}
}
}
}
constructor¶
new Sharing(options);
Creates a new Sharing instance.
Parameters¶
options
-SharingOptions
: options for Sharing constructor.contractLoader
-ContractLoader
:ContractLoader
instancecryptoProvider
-CryptoProvider
:CryptoProvider
instancedescription
-Description
:Description
instancedfs
-DfsInterface
:DfsInterface
instanceexecutor
-Executor
:Executor
instancekeyProvider
-KeyProvider
:KeyProvider
instancenameResolver
-NameResolver
:NameResolver
instancedefaultCryptoAlgo
-string
(optional): crypto algorith name fromCryptoProvider
, defaults toaes
log
-Function
(optional): function to use for logging:(message, level) => {...}
logLevel
-LogLevel
(optional): messages with this level will be logged withlog
logLog
-LogLogInterface
(optional): container for collecting log messageslogLogLevel
-LogLevel
(optional): messages with this level will be pushed tologLog
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¶
address
-string
: contract address or ENS addressoriginator
-string
: Ethereum account id of the sharing userpartner
-string
: Ethereum account id for which key shall be addedsection
-string
: data section the key is intended for or ‘*’block
-number|string
: starting with this block, the key is validsharingKey
-string
: key to sharecontext
-string
(optional): context to share key inisHashKey
-bool
(optional): indicates if given key already is a hash key, defaults tofalse
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¶
address
-string
: contract address or ENS addressoriginator
-string
: Ethereum account id of the sharing userpartner
-string
: Ethereum account id for which key shall be addedsection
-string
: data section the key is intended for or ‘*’block
-number|string
: starting with this block, the key is validsharingKey
-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¶
sharings
-any
: object with sharings infooriginator
-string
: Ethereum account id of the sharing userpartner
-string
: Ethereum account id for which key shall be addedsection
-string
: data section the key is intended for or ‘*’block
-number|string
: starting with this block, the key is validsharingKey
-string
: key to sharecontext
-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¶
address
-string
: contract address or ENS addresspartner
-string
: Ethereum account id for which key shall be retrievedsection
-string
: data section the key is intended for or ‘*’block
-number|string
(optional): starting with this block, the key is valid, defaults toNumber.MAX_SAFE_INTEGER
sharingId
-string
(optional): id of a sharing (when multi-sharings is used), defaults tonull
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¶
address
-string
: contract address or ENS addresspartner
-string
: Ethereum account id for which key shall be retrievedsection
-string
: data section the key is intended for or ‘*’sharingId
-string
(optional): id of a sharing (when multi-sharings is used), defaults tonull
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¶
address
-string
: contract address or ENS addressoriginator
-string
: Ethereum account id of the sharing userpartner
-string
: Ethereum account id for which key shall be addedhashKey
-string
: key for DFS hashescontext
-string
(optional): context to share key insharingId
-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¶
address
-string
: contract address or ENS addresspartner
-string
: Ethereum account id for which key shall be retrievedsharingId
-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¶
address
-string
: contract address or ENS address_partner
-string
(optional): Ethereum account id for which key shall be retrieved_section
-string
(optional): data section the key is intended for or ‘*’_block
-number
(optional): starting with this block, the key is validsharingId
-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¶
address
-string
: contract address or ENS addressoriginator
-string
: Ethereum account id of the sharing userpartner
-string
: Ethereum account id for which key shall be removedsection
-string
: data section of the keysharingId
-string
(optional): id of a sharing (when multi-sharings is used), defaults tonull
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¶
contact
-any
: contract with sharing infosharingId
-string
(optional): id of a sharing in mutlisharings, defaults tonull
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¶
contract
-string|any
: contract address or instancesharings
-any
: sharings object with encrypted keysoriginator
-string
: Ethereum account id of the sharing usersharingId
-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¶
address
-string
: contract addresssharingHash
-string
: bytes32 hash of a sharingsharingId
-string
(optional): id of a multisharing, defaults tonull
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();