Я хотел бы использовать пару ключей одной из моих учетных записей Ethereum, чтобы подписать часть данных. Как это может быть сделано?
В JSON RPC API есть функция, еще не перенесенная на web3, чтобы подписывать данные напрямую одним вызовом функции RPC , не возясь с ключами и криптографией. Если вам не нужно подписывать сообщения на стороне клиента (поскольку для этого требуется соединение rpc и учетная запись должна быть разблокирована), вы можете использовать eth_sign .
eth_sign принимает два параметра: адрес, который вы разблокировали в Geth, eth или pyethapp, и данные, которые вы хотите подписать.
Вот пример запроса, который вы можете сделать со curl
своего терминала, конечно, вы можете использовать свой любимый язык программирования и библиотеки, чтобы сделать этот запрос:
// 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"
}
Бит «результат» в json содержит ваше подписанное сообщение в шестнадцатеричном формате.
0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
eth_sign
и, следовательно, вызовы более высокого уровня, например, web3.eth.sign
сначала хэшируют сообщение перед подписью, что позволяет получить вывод фиксированной длины, который затем может быть проанализирован в r/s/v для ecrecover
.Во-первых, вам понадобится закрытый ключ для вашей учетной записи. Чтобы сгенерировать новый ключ, я использую elliptic.js
:
import {ec as EC} from 'elliptic';
const ec = new EC('secp256k1');
const keypair = ec.genKeyPair();
Если у вас есть ключ в узле Ethereum, вы можете использовать keythereum
его для импорта. Это также даст вам elliptic.js
ключ.
Когда у вас есть ключ, вам понадобится криптобиблиотека и некоторый код, чтобы склеить все это вместе. Я использую Crypto-JS
в этом коде:
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));
}
Как упоминалось в этом ответе , если у вас есть доступ к узлу RPC или geth
, проще всего использовать встроенные eth_sign
функции.
Существуют различные библиотеки для Javascript, которые позволяют вам делать это вручную, если вы не боитесь писать код. Пример показывает Ниран .
Если у вас есть (или вы довольны) node.js
среда, вы можете попробовать helpeth , который представляет собой инструмент командной строки для управления ключами и подписи:
$ 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
Просто используйте MyEtherWallet, который поддерживает подпись и проверку сообщений в вашем браузере через: https://www.myetherwallet.com/signmsg.html .
Только что протестировано:
{
"address":"0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf",
"msg":"Signing a Message with the first best available private key for 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf. | 20 APR 2017 09:46:48",
"sig":"0x85589aa36c3d5e1080e17220ae33768c42054b519cf90934bffd92b341dc1b6e4f2f632e21cf3ad104db746a02c8126a2cbb4232ee5c5b7d40085e598e5460351c"
}
Эта проблема возникла у меня недавно, поэтому я предоставлю последнее решение, которое сработало. В первую очередь с использованием инструментов Ethereum в JavaScript и проверки в сети.
Рабочий минимальный тестовый пример можно найти здесь: https://github.com/AdamJLemmon/ethereum-signing .
Примечание: truffle version 4.1.14
иweb3 version 0.20.6
Начиная с самого начала может быть создана новая учетная запись. Доступ к адресу и закрытому ключу можно получить непосредственно из нового кошелька:
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');
Затем можно указать данные для подписи и взять хэш:
const messageToSign = 'adamjlemmon';
const hash = web3.sha3(messageToSign);
Наконец, эти данные могут быть подписаны:
const sig = await generateSignature(hash, privateKey);
Где generateSignature
следующее:
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);
}
Я не буду публиковать здесь исходный код контракта, но его можно найти в связанном тестовом примере выше и отметить здесь: https://github.com/AdamJLemmon/ethereum-signing/blob/master/contracts/TestVerification.sol
q9f