Skip to content

Instantly share code, notes, and snippets.

@jMyles
Created June 26, 2019 16:57
Show Gist options
  • Save jMyles/9526dee62674718ab97b93793ac45bfa to your computer and use it in GitHub Desktop.
Save jMyles/9526dee62674718ab97b93793ac45bfa to your computer and use it in GitHub Desktop.
pragma solidity ^0.5.3;
/**
* @notice Library to recover address and verify signatures
* @dev Simple wrapper for `ecrecover`
**/
library SignatureVerifier {
enum HashAlgorithm {KECCAK256, SHA256, RIPEMD160}
/**
* @notice Recover signer address from hash and signature
* @param _hash 32 bytes message hash
* @param _signature Signature of hash - 32 bytes r + 32 bytes s + 1 byte v (could be 0, 1, 27, 28)
**/
function recover(bytes32 _hash, bytes memory _signature)
internal
pure
returns (address)
{
require(_signature.length == 65);
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(_signature, 32))
s := mload(add(_signature, 64))
v := byte(0, mload(add(_signature, 96)))
}
// Version of signature should be 27 or 28, but 0 and 1 are also possible versions
if (v < 27) {
v += 27;
}
require(v == 27 || v == 28);
return ecrecover(_hash, v, r, s);
}
/**
* @notice Transform public key to address
* @param _publicKey secp256k1 public key
**/
function toAddress(bytes memory _publicKey) internal pure returns (address) {
return address(uint160(uint256(keccak256(_publicKey))));
}
/**
* @notice Hash using one of pre built hashing algorithm
* @param _message Signed message
* @param _algorithm Hashing algorithm
**/
function hash(bytes memory _message, HashAlgorithm _algorithm)
internal
pure
returns (bytes32 result)
{
if (_algorithm == HashAlgorithm.KECCAK256) {
result = keccak256(_message);
} else if (_algorithm == HashAlgorithm.SHA256) {
result = sha256(_message);
} else {
result = ripemd160(_message);
}
}
/**
* @notice Verify ECDSA signature
* @dev Uses one of pre built hashing algorithm
* @param _message Signed message
* @param _signature Signature of message hash
* @param _publicKey secp256k1 public key in uncompressed format without prefix byte (64 bytes)
* @param _algorithm Hashing algorithm
**/
function verify(
bytes memory _message,
bytes memory _signature,
bytes memory _publicKey,
HashAlgorithm _algorithm
)
internal
pure
returns (bool)
{
require(_publicKey.length == 64);
return toAddress(_publicKey) == recover(hash(_message, _algorithm), _signature);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment