Создание автономного генератора адресов для Ethereum

Я нашел этот биткойн-бумажный кошелек: https://bitcoinpaperwallet.com/bitcoinpaperwallet/generate-wallet.html .

Я хотел бы добавить это Ethereum просто для удовольствия.

В этом вопросе они показывают, как создать адрес в автономном режиме.

Я пытался использовать ту же библиотеку EllipticCurve, что и они, вы можете проверить это здесь , я думаю, что Elliptic Curve везде одинакова, верно?

На основе этого я создал скрипт, показанный ниже. Я получаю закрытый ключ, открытый ключ и адрес, но... Если я попытаюсь сгенерировать адрес из закрытого ключа с помощью web3, я получу другой.

Любые идеи будут высоко оценены.

<script type="text/javascript">
    //Ethereum - January 2018
    Ethereum.ECDSA = Bitcoin.ECDSA;

    Ethereum.ECKey = (function() {

        var ECDSA = Ethereum.ECDSA;
        var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
        var rng = new SecureRandom();

        var ECKey = function (input) {
            console.log("ethereum input");
            console.log(input);
            if (!input) {
                var n = ecparams.getN();
                console.log("getN");

                this.priv = ECDSA.getBigRandom(n);
                console.log();
                console.log("this.priv");
                console.log(this.priv);
                console.log("====");
            }
        }

        ECKey.prototype.getEthereumAddress = function () {

            console.log("getEthereumAddress");
            var hash = this.getPubKeyHash();
            console.log("hashEther");
            console.log(hash);
            var ola =  Crypto.util.bytesToHex(hash).toString().toUpperCase();
            console.log("ola");
            console.log(ola);

            //var sourceAddress = keccak256(hash);



            var sourceBuffer = keccak256.buffer(hash).slice(-20);
            address = this.buffer2Hex(sourceBuffer);

            console.log("AAAAAA");
            console.log(address);
            return address.toString();
        };

        /*
         * Return public key as a byte array in DER encoding
         */
        ECKey.prototype.getPub = function () {

            console.log("getPub");
                if (this.pubUncomp) return this.pubUncomp;
                return this.pubUncomp = this.getPubPoint().getEncoded(0);

        };

        ECKey.prototype.getPubKeyHash = function () {
            console.log("getPubKeyHashx");
            console.log(this.getPub());
            console.log("====");
            if (this.pubKeyHashUncomp) return this.pubKeyHashUncomp;
            return this.pubKeyHashUncomp = this.getPub();

        };

        /**
         * Return public point as ECPoint object.
         */
        ECKey.prototype.getPubPoint = function () {
            if (!this.pubPoint) {
                this.pubPoint = ecparams.getG().multiply(this.priv);
                this.pubPoint.compressed = this.compressed;
            }
            return this.pubPoint;
        };

        ECKey.prototype.buffer2Hex = function(buffer) { // buffer is an ArrayBuffer
            return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16))).join('');
        }

        /**
         * Set whether the public key should be returned compressed or not.
         */
        ECKey.prototype.setCompressed = function (v) {
            this.compressed = !!v;
            if (this.pubPoint) this.pubPoint.compressed = this.compressed;
            return this;
        };

        // Private Key Hex Format
        ECKey.prototype.getEthereumPrivateKeyHexFormat = function () {
            var ola =  Crypto.util.bytesToHex(this.getEthereumPrivateKeyByteArray()).toString().toUpperCase();
            console.log("getBitcoinHexFormat");
            console.log(ola);
            return ola;
        };

        ECKey.prototype.getEthereumAddressHexFormat = function () {
            var ola =  Crypto.util.bytesToHex(this.getEthereumPrivateKeyByteArray()).toString().toUpperCase();
            console.log("getBitcoinHexFormat");
            console.log(ola);
            return ola;
        };

        ECKey.prototype.getEthereumPrivateKeyByteArray = function () {
            // Get a copy of private key as a byte array
            var bytes = this.priv.toByteArrayUnsigned();
            // zero pad if private key is less than 32 bytes
            while (bytes.length < 32) bytes.unshift(0x00);
            return bytes;
        };

        // Sipa Private Key Wallet Import Format
        ECKey.prototype.getEthereumPrivateKey = function () {
            console.log("getEthereumPrivateKey");
            var bytes = this.getEthereumPrivateKeyByteArray();
            return Crypto.util.bytesToHex(bytes).toString().toUpperCase();
        };


        return ECKey;
    })();


    </script>

Ответы (1)

Этот код в основном правильный, но есть две небольшие проблемы:

  1. Прежде чем хешировать открытый ключ, вам нужно удалить первый байт. Первый байт часто указывает, сжат ключ или нет. В Ethereum значение всегда должно быть несжатым, и вы не включаете префикс при хешировании.
  2. buffer2Hexкажется сломанным.

Вот исправленная версия getEthereumAddress:

ECKey.prototype.getEthereumAddress = function () {
  return Crypto.util.bytesToHex(
    keccak256.array(
      this.getPub().slice(1) // drop the 1-byte prefix
    ).slice(-20));           // take the last 20 bytes
};

(Если keccak256.arrayдля вас не существует, возможно, вы используете другую библиотеку, чем я. Я использовал js-sha3 .)

Спасибо!!! это была моя ошибка. Можете ли вы дать мне свой адрес электронной почты или твиттер или LinkedIn? ты спасатель!!
smarx@smarx.com, @smarx
Спасибо @smarx. Может быть, вы можете помочь мне с этим: ethereum.stackexchange.com/questions/36036/…
еще один вопрос: если пользователь вводит случайную строку в качестве семени для генерации адреса, будет ли это действительным? var bytes = Crypto.charenc.UTF8.stringToBytes(поставляетсяKey)); this.priv = новый BigInteger (байты); Если пользователь вводит строку закрытого ключа, будет ли это действительным? var bytes = Crypto.util.hexToBytes (privStr); this.priv = новый BigInteger (байты);
Я новичок в этом, и я получил смесь среди всех монет! :D