Going public but staying permissioned – Hands on EcRecover

When discussing blockchain technology for business you typically face a recurring dilemma. It is not about choosing between Bitcoin or Ethereum they are two households, both alike in dignity but rather about public versus private or permissioned blockchains. The efficiency of a blockchain application improves as the number of peers in the network and the diversity among them grow. Therefore when you build on a public blockchain you start with a considerable ecosystem but it comes with at a price because anyone can interact with your application. Wisely and slow they stumble that run fast, building on a public blockchain requires to pay a close attention to the quality and the resilience of the code you use to avoid misbehaviors and edge cases.


In this short article I want to introduce a way to keep your blockchain application permissioned on Ethereum using what I think is an underrated function of Solidity: EcRecover. This function can notably compel a user to get an authorization token externally to access a smart-contract. Therefore, the smart-contract can be publicly deployed but restricted to permissioned users

Jan de Bray, Regents of the Children's Orphanage in Haarlem
Jan de Bray – The Regents of the Children s Orphanage in Haarlem. 1663.

 What is EcRecover ?

 It is a built in (i.e. precompiled) function on Ethereum The name EcRecover derives from elliptic curve recovering and ECDSA (Elliptic Curve Digital Signature Algorithm). When you sign data with ECDSA you get a signature pair (r,s). The precompiled EcRecover takes 4 inputs, namely “h” the original hash of the signed data, the signature pair “(r,s)” and the parameter “v” to select the proper point on the elliptic curve. It returns an Ethereum address (i.e. a public key) that can be compared to the address that claims to have signed the data. You can find the code of the precompile written in Rust here 

 Let’s sign and use EcRecover

 The first parameter of EcRecover has to be a hex string of 64 bytes which is the default type of a SHA3 hash in Ethereum. A very handy way to produce a compliant hash is to use the web3.js library but you should be aware that SHA3 sometimes does not behave like it does in Solidity.

There is an issue opened on github about it. I recommend the solidity-sha3 library developed by Raine Revere to avoid this problem.

1
2
sha3(“Welcome to EY Lab”)
‘0xf3d4f028f907391acab0fd4894af4b9c5fc9a7a7c8e8a1e52e301c58319effc2’

And sign it using eth.sign(address, DataToSign) from the web3 library.Note that the parameter “address” is the unlocked account you wish to sign with. If you are using the Parity client, the “signer” in the web interface will request an authorization if the account is not unlocked :

1
2
signed = web3.eth.sign(‘0x0088A8FFaDF72A884989064D8590c0A1b823dD7C’,’0xf3d4f028f907391acab0fd4894af4b9c5fc9a7a7c8e8a1e52e301c58319effc2′)
‘0xbade6e6dd120768fda79be6445960fd1258a85abe7d742c63c3739be01886b9e7cb999638196f099d42e09e60f6f4ed4f73aa6a77f8293bdc604cd95be4f477200’

The resulting hex string contains the three elements r, s and v that will be used in EcRecover :

1
2
3
4
5
6
r = signed.substr(0, 66)
‘0xbade6e6dd120768fda79be6445960fd1258a85abe7d742c63c3739be01886b9e’
s = ‘0x’ + signed.substr(66, 64)
‘0x7cb999638196f099d42e09e60f6f4ed4f73aa6a77f8293bdc604cd95be4f4772’
v = parseInt(signed.substr(130)) + 27
27

Now that we have all the parameters for EcRecover, here is a simple contract to test it:

1
2
3
4
5
pragma solidity ^0.4.6;
contract EcRecovered {
address public log;
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) {
log = ecrecover(hash, v, r, s);}}

Is it costly ? How to use it ?

Well not that much, the EcRecover is priced at 3 000 gas but will certainly come in practice with a bunch of other operations. For example, you could want to check the consistency of the hash before using EcRecover. For example, have a look at this contract:

1
2
3
4
5
6
7
8
9
10
pragma solidity ^0.4.6;
contract EcRecoveredfunds {
address public auth;
function EcRecoveredfunds ()
{ auth = msg.sender;}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s, uint blockExpired, bytes32 salt) {
if (block.number >; blockExpired) {throw;}
else if (hash != sha3(blockExpired, salt)){ throw;}
else if (ecrecover(hash, v, r, s) != auth) {throw;}
selfdestruct(msg.sender);}}

Say this contract has been deployed by the address “auth” and holds ether. A user can be allowed by “auth” to withdraw those funds for a limited period of time (i.e. as long as the call is made before “blockExpired”). The signed hash acts as the authorization token I mentioned earlier making the smart-contract publicly deployed but restricted to permissioned users.

Is it safe to use?

EcRecover is as safe and resistant to attacks as elliptic curve signatures are, what here shall miss, our toil shall strive to mend.

Jérôme de Tychey

Jan de Bray, The governors of the guild of St. Luke
Jan de Bray – The Governors of the Guild of St Luke 1675