Ich versuche hier ein kleines Beispiel für die Arbeit mit ECDSA.sol zu bekommen: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/cryptography/ECDSA.sol
Dieser Vertrag:
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);
}
}
Auf der Client-Seite:
Ich bin mir nicht sicher, was mir fehlt. Ich denke , der ursprüngliche Nachrichten-Hash sollte signiert werden und EIP-712 führt die "Ethereum-Signierung" durch, also sollte ich den "Ethereum-Hash" an ecrecover senden (wie in ECDSA.sol implementiert). Jedenfalls bringt keine Kombination Freude.
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.");
});
});
Ich wäre sehr dankbar, wenn mich jemand aufklären könnte.
Truffle v5.0.41 (core: 5.0.41)
Solidity - 0.5.8 (solc-js)
Node v8.10.0
Web3.js v1.2.1
Danke!
Aktualisieren
Für alle anderen, denen das passiert, ist dies der überarbeitete, bestandene Test.
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.");
});
});
Das Problem ist, dass eth.sign
eine Signatur zurückgegeben wird, bei der v
0 oder 1 ist, und ecrecover
erwartet wird, dass sie 27 oder 28 ist.
Ein Hinweis in der Dokumentation zu web3 v0.20 ist klar:
Beachten Sie, dass wenn Sie verwenden
ecrecover
, entweder oderv
sein wird . Um diesen Wert zu verwenden, müssen Sie ihn daher in eine ganze Zahl parsen und dann hinzufügen . Dies ergibt entweder ein oder ein ."00"
"01"
27
27
28
Sie müssen so etwas tun
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
Rob, wie ich sehe, hast du bereits eine Lösung gefunden (was großartig ist).
Für zukünftige Leser:
Weitere Informationen zu OpenZeppelin-Verträgen finden Sie in der Dokumentation, in diesem Fall im Abschnitt Kryptographie: https://docs.openzeppelin.com/contracts/2.x/utilities#cryptography
Die Tests für die Verträge können hilfreich sein, in diesem Fall ECDSA.test.js: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/test/cryptography/ECDSA.test.js
Im Forum gibt es ein Tutorial zum Signieren: https://forum.openzeppelin.com/t/sign-it-like-you-mean-it-creating-and-verifying-ethereum-signatures/697
Wenn Sie Fragen zur Verwendung von OpenZeppelin haben, können Sie diese auch im Community-Forum stellen: https://forum.openzeppelin.com/
Offenlegung: Ich bin der Community Manager bei OpenZeppelin
gute Stimmung
abcoatup
openzeppelin-solidity
ist jetzt@openzeppelin/contracts
. Auch in Umgebungen wie Truffle können Sie Ihren Import schreiben als:import "@openzeppelin/contracts/cryptography/ECDSA.sol";
Sie müssen nicht angebennode_modules
abcoatup