Сохранение твердости и web3j Sign.signMessage () несовместимы, не так ли?

Использование Web3j для подписания и проверки сообщения в порядке, но когда я использую подпись, сгенерированную Web3j, для проверки с помощью ecrecover в целом, она не работает правильно. Адрес подписчика отличается при выполнении кода целостности.

При поиске решения я узнал, что новая версия geth добавляет строку «\ x19Ethereum Signed Message: \ n32» при подписании.

Ссылка здесь: Полностью озадачена ecrecover

Я попытался использовать решение в справочном вопросе, но он не работает. Мой вопрос в том, что отличается от Web3j? Может ли кто-нибудь, знакомый с Web3j, предоставить мне рабочий пример для подписания и проверки сообщений?

Вот упрощенная версия контракта, над которым я работал:

pragma solidity ^0.4.0;

contract Auth {   

    string public name;

    function Auth(){
        name = "Auth 1.0";
    }

    function verify(bytes32 _message, uint8 _v, bytes32 _r, bytes32 _s) constant returns (address) {
        address signer = ecrecover(_message, _v, _r, _s);
        return signer;
    }

    function verifyWithPrefix(bytes32 _message, uint8 _v, bytes32 _r, bytes32 _s) constant returns (address) {
        bytes memory prefix = "\x19Ethereum Signed Message:\n32";
        bytes32 prefixedHash = sha3(prefix, _message);
        address signer = ecrecover(prefixedHash, _v, _r, _s);
        return signer;
    }
}

Вот код Java с помощью Web3j.

    // Message to sign
    String plainMessage = "hello world";
    byte[] hexMessage = Hash.sha3(plainMessage.getBytes());

    // Use java to sign and verify the signature
    Sign.SignatureData signMessage = Sign.signMessage(hexMessage, ALICE.getEcKeyPair());
    String pubKey = Sign.signedMessageToKey(hexMessage, signMessage).toString(16);
    String signerAddress = Keys.getAddress(pubKey);
    System.out.println("Signer address    : 0x"+ signerAddress);

    // Now use java signature to verify from the blockchain
    Bytes32 message = new Bytes32(hexMessage);
    Uint8 v = new Uint8(signMessage.getV());
    Bytes32 r = new Bytes32(signMessage.getR());
    Bytes32 s = new Bytes32(signMessage.getS());

    String address = contract.verify(message, v, r, s).get().getValue().toString(16);
    String address2 = contract.verifyWithPrefix(message, v, r, s).get().getValue().toString(16);
    System.out.println("Recovered address1 : 0x"+address);
    System.out.println("Recovered address2 : 0x"+address2);
5 голосов | спросил eth-new-user 11 J0000006Europe/Moscow 2017, 16:19:31

1 ответ


3

Проблема была на самом деле двойным хэшированием.

Просмотр метода signMessage () Web3j

Sign.SignatureData sig =Sign.signMessage(messageBytes, ecKeyPair);

и метод signedMessageToKey ()

String pubKey = Sign.signedMessageToKey(messageBytes, sig).toString(16);

Эти методы внутренне хешируют (sha3) входные сообщенияBytes перед подписанием и проверкой. Это отлично работает, когда обе подписи генерируются и проверяются с использованием самой Web3j. Но это делает подпись Web3j отличной от того, что получено из метода sign () geth.

Вот публичная сущность с модифицированным файлом Sign.java от Web3j, который можно использовать, чтобы избежать двойной проблемы хэширования: https://gist.github.com/xoriole/4c2a9630dba5a20ee28fb58edf193375

ответил eth-new-user 13 J0000006Europe/Moscow 2017, 10:29:45

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132