diff --git a/contracts/ECRecovery.sol b/contracts/ECRecovery.sol new file mode 100644 index 000000000..709ee43cb --- /dev/null +++ b/contracts/ECRecovery.sol @@ -0,0 +1,54 @@ +pragma solidity ^0.4.18; + + +/** + * @title Eliptic curve signature operations + * + * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d + */ + +library ECRecovery { + + /** + * @dev Recover signer address from a message by using his signature + * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. + * @param sig bytes signature, the signature is generated using web3.eth.sign() + */ + function recover(bytes32 hash, bytes sig) public pure returns (address) { + bytes32 r; + bytes32 s; + uint8 v; + + //Check the signature length + if (sig.length != 65) { + return (address(0)); + } + + // Divide the signature in r, s and v variables + assembly { + r := mload(add(sig, 32)) + s := mload(add(sig, 64)) + v := byte(0, mload(add(sig, 96))) + } + + // Version of signature should be 27 or 28, but 0 and 1 are also possible versions + if (v < 27) { + v += 27; + } + + // If the version is correct return the signer address + if (v != 27 && v != 28) { + return (address(0)); + } else { + + /* + * https://github.com/ethereum/go-ethereum/issues/3731 + */ + + bytes memory prefix = "\x19Ethereum Signed Message:\n32"; + hash = keccak256(prefix, hash); + return ecrecover(hash, v, r, s); + } + } + +}