I want to store some data in smart contract and then decrypt it on chain. Pseudocode:
contract EncryptedData {
bytes data;
string public decryptedData;
constructor(bytes data_) public {
data = data_;
}
function decrypt(bytes key) public {
decryptedData = decryptDataSomehow(data, key);
}
}
I know that when contract gets called the entire network gets the key and I'm fine with it.
The question is only "how can I decrypt data on chain"? I googled a lot but I didn't find any cryptographic primitives available. Only some EIPs like EIP-213 and so on, but nothing specific.
I'm not cryptographic PhD to implement cryptography myself (and it probably would burn bazillions of gas) so I need some builtins tools or at least already tested contracts.
What are my options here? I can't do it offchain because the entire idea of the whole thing is trust that only smart contract could have. I can't call oracles or something, the entire thing should be completely on-chain.
Edit: I actually have a little bit different situation. My contract is more like
contract EncryptedData {
bytes[] data;
string public decryptedData[];
function addData(bytes data_) {
data.push(data_);
}
function decrypt(bytes key) public {
for (uint i = 0; i < data.length; i++) {
decryptedData.push(decryptDataSomehow(data[i], key));
}
}
}
Best Answer
You may use the following simple function to encrypt/decrypt arbitrary data on-chain:
It is symmetric, i.e.
encryptDecrypt (encryptDecrypt (x, key), key) == x
for anyx
andkey
. It is also secure enough.Algorithm explanation: This function just XORs data with the following sequence of 32-byte hashes:
This approach is known as Counter (CTR) encryption mode.
You may easily implement the same logic on any programming language that is able to calculate keccak256 on binary data.
Security Note: This schema assumes that each key is used only once and is hard to guess, preferably random. If you want to use one key several times, or use weak keys, you need to use initial vector like this:
For encryption:
For decryption: