Addresses
為乙太坊創建離線地址創建者
我發現了這個比特幣紙錢包:https ://bitcoinpaperwallet.com/bitcoinpaperwallet/generate-wallet.html
我想添加它乙太坊只是為了好玩。
在這個問題上,他們展示瞭如何離線創建地址。
我嘗試使用他們正在使用的同一個 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>
這段程式碼大部分是正確的,但有兩個小問題:
- 在散列公鑰之前,您需要刪除第一個字節。第一個字節通常表示密鑰是否被壓縮。在乙太坊中,該值必須始終未壓縮,並且在散列時不包含前綴。
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。)