Wie kann ich ein Datenelement mit dem privaten Schlüssel einer Ethereum-Adresse signieren?

Ich möchte das Schlüsselpaar eines meiner Ethereum-Konten verwenden, um ein Datenelement zu signieren. Wie kann dies geschehen?

Antworten (5)

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 curlvon 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
Wie kann ich das Konto mit dem privaten Schlüssel anstelle des Kontokennworts @makvoid entsperren?
Um Ihre Frage zu beantworten, können Sie so etwas wie keythereum ( github.com/ethereumjs/keythereum ) verwenden, um Ihren (nicht verschlüsselten) privaten Klartextschlüssel in das verschlüsselte Format geth/parity use zu konvertieren. Dann können Sie es in das Schlüsselverzeichnis (Sie können diesen Schritt skripten) Ihrer Geth/Parity-Installation schreiben/kopieren und dann meiner Antwort folgen --- Andernfalls können Sie eine andere Bibliothek wie ethereumjs-utils verwenden und Ihren privaten Schlüssel direkt zum Signieren verwenden : github.com/ethereumjs/ethereumjs-util/blob/master/index.js#L339 (Quelle)
Bitte sehen Sie sich meine Folgefrage an: ethereum.stackexchange.com/questions/36561/…
Wie kann ich diese verhexte signierte Nachricht auf Solidität überprüfen?
Es ist wichtig zu beachten (weil niemand es erwähnt), dass eth_signund daher Aufrufe auf höherer Ebene wie web3.eth.signzuerst 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.jsSchlüssel.

Sobald Sie einen Schlüssel haben, benötigen Sie eine Kryptobibliothek und etwas Code, um alles zusammenzufügen. Ich verwende Crypto-JSin 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));
}
Hinweis: Wenn eine Alternative zu CryptoJS verwendbar ist, kann das js-sha3-Modul auf NPM SHA-3-Standard-Hashes erzeugen, da CryptoJS.SHA3 nicht auf den SHA-3 FIPS 202-Standard aktualisiert wurde.
Das ist ein guter Punkt. Die „SHA3“-Hashes von Ethereum sind Keccak-Hashes. Crypto-JS ist immer noch veraltet und nennt Keccak fälschlicherweise „SHA3“, aber es ist wahrscheinlich die gewünschte Hash-Funktion. medium.com/@ConsenSys/…

Wie in dieser Antwortgeth erwähnt, ist es am einfachsten, die integrierte eth_signFunktionalitä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.14undweb3 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 generateSignaturesteht 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