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 | 1x 177x 176x 175x 174x 173x 172x 171x 170x 169x 120x 82x 34x 48x 47x 47x 47x 47x 149x 99x 99x 99x 99x 99x 99x 99x 47x 46x 46x 146x 146x 146x 146x 46x 1x | /** * @file Secret Recovery * @copyright Multifactor 2022 All Rights Reserved * * @description * Recover original shares of a secret from shares using various methods * * @author Vivek Nair (https://nair.me) <[email protected]> */ const secrets = require('secrets.js-34r7h') /** * K-of-N secret recovery. Uses bitwise XOR for k=n, Shamir's Secret Sharing for 1 < K < N, and direct secret sharing for K = 1. * * @example * // share secret using 2-of-3 shares * const shares = mfkdf.secrets.share(Buffer.from('hello world'), 2, 3) // -> [Buffer, Buffer, Buffer] * * // recover secret using 2 shares * const secret = mfkdf.secrets.combine([shares[0], null, shares[2]], 2, 3) * secret.toString() // -> hello world * * // recover original 3 shares * const recover = mfkdf.secrets.recover([shares[0], null, shares[2]], 2, 3) // -> [Buffer, Buffer, Buffer] * * @param {Array.<Buffer>} shares - The secret shares to be combined * @param {number} k - The threshold of shares required to reconstruct the secret * @param {number} n - The number of shares that were originally generated * @returns {Buffer} The retrieved secret as a Buffer * @author Vivek Nair (https://nair.me) <[email protected]> * @since 0.8.0 * @memberOf secrets */ function recover (shares, k, n) { if (!Array.isArray(shares)) throw new TypeError('shares must be an array') if (shares.length === 0) throw new RangeError('shares must not be empty') if (!Number.isInteger(n)) throw new TypeError('n must be an integer') if (!(n > 0)) throw new RangeError('n must be positive') if (!Number.isInteger(k)) throw new TypeError('k must be an integer') if (!(k > 0)) throw new RangeError('k must be positive') if (k > n) throw new RangeError('k must be less than or equal to n') if (shares.length < k) throw new RangeError('not enough shares provided to retrieve secret') if (k === 1) { // 1-of-n return Array(n).fill(shares.filter(x => Buffer.isBuffer(x))[0]) } else if (k === n) { // n-of-n return shares } else { // k-of-n if (shares.length !== n) throw new RangeError('provide a shares array of size n; use NULL for unknown shares') const bits = Math.max(Math.ceil(Math.log(n + 1) / Math.LN2), 3) secrets.init(bits) const formatted = [] for (const [index, share] of shares.entries()) { if (share) { let value = Number(bits).toString(36) // bits const maxIdLength = (Math.pow(2, bits) - 1).toString(16).length value += (index + 1).toString(16).padStart(maxIdLength, '0') // id let hex = share.toString('hex') if (hex.charAt(0) === '0') hex = hex.substring(1) value += hex formatted.push(value) } } if (formatted.length < k) throw new RangeError('not enough shares provided to retrieve secret') const newShares = [] for (let i = 0; i < n; i++) { const newShare = secrets.newShare(i + 1, formatted) const components = secrets.extractShareComponents(newShare) if (components.data.length % 2 === 1) components.data = '0' + components.data newShares.push(Buffer.from(components.data, 'hex')) } return newShares } } module.exports.recover = recover |