Ich möchte das Schlüsselpaar eines meiner Ethereum-Konten verwenden, um ein Datenelement zu signieren. Wie kann dies geschehen?
Es gibt eine Funktionalität der JSON-RPC-API, die noch nicht auf web3 portiert wurde, um Daten direkt mit einem RPC-Funktionsaufruf zu signieren , ohne mit Schlüsseln und Krypto herumzuspielen. Wenn Sie Nachrichten nicht clientseitig signieren müssen (weil dies eine RPC-Verbindung erfordert und das Konto entsperrt werden muss), können Sie eth_sign verwenden .
eth_sign akzeptiert zwei Parameter, die Adresse, die Sie in Geth, eth oder pyethapp entsperrt haben, und die Daten, die Sie signieren möchten.
Hier ist eine Beispielanfrage, die Sie curl
von Ihrem Terminal aus stellen können. Natürlich können Sie Ihre bevorzugte Programmiersprache und Bibliotheken verwenden, um diese Anfrage zu stellen:
// parameters:
// address: 0xd1ade25ccd3d550a7eb532ac759cac7be09c2719 (needs to be unlocked)
// message: "Schoolbus"
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sign","params":["0xd1ade25ccd3d550a7eb532ac759cac7be09c2719", "Schoolbus"],"id":1}'
// Result
{
"id":1,
"jsonrpc": "2.0",
"result": "0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601"
}
Das "Ergebnis"-Bit im JSON enthält Ihre signierte Nachricht in Hex.
0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
eth_sign
und daher Aufrufe auf höherer Ebene wie web3.eth.sign
zuerst die Nachricht vor dem Signieren hashen, was eine Ausgabe mit fester Länge ermöglicht, die dann in r/s/v für geparst werden kann ecrecover
.Zunächst benötigen Sie den privaten Schlüssel für Ihr Konto. Um einen brandneuen Schlüssel zu generieren, verwende ich elliptic.js
:
import {ec as EC} from 'elliptic';
const ec = new EC('secp256k1');
const keypair = ec.genKeyPair();
Wenn Sie einen Schlüssel in Ihrem Ethereum-Knoten haben, können Sie ihn verwenden keythereum
, um ihn zu importieren. Dadurch erhalten Sie auch einen elliptic.js
Schlüssel.
Sobald Sie einen Schlüssel haben, benötigen Sie eine Kryptobibliothek und etwas Code, um alles zusammenzufügen. Ich verwende Crypto-JS
in diesem Code:
import BigNumber from 'bignumber.js';
import CryptoJS from 'crypto-js';
type WordArray = object;
// https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v/38909#38909
const UNCOMPRESSED_PUBKEY_HEADER = 27;
/**
* Sign the given hex-encoded bytes.
*/
function signHex(keypair, hex) {
const signature = keypair.sign(hex);
return {
v: UNCOMPRESSED_PUBKEY_HEADER + signature.recoveryParam,
r: new BigNumber(signature.r.toString(16), 16),
s: new BigNumber(signature.s.toString(16), 16),
};
}
/**
* Sign the hash of a message. If the message is a string, it is encoded
* as UTF-8 bytes. As a result, hex-encoded strings are not valid input. They
* must be parsed into WordArrays first.
*/
function signMessageHash(keypair, message) {
const hash: WordArray = CryptoJS.SHA3(message, {outputLength: 256});
return signHex(keypair, hash.toString(CryptoJS.enc.Hex));
}
Wie in dieser Antwortgeth
erwähnt, ist es am einfachsten, die integrierte eth_sign
Funktionalität zu verwenden , wenn Sie Zugriff auf einen RPC-Knoten oder haben.
Es gibt verschiedene Bibliotheken für Javascript, mit denen Sie dies manuell tun können, wenn Sie keine Angst haben, Code zu schreiben. Ein Beispiel zeigt Niran .
Wenn Sie die Umgebung haben (oder gerne verwenden) , können Sie helpethnode.js
ausprobieren, ein Befehlszeilentool zum Verwalten von Schlüsseln und Signieren:
$ helpeth --password 'Use --password-prompt instead for security' --keyfile UTC--2016-03-17T19-06-57.064Z--15f2f3e0f2d74ea7b185fc12f24cb4f402cc96d0 signMessage 'Hello World'
Input message: Hello World
Message hash (Keccak): 0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba
The signature: 0x167760997a69e225c0668e6761cd20cac70f3a6ace29fe2d287c3003daf6972b10d158a47e8f064cf982a3defdf236247c41249dbfb0fb81f0d126c26a94971d01
Verwenden Sie einfach MyEtherWallet, das das Signieren und Verifizieren von Nachrichten in Ihrem Browser unterstützt über: https://www.myetherwallet.com/signmsg.html
Gerade getestet:
{
"address":"0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf",
"msg":"Signing a Message with the first best available private key for 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf. | 20 APR 2017 09:46:48",
"sig":"0x85589aa36c3d5e1080e17220ae33768c42054b519cf90934bffd92b341dc1b6e4f2f632e21cf3ad104db746a02c8126a2cbb4232ee5c5b7d40085e598e5460351c"
}
Dieses Problem ist kürzlich für mich aufgetreten, daher wird die neueste Lösung bereitgestellt, die funktioniert hat. Hauptsächlich Verwendung von Ethereum-Tools in JavaScript und Verifizierung in der Kette.
Den funktionierenden minimalen Testfall finden Sie hier: https://github.com/AdamJLemmon/ethereum-signing
Hinweis: truffle version 4.1.14
undweb3 version 0.20.6
Von Anfang an kann ein brandneues Konto generiert werden. Auf die Adresse und den privaten Schlüssel kann direkt von der neuen Brieftasche aus zugegriffen werden:
const bip39 = require('bip39');
const hdkey = require('ethereumjs-wallet/hdkey');
const mnemonic = bip39.generateMnemonic();
const hdwallet = hdkey.fromMasterSeed(bip39.mnemonicToSeed(mnemonic));
const path = "m/44'/60'/0'/0/0";
const wallet = hdwallet.derivePath(path).getWallet();
const address = `0x${wallet.getAddress().toString('hex')}`;
const privateKey = wallet.getPrivateKey().toString('hex');
Dann können die zu signierenden Daten angegeben und der Hash genommen werden:
const messageToSign = 'adamjlemmon';
const hash = web3.sha3(messageToSign);
Abschließend können diese Daten signiert werden:
const sig = await generateSignature(hash, privateKey);
Wo generateSignature
steht folgendes:
const ethUtil = require("ethereumjs-util");
module.exports = (dataToSign, privateKey) => {
const msg = Buffer.from(dataToSign.replace("0x", ""), "hex");
const msgHash = ethUtil.hashPersonalMessage(msg);
const sig = ethUtil.ecsign(msgHash, new Buffer(privateKey, 'hex'));
return ethUtil.toRpcSig(sig.v, sig.r, sig.s);
}
Ich werde die Vertragsquelle hier nicht posten, aber sie kann im oben verlinkten Testfall gefunden und hier notiert werden: https://github.com/AdamJLemmon/ethereum-signing/blob/master/contracts/TestVerification.sol
q9f