ECDSA.sol
1 pragma solidity >=0.5.0 <0.7.0; 2 3 /** 4 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. 5 * 6 * These functions can be used to verify that a message was signed by the holder 7 * of the private keys of a given address. 8 */ 9 library ECDSA { 10 /** 11 * @dev Returns the address that signed a hashed message (`hash`) with 12 * `signature`. This address can then be used for verification purposes. 13 * 14 * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: 15 * this function rejects them by requiring the `s` value to be in the lower 16 * half order, and the `v` value to be either 27 or 28. 17 * 18 * NOTE: This call _does not revert_ if the signature is invalid, or 19 * if the signer is otherwise unable to be retrieved. In those scenarios, 20 * the zero address is returned. 21 * 22 * IMPORTANT: `hash` _must_ be the result of a hash operation for the 23 * verification to be secure: it is possible to craft signatures that 24 * recover to arbitrary addresses for non-hashed data. A safe way to ensure 25 * this is by receiving a hash of the original message (which may otherwise 26 * be too long), and then calling {toEthSignedMessageHash} on it. 27 */ 28 function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { 29 // Check the signature length 30 if (signature.length != 65) { 31 return (address(0)); 32 } 33 34 // Divide the signature in r, s and v variables 35 bytes32 r; 36 bytes32 s; 37 uint8 v; 38 39 // ecrecover takes the signature parameters, and the only way to get them 40 // currently is to use assembly. 41 // solhint-disable-next-line no-inline-assembly 42 assembly { 43 r := mload(add(signature, 0x20)) 44 s := mload(add(signature, 0x40)) 45 v := byte(0, mload(add(signature, 0x60))) 46 } 47 48 // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature 49 // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines 50 // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most 51 // signatures from current libraries generate a unique signature with an s-value in the lower half order. 52 // 53 // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value 54 // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or 55 // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept 56 // these malleable signatures as well. 57 if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { 58 return address(0); 59 } 60 61 if (v != 27 && v != 28) { 62 return address(0); 63 } 64 65 // If the signature is valid (and not malleable), return the signer address 66 return ecrecover(hash, v, r, s); 67 } 68 69 /** 70 * @dev Returns an Ethereum Signed Message, created from a `hash`. This 71 * replicates the behavior of the 72 * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`personal_sign`] 73 * JSON-RPC method. 74 * 75 * See {recover}. 76 */ 77 function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { 78 // 32 is the length in bytes of hash, 79 // enforced by the type signature above 80 //return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); 81 return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); 82 } 83 84 /** 85 * @dev Returns an ERC191 Signed Message, created from a `hash`. This 86 * replicates the behavior of the 87 * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_signTypedData`] 88 * JSON-RPC method. 89 * 90 * See {recover}. 91 */ 92 function toERC191SignedMessage(address _validator, bytes memory data) internal pure returns (bytes32) { 93 return keccak256(abi.encodePacked(byte(0x19), byte(0x0), _validator, data)); 94 } 95 96 function toERC191SignedMessage(byte version, bytes memory versionData, bytes memory data) internal pure returns (bytes32) { 97 return keccak256(abi.encodePacked(byte(0x19), version, versionData, data)); 98 } 99 /** 100 * @notice Transform public key to address 101 * @param _publicKey secp256k1 public key 102 **/ 103 function toAddress(bytes memory _publicKey) internal pure returns (address payable) { 104 return address(uint160(uint256(keccak256(_publicKey)))); 105 } 106 107 108 } 109 110