Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
O
openzeppelin-contracts-upgradeable
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
俞永鹏
openzeppelin-contracts-upgradeable
Commits
1488d4f6
Unverified
Commit
1488d4f6
authored
Jun 01, 2021
by
Hadrien Croubois
Committed by
GitHub
Jun 01, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve ECDSA tests and docs (#2619)
parent
adc50d46
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
32 additions
and
47 deletions
+32
-47
ECDSA.sol
contracts/utils/cryptography/ECDSA.sol
+4
-0
sign.js
test/helpers/sign.js
+1
-20
ECDSA.test.js
test/utils/cryptography/ECDSA.test.js
+25
-25
SignatureChecker.test.js
test/utils/cryptography/SignatureChecker.test.js
+2
-2
No files found.
contracts/utils/cryptography/ECDSA.sol
View file @
1488d4f6
...
@@ -22,6 +22,10 @@ library ECDSA {
...
@@ -22,6 +22,10 @@ library ECDSA {
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
// Divide the signature in r, s and v variables
// Divide the signature in r, s and v variables
...
...
test/helpers/sign.js
View file @
1488d4f6
...
@@ -4,23 +4,6 @@ function toEthSignedMessageHash (messageHex) {
...
@@ -4,23 +4,6 @@ function toEthSignedMessageHash (messageHex) {
return
web3
.
utils
.
sha3
(
Buffer
.
concat
([
prefix
,
messageBuffer
]));
return
web3
.
utils
.
sha3
(
Buffer
.
concat
([
prefix
,
messageBuffer
]));
}
}
function
fixSignature
(
signature
)
{
// in geth its always 27/28, in ganache its 0/1. Change to 27/28 to prevent
// signature malleability if version is 0/1
// see https://github.com/ethereum/go-ethereum/blob/v1.8.23/internal/ethapi/api.go#L465
let
v
=
parseInt
(
signature
.
slice
(
130
,
132
),
16
);
if
(
v
<
27
)
{
v
+=
27
;
}
const
vHex
=
v
.
toString
(
16
);
return
signature
.
slice
(
0
,
130
)
+
vHex
;
}
// signs message in node (ganache auto-applies "Ethereum Signed Message" prefix)
async
function
signMessage
(
signer
,
messageHex
=
'0x'
)
{
return
fixSignature
(
await
web3
.
eth
.
sign
(
messageHex
,
signer
));
};
/**
/**
* Create a signer between a contract and a signer for a voucher of method, args, and redeemer
* Create a signer between a contract and a signer for a voucher of method, args, and redeemer
* Note that `method` is the web3 method, not the truffle-contract method
* Note that `method` is the web3 method, not the truffle-contract method
...
@@ -55,12 +38,10 @@ const getSignFor = (contract, signer) => (redeemer, methodName, methodArgs = [])
...
@@ -55,12 +38,10 @@ const getSignFor = (contract, signer) => (redeemer, methodName, methodArgs = [])
// return the signature of the "Ethereum Signed Message" hash of the hash of `parts`
// return the signature of the "Ethereum Signed Message" hash of the hash of `parts`
const
messageHex
=
web3
.
utils
.
soliditySha3
(...
parts
);
const
messageHex
=
web3
.
utils
.
soliditySha3
(...
parts
);
return
signMessage
(
signer
,
messageHex
);
return
web3
.
eth
.
sign
(
messageHex
,
signer
);
};
};
module
.
exports
=
{
module
.
exports
=
{
signMessage
,
toEthSignedMessageHash
,
toEthSignedMessageHash
,
fixSignature
,
getSignFor
,
getSignFor
,
};
};
test/utils/cryptography/ECDSA.test.js
View file @
1488d4f6
const
{
expectRevert
}
=
require
(
'@openzeppelin/test-helpers'
);
const
{
expectRevert
}
=
require
(
'@openzeppelin/test-helpers'
);
const
{
toEthSignedMessageHash
,
fixSignature
}
=
require
(
'../../helpers/sign'
);
const
{
toEthSignedMessageHash
}
=
require
(
'../../helpers/sign'
);
const
{
expect
}
=
require
(
'chai'
);
const
{
expect
}
=
require
(
'chai'
);
...
@@ -46,6 +46,30 @@ contract('ECDSA', function (accounts) {
...
@@ -46,6 +46,30 @@ contract('ECDSA', function (accounts) {
});
});
context
(
'recover with valid signature'
,
function
()
{
context
(
'recover with valid signature'
,
function
()
{
context
(
'using web3.eth.sign'
,
function
()
{
it
(
'returns signer address with correct signature'
,
async
function
()
{
// Create the signature
const
signature
=
await
web3
.
eth
.
sign
(
TEST_MESSAGE
,
other
);
// Recover the signer address from the generated message and signature.
expect
(
await
this
.
ecdsa
.
recover
(
toEthSignedMessageHash
(
TEST_MESSAGE
),
signature
,
)).
to
.
equal
(
other
);
});
it
(
'returns a different address'
,
async
function
()
{
const
signature
=
await
web3
.
eth
.
sign
(
TEST_MESSAGE
,
other
);
expect
(
await
this
.
ecdsa
.
recover
(
WRONG_MESSAGE
,
signature
)).
to
.
not
.
equal
(
other
);
});
it
(
'reverts with invalid signature'
,
async
function
()
{
// eslint-disable-next-line max-len
const
signature
=
'0x332ce75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e01c'
;
await
expectRevert
(
this
.
ecdsa
.
recover
(
TEST_MESSAGE
,
signature
),
'ECDSA: invalid signature'
);
});
});
context
(
'with v0 signature'
,
function
()
{
context
(
'with v0 signature'
,
function
()
{
// Signature generated outside ganache with method web3.eth.sign(signer, message)
// Signature generated outside ganache with method web3.eth.sign(signer, message)
const
signer
=
'0x2cc1166f6212628A0deEf2B33BEFB2187D35b86c'
;
const
signer
=
'0x2cc1166f6212628A0deEf2B33BEFB2187D35b86c'
;
...
@@ -120,30 +144,6 @@ contract('ECDSA', function (accounts) {
...
@@ -120,30 +144,6 @@ contract('ECDSA', function (accounts) {
await
expectRevert
(
this
.
ecdsa
.
recover
(
message
,
highSSignature
),
'ECDSA: invalid signature
\'
s
\'
value'
);
await
expectRevert
(
this
.
ecdsa
.
recover
(
message
,
highSSignature
),
'ECDSA: invalid signature
\'
s
\'
value'
);
});
});
context
(
'using web3.eth.sign'
,
function
()
{
it
(
'returns signer address with correct signature'
,
async
function
()
{
// Create the signature
const
signature
=
fixSignature
(
await
web3
.
eth
.
sign
(
TEST_MESSAGE
,
other
));
// Recover the signer address from the generated message and signature.
expect
(
await
this
.
ecdsa
.
recover
(
toEthSignedMessageHash
(
TEST_MESSAGE
),
signature
,
)).
to
.
equal
(
other
);
});
it
(
'returns a different address'
,
async
function
()
{
const
signature
=
fixSignature
(
await
web3
.
eth
.
sign
(
TEST_MESSAGE
,
other
));
expect
(
await
this
.
ecdsa
.
recover
(
WRONG_MESSAGE
,
signature
)).
to
.
not
.
equal
(
other
);
});
it
(
'reverts with invalid signature'
,
async
function
()
{
// eslint-disable-next-line max-len
const
signature
=
'0x332ce75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e01c'
;
await
expectRevert
(
this
.
ecdsa
.
recover
(
TEST_MESSAGE
,
signature
),
'ECDSA: invalid signature'
);
});
});
});
});
context
(
'toEthSignedMessage'
,
function
()
{
context
(
'toEthSignedMessage'
,
function
()
{
...
...
test/utils/cryptography/SignatureChecker.test.js
View file @
1488d4f6
const
{
toEthSignedMessageHash
,
fixSignature
}
=
require
(
'../../helpers/sign'
);
const
{
toEthSignedMessageHash
}
=
require
(
'../../helpers/sign'
);
const
{
expect
}
=
require
(
'chai'
);
const
{
expect
}
=
require
(
'chai'
);
...
@@ -14,7 +14,7 @@ contract('SignatureChecker (ERC1271)', function (accounts) {
...
@@ -14,7 +14,7 @@ contract('SignatureChecker (ERC1271)', function (accounts) {
before
(
'deploying'
,
async
function
()
{
before
(
'deploying'
,
async
function
()
{
this
.
signaturechecker
=
await
SignatureCheckerMock
.
new
();
this
.
signaturechecker
=
await
SignatureCheckerMock
.
new
();
this
.
wallet
=
await
ERC1271WalletMock
.
new
(
signer
);
this
.
wallet
=
await
ERC1271WalletMock
.
new
(
signer
);
this
.
signature
=
fixSignature
(
await
web3
.
eth
.
sign
(
TEST_MESSAGE
,
signer
)
);
this
.
signature
=
await
web3
.
eth
.
sign
(
TEST_MESSAGE
,
signer
);
});
});
context
(
'EOA account'
,
function
()
{
context
(
'EOA account'
,
function
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment