Я пытаюсь получить небольшой пример работы с ECDSA.sol здесь: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/cryptography/ECDSA.sol
Этот контракт:
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
pragma solidity 0.5.8;
import "../../node_modules/openzeppelin-solidity/contracts/cryptography/ECDSA.sol";
contract Sigs {
using ECDSA for bytes32;
function rndHash() public view returns(bytes32) {
return keccak256(abi.encodePacked(block.number));
}
function ethSignedHash(bytes32 messageHash) public pure returns(bytes32) {
return messageHash.toEthSignedMessageHash();
}
function recover(bytes32 hash, bytes memory signature) public pure returns(address) {
return hash.recover(signature);
}
}
На стороне клиента:
Я не уверен, что мне не хватает. Я думаю, что исходный хэш сообщения должен быть подписан, а EIP-712 выполняет «подписание Ethereum», поэтому я должен отправить «хэш Ethereum» в ecrecover (как реализовано в ECDSA.sol). В любом случае, никакая комбинация не приносит никакой радости.
var Sigs = artifacts.require("./Junk/Sigs");
contract("Sigs", accounts => {
var signer;
beforeEach(async () => {
signer = accounts[0];
sigs = await Sigs.new({from: signer});
});
it("should recover signer address.", async () => {
console.log("SIGNER: ", signer);
var random = await sigs.rndHash({from: signer});
var ethHash = await sigs.ethSignedHash(random);
// four possible combinations tried for the next step :/
var signature = await web3.eth.sign(random, signer); // sign the random hash or the ethHash
var recovered = await sigs.recover(ethHash, signature); // recover from the random hash or the ethHash
console.log("random1: ", random);
console.log("signature: ", signature);
console.log("recovered: ", recovered);
assert.strictEqual(recovered, signer, "The recovered signature does not match the signer.");
});
});
Буду очень признателен, если кто-нибудь сможет меня развести.
Truffle v5.0.41 (core: 5.0.41)
Solidity - 0.5.8 (solc-js)
Node v8.10.0
Web3.js v1.2.1
Спасибо!
Обновлять
Для всех, кто сталкивается с этим, это пересмотренный, проходной тест.
const Sigs = artifacts.require("./Junk/Sigs");
const EthCrypto = require("eth-crypto");
contract("Sigs", accounts => {
var signer;
beforeEach(async () => {
signer = accounts[0];
sigs = await Sigs.new({from: signer});
});
it("should recover signer address.", async () => {
console.log("SIGNER: ", signer);
var message = "0x1234";
console.log("message: ", message);
var msgHash = await sigs.messageHash(message);
var ethHash = await sigs.ethSignedHash(msgHash);
var signature = await web3.eth.sign(msgHash, signer); // sign the mesage hash
signature = signature.substr(0, 130) + (signature.substr(130) == "00" ? "1b" : "1c"); // v: 0,1 => 27,28
var recovered = await sigs.recover(ethHash, signature); // recover from the ethHash
console.log("msgHash: ", msgHash);
console.log("ethHash: ", ethHash);
console.log("signature: ", signature);
console.log("recovered: ", recovered);
assert.strictEqual(recovered, signer, "The recovered signature does not match the signer.");
});
});
Проблема в том, что eth.sign
возвращает подпись, где v
0 или 1, и ecrecover
ожидается, что она будет 27 или 28.
Примечание в документации для web3 v0.20 ясно:
Обратите внимание, что если вы используете
ecrecover
,v
будет либо ,"00"
либо"01"
. В результате, чтобы использовать это значение, вам придется преобразовать его в целое число, а затем добавить27
. Это приведет либо к a,27
либо к28
.
Вы должны сделать что-то вроде этого
var signature = await web3.eth.sign(random, signer); // sign the random hash or the ethHash
signature = signature.substr(0, 130) + (signature.substr(130) == "00" ? "1b" : "1c");
var recovered = await sigs.recover(ethHash, signature); // recover from the random hash or the ethHash
Роб, я вижу, что ты уже решил (и это здорово).
Для будущих читателей:
Дополнительные сведения о контрактах OpenZeppelin можно найти в документации, в данном случае в разделе «Криптография»: https://docs.openzeppelin.com/contracts/2.x/utilities#cryptography .
Тесты для контрактов могут быть полезны для просмотра, в данном случае ECDSA.test.js: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/test/cryptography/ECDSA.test.js .
На форуме есть руководство по подписанию: https://forum.openzeppelin.com/t/sign-it-like-you-mean-it-creating-and-verifying-ethereum-signatures/697 .
Если у вас есть вопросы по использованию OpenZeppelin, вы также можете задать их на форуме сообщества: https://forum.openzeppelin.com/
Раскрытие информации: я менеджер сообщества в OpenZeppelin
хорошая вибрация
накидка
openzeppelin-solidity
сейчас@openzeppelin/contracts
. Кроме того, в таких средах, как трюфель, вы можете записать свой импорт как:import "@openzeppelin/contracts/cryptography/ECDSA.sol";
вам не нужно указыватьnode_modules
накидка