Как я могу подписать часть данных закрытым ключом адреса Ethereum?

Я хотел бы использовать пару ключей одной из моих учетных записей Ethereum, чтобы подписать часть данных. Как это может быть сделано?

Ответы (5)

В 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
как я могу разблокировать учетную запись, используя закрытый ключ вместо пароля учетной записи @makvoid
чтобы ответить на ваш вопрос, вы можете использовать что-то вроде keythereum ( github.com/ethereumjs/keythereum ), чтобы преобразовать ваш незашифрованный закрытый ключ в зашифрованный формат, использующий geth/parity. Затем вы можете написать/скопировать его в каталог ключей (вы можете написать сценарий этого шага) вашей установки geth/parity, а затем следовать моему ответу --- В противном случае вы можете использовать другую библиотеку, например ethereumjs-utils, и использовать свой закрытый ключ для прямой подписи. : github.com/ethereumjs/ethereumjs-util/blob/master/index.js#L339 (источник)
Пожалуйста, просмотрите мой дополнительный вопрос: ethereum.stackexchange.com/questions/36561/…
Как я могу проверить это шестнадцатеричное подписанное сообщение на прочность?
Важно отметить (потому что никто не упоминает об этом), что 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));
}
Примечание. Если можно использовать альтернативу CryptoJS, модуль js-sha3 в NPM может создавать стандартные хэши SHA-3, поскольку CryptoJS.SHA3 не был обновлен до стандарта SHA-3 FIPS 202.
Неплохо подмечено. Хеши Ethereum «SHA3» — это хэши Keccak. Crypto-JS все еще устарел и неправильно называет Keccak «SHA3», но, вероятно, это именно та хэш-функция, которая вам нужна. medium.com/@ConsenSys/…

Как упоминалось в этом ответе , если у вас есть доступ к узлу 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