Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | 1x 1x 1x 9x 1x 1x 1x 1x 1x 1x 1x 2182x 2182x 2182x 2182x 2182x 2182x 2182x 156x 156x 156x 156x 156x 156x 156x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 1241x 41x 1200x 1200x 21x 450x 450x 450x 450x 450x 450x 2182x 2182x 2182x 2182x 2182x 2182x 2182x 2182x 2182x 2182x 450x 1x 1x | "use strict"; var __importStar = (this && this.__importStar) || function (mod) { Iif (mod && mod.__esModule) return mod; var result = {}; Eif (mod != null) for (var k in mod) Eif (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); /** * Copyright 2019 NEM * * Licensed under the BSD 2-Clause License (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://opensource.org/licenses/BSD-2-Clause * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ const nacl = __importStar(require("tweetnacl")); const bs58check = require('bs58check'); // internal dependencies const index_1 = require("../../index"); /** * Implementation of CKDPriv() function as described in SLIP-10 * for multi-curve BIP32 compatibility with ED25519. * * Difference to BIP32: * - Using 64-bytes master private key instead 32-bytes. * * @see https://cardanolaunch.com/assets/Ed25519_BIP.pdf * @see https://github.com/satoshilabs/slips/blob/master/slip-0010.md * @see https://github.com/alepop/ed25519-hd-key/blob/master/src/index.ts#L36 * @param parent {NodeEd25519} * @param index {number} * @param macType {MACType} * @return {NodeEd25519} */ const CKDPriv = (parent, index, macType = index_1.MACType.HMAC) => { const indexBuffer = Buffer.allocUnsafe(4); indexBuffer.writeUInt32BE(index, 0); // 0x00 || privateKey || index const data = Buffer.concat([Buffer.alloc(1, 0), parent.privateKey, indexBuffer]); // derive with said `macType` MAC algorithm const I = index_1.MACImpl.create(macType, parent.chainCode, data); // IL = privateKey ; IR = chainCode const IL = I.slice(0, 32); const IR = I.slice(32); return new NodeEd25519(IL, undefined, IR, parent.network); }; /** * Class `NodeEd25519` describes a hyper-deterministic BIP32 node * implementation, compatible with ed25519 EC-curve. * * It is an implementation of BIP32 that is adapted to work with * ED25519 ellyptic curve keys rather than secp256k1 keys. * * This class *uses* features provided by the `bitcoinjs/bip32` package * and therefor is licensed under the BSD-2 Clause License as mentioned * [here](https://github.com/bitcoinjs/bip32/blob/master/LICENSE). * * @see https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki * @see https://github.com/satoshilabs/slips/blob/master/slip-0010.md * @see https://github.com/bitcoinjs/bip32 * @see https://github.com/nemtech/NIP/issues/12 * @since 0.2.0 */ class NodeEd25519 extends index_1.DeterministicKey { // private readonly __D: Buffer | undefined // private Key // private __Q: Buffer | undefined // public Key /** * Create a hyper-deterministic ED25519 node from a * binary seed. * * Depending on the curve algorithm, the seed is prepended with one of: * * - `ed25519 seed` for ed25519[-sha512] implementation (Network.SYMBOL) * * @see https://github.com/bitcoinjs/bip32/blob/master/src/bip32.js#L258 * @param seed {Buffer} * @param network {Network} * @return {NodeInterface} */ static fromSeed(seed, network, macType = index_1.MACType.HMAC) { Iif (seed.length < 16) throw new TypeError('Seed should be at least 128 bits'); Iif (seed.length > 64) throw new TypeError('Seed should be at most 512 bits'); // (1) depending on curve algorithm, prepend the seed with one of: // `ed25519 seed` for ed25519[-sha512] implementation (Network.SYMBOL) const prefix = 'ed25519 seed'; const I = index_1.MACImpl.create(macType, Buffer.from(prefix, 'utf8'), seed); // (2) Split in 2 parts: privateKey and chainCode const kL = I.slice(0, 32); const kR = I.slice(32); // kL = privateKey ; kR = chainCode return new NodeEd25519(kL, undefined, kR, network); } /** * Decode a base58 extended key payload into its' * `NodeEd25519` object representation. * * This method parses the base58 binary data and * uses read fields to initialize a BIP32-ED25519 * hyper-deterministic node. * * No ED25519 changes have been done here. * * @see https://github.com/bitcoinjs/bip32/blob/master/ts-src/bip32.ts#L286 * @param inString {string} The base58 payload of the extended key. * @param network {Network} (Optional) The network of the key. * @return {NodeEd25519} */ static fromBase58(inString, network) { // decode base58 const buffer = bs58check.decode(inString); Iif (buffer.length !== 78) { throw new TypeError('Base58 payload must be exactly 78 bytes, but got: ' + buffer.length + ' bytes.'); } // 4 bytes: version bytes const version = buffer.readUInt32BE(0); Iif (version !== index_1.Network.SYMBOL.privateKeyPrefix && version !== index_1.Network.SYMBOL.publicKeyPrefix) { throw new TypeError('Payload Version must be one of: ' + index_1.Network.SYMBOL.privateKeyPrefix + ' or ' + index_1.Network.SYMBOL.publicKeyPrefix + '.'); } // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ... const depth = buffer[4]; // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key) const parentFingerprint = buffer.readUInt32BE(5); // if depth is 0, parentFingerprint must be 0x00000000 (master node) Iif (depth === 0 && parentFingerprint !== 0x00000000) { throw new TypeError('Expected master node but got child with parentFingerprint: ' + parentFingerprint + '.'); } // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized. // This is encoded in MSB order. (0x00000000 if master key) const index = buffer.readUInt32BE(9); // If depth is 0, index must also be 0 (master node) Iif (depth === 0 && index !== 0) { throw new TypeError('Expected index 0 with depth 0 but got index: ' + index + '.'); } // 32 bytes: the chain code const chainCode = buffer.slice(13, 45); let hd; Iif (version === index_1.Network.SYMBOL.privateKeyPrefix) { // 33 bytes: private key data (0x00 + k) if (buffer.readUInt8(45) !== 0x00) { throw new TypeError('Private key must start be prepended by 0x00.'); } // extract private key (32 bytes) const k = buffer.slice(46, 78); // k = privateKey (createFromPrivateKey) hd = new NodeEd25519(k, undefined, chainCode, network, depth, index, parentFingerprint); } else { // 33 bytes: public key data (0x02 + X or 0x03 + X) // extract public key (33 bytes) const X = buffer.slice(45, 78); // X = publicKey hd = new NodeEd25519(undefined, X, chainCode, network, depth, index, parentFingerprint); } return hd; } /** * Getter for the `publicKey` of the key. * * @access public * @return {Buffer} */ get publicKey() { if (this.getQ() !== undefined) { return this.getQ(); } // use tweetnacl to generate key pair (SHA512) const keyPair = nacl.sign.keyPair.fromSeed(this.privateKey); return Buffer.from(keyPair.publicKey); } /** * Get the neutered node. * * @access public * @return {NodeInterface} */ neutered() { return new NodeEd25519(undefined, this.publicKey, this.chainCode, this.network, this.getDepth(), this.getIndex(), this.getParentFingerprint()); } /** * Generic child derivation. * * This method reads the derivation paths and uses `derive` * and `deriveHardened` accordingly. * * Derivation paths starting with `m/` are only possible * with master nodes (for example created from seed). * * @param index {number} * @return {NodeInterface} */ derivePath(path) { Iif (!this.isValidPath(path)) { throw new TypeError('Invalid BIP32 derivation path provided.'); } let splitPath = path.split('/'); // check whether current node is a master node, // if not: "m/" derivation is not possible. Iif (splitPath[0] === 'm' && this.getParentFingerprint()) { throw new TypeError('Expected master node with "m" derivation, but got child with parentFingerprint.'); } // drop first level path "m" Eif (splitPath[0] === 'm') { splitPath = splitPath.slice(1); } // apply derivation for each path level return splitPath.reduce((prevHd, indexStr) => { let index; // Always use hardened key derivation index = parseInt(indexStr.replace(/'/, ''), 10); return prevHd.deriveHardened(index); }, this); } /** * Hardened child derivation (derives private key). * * @internal Do not use this method directly, please use the `derivePath()` method instead. * @param index {number} * @return {NodeInterface} */ deriveHardened(index) { const UINT31_MAX = Math.pow(2, 31) - 1; Iif (index > UINT31_MAX) { throw new TypeError('Hardened derivation maximum index overflow.'); } // Only derives hardened private keys by default return this.derive(index + NodeEd25519.HIGHEST_BIT); } /** * Derive a child node with `index`. * * When the node is *not neutered*, an extended private * key will be created and when the node is *neutered*, * an extended public key will be created. * * This method is an overload of the `bitcoinjs/bip32` * package's `derive` method adapted to use *our* child * key derivation functions `CKDPriv` and `CKDPub`. * * @see https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions * @internal Do not use this method directly, please use the `derivePath()` method instead. * @param index {number} * @return {NodeInterface} */ derive(index) { // check derivation validity const isHardened = index >= NodeEd25519.HIGHEST_BIT; Iif (isHardened && this.isNeutered()) { throw new TypeError('Missing private key for hardened child key derivation.'); } // Parent key is current node const parentKey = this; Eif (!this.isNeutered()) { // (1) Private parent key -> private child key // use ED25519-adapted child key derivation function return CKDPriv(parentKey, index); } // (2) Public parent key -> public child key // This is not possible with our implementation throw new Error('Non-Hardened key derivation is not permitted with ED25519 curve.'); } /** * Sign binary data with current node. * * Overloads the `bitcoinjs/bip32` method named `sign` in order to * be ED25519 compliant and use `tweetnacl` with ed25519 instead * of secp256k1. * * @see https://github.com/bitcoinjs/bip32/blob/master/ts-src/bip32.ts#L277 * @param hash {Buffer} The binary data to sign. * @return {NodeInterface} */ sign(hash) { // use tweetnacl to generate key pair (SHA512) const keyPair = nacl.sign.keyPair.fromSeed(this.privateKey); // generate shared secret const secretKey = new Uint8Array(64); secretKey.set(this.privateKey); secretKey.set(keyPair.publicKey, 32); // use tweetnacl to sign const signature = nacl.sign.detached(hash, secretKey); return Buffer.from(signature); } /** * Verify a signature `signature` for data * `hash` with the current node. * * Overloads the `bitcoinjs/bip32` method named `verify` in order to * be ED25519 compliant and use `tweetnacl` with ed25519 instead * of secp256k1. * * @see https://github.com/bitcoinjs/bip32/blob/master/ts-src/bip32.ts#L281 * @param hash {Buffer} The binary data that was supposedly signed. * @param signature {Buffer} The signature binary data that needs to be verified. * @return {boolean} Returns true for a valid signature, false otherwise. */ verify(hash, signature) { // use tweetnacl to verify signature return nacl.sign.detached.verify(hash, signature, this.publicKey); } /** * Validate a BIP32/BIP44 path by regular expression. * * @see https://github.com/bitcoinjs/bip32/blob/master/src/bip32.js#L26 * @param path {string} * @return {boolean} */ isValidPath(path) { return path.match(/^(m\/)?(\d+'?\/)*\d+'?$/) !== null; } } exports.NodeEd25519 = NodeEd25519; /** * Hardened key derivation uses HIGHEST_BIT. * @var number */ NodeEd25519.HIGHEST_BIT = 0x80000000; |