-
Notifications
You must be signed in to change notification settings - Fork 12.4k
Add isValidSignatureAndData to Bouncer to verify method calls
#973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
98538ea
273c846
2622a66
be50c84
da1a4f1
6afc6b3
29036cc
a02b258
d2f6fc7
91ec2c1
006db16
b30361d
2a8e1d5
68d9b74
b528c26
aab0822
7e050b6
3f3495c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,12 +20,23 @@ import "../ECRecovery.sol"; | |
| * @dev Then restrict access to your crowdsale/whitelist/airdrop using the | ||
| * @dev `onlyValidSignature` modifier (or implement your own using isValidSignature). | ||
| * @dev | ||
| * @dev In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and | ||
| * @dev `onlyValidSignatureAndData` can be used to restrict access to only a given method | ||
| * @dev or a given method with given parameters respectively. | ||
| * @dev | ||
| * @dev See the tests Bouncer.test.js for specific usage examples. | ||
| * @notice A method that uses the `onlyValidSignatureAndData` modifier must make the _sig | ||
| * @notice parameter the "last" parameter. You cannot sign a message that has its own | ||
| * @notice signature in it so the last 160 bytes is of msg.data (which represents _sig) | ||
| * @notice is ignored when validating. | ||
| */ | ||
| contract SignatureBouncer is Ownable, RBAC { | ||
| using ECRecovery for bytes32; | ||
|
|
||
| string public constant ROLE_BOUNCER = "bouncer"; | ||
| uint constant METHOD_ID_SIZE = 4; | ||
| // (signature length size) 32 bytes + (signature size 65 bytes padded) 96 bytes | ||
| uint constant SIG_SIZE = 128; | ||
|
||
|
|
||
| /** | ||
| * @dev requires that a valid signature of a bouncer was provided | ||
|
|
@@ -36,6 +47,24 @@ contract SignatureBouncer is Ownable, RBAC { | |
| _; | ||
| } | ||
|
|
||
| /** | ||
| * @dev requires that a valid signature with a specifed method of a bouncer was provided | ||
| */ | ||
| modifier onlyValidSignatureAndMethod(bytes _sig) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would use
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's follow this up with a change to |
||
| { | ||
| require(isValidSignatureAndMethod(msg.sender, _sig)); | ||
| _; | ||
| } | ||
|
|
||
| /** | ||
| * @dev requires that a valid signature with a specifed method and params of a bouncer was provided | ||
| */ | ||
| modifier onlyValidSignatureAndData(bytes _sig) | ||
| { | ||
| require(isValidSignatureAndData(msg.sender, _sig)); | ||
| _; | ||
| } | ||
|
|
||
| /** | ||
| * @dev allows the owner to add additional bouncer addresses | ||
| */ | ||
|
|
@@ -73,6 +102,46 @@ contract SignatureBouncer is Ownable, RBAC { | |
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @dev is the signature of `this + sender + methodId` from a bouncer? | ||
| * @return bool | ||
| */ | ||
| function isValidSignatureAndMethod(address _address, bytes _sig) | ||
| internal | ||
| view | ||
| returns (bool) | ||
| { | ||
| bytes memory data = new bytes(METHOD_ID_SIZE); | ||
| for (uint i = 0; i < data.length; i++) { | ||
| data[i] = msg.data[i]; | ||
| } | ||
| return isValidDataHash( | ||
| keccak256(address(this), _address, data), | ||
| _sig | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @dev is the signature of `this + sender + methodId + params(s)` from a bouncer? | ||
| * @notice the _sig parameter of the method being validated must be the "last" parameter | ||
| * @return bool | ||
| */ | ||
| function isValidSignatureAndData(address _address, bytes _sig) | ||
| internal | ||
| view | ||
| returns (bool) | ||
| { | ||
| require(msg.data.length > SIG_SIZE); | ||
| bytes memory data = new bytes(msg.data.length - SIG_SIZE); | ||
| for (uint i = 0; i < data.length; i++) { | ||
| data[i] = msg.data[i]; | ||
| } | ||
| return isValidDataHash( | ||
| keccak256(address(this), _address, data), | ||
| _sig | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @dev internal function to convert a hash to an eth signed message | ||
| * @dev and then recover the signature and check it against the bouncer role | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we update this to the new value of 128 and also mention that for this to be easy to construct signatures for, your arguments must be fixed-sized?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(sorry, just took one last pass through it and I think it's worth adding a comment about this)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shrugs Ah, sorry, my bad. I'll get that changed. I actually went and posted a detailed answer on a stack overflow thread about how
msg.datais constructed https://ethereum.stackexchange.com/a/50616/40921 . Do you want me to link this thread in the comments?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, that's a solid answer