import secrets from "../lib/secrets"; import { encryptMessage } from "./signingUtilities"; import { encodeResponse } from "./appUtility"; import { getSliceRange } from "./numberUtilities"; import { THRESHOLD } from "../constants/secrets"; /** Initialize */ export const initSecrets = (bits, rngType) => secrets.init(bits, rngType); export const setRNG = rngType => secrets.setRNG(rngType); export const getSecretsConfig = () => secrets.getConfig(); /** * Function generates a random bits length string, and output it in hexadecimal format * * @param {number} bits * @returns {string} hex */ export const generateSecret = bits => secrets.random(bits); /** * Divide a secret expressed in hexadecimal form into numShares number of shares, requiring that threshold number of shares be present for reconstructing the secret * * @param {string} secret * @param {number} numShares * @param {number} threshold * @param {number} [padLength=128] * @returns {array} */ export const divideSecretToShares = ( secret, numShares, threshold, padLength = 128 ) => secrets.share(secret, numShares, threshold, padLength); /** * Reconstructs a secret from shares * * @param {array} shares * @returns {string} */ export const combineSecret = shares => secrets.combine(shares); export const encryptShare = async (share, publicKey) => await encryptMessage(share, publicKey, "secretPart"); /** Account Recovery key management */ export const generateRecoveryKey = () => { const recoveryKey = generateSecret(512); return recoveryKey; }; export const getRecoveryKeyShares = (recoveryKey, sharesNumber) => { return divideSecretToShares(recoveryKey, sharesNumber, THRESHOLD); }; function getSecretSliceRange(max) { const { beginIndex, endIndex } = getSliceRange(max); if (endIndex - beginIndex < THRESHOLD) { return getSecretSliceRange(max); } return { beginIndex, endIndex }; } export const checkRecoveryKeyCombine = (recoveryKey, recoveryKeyShares) => { let checkKey; const { beginIndex, endIndex } = getSecretSliceRange( recoveryKeyShares.length + 1 ); console.log({ beginIndex, endIndex }); checkKey = combineSecret(recoveryKeyShares.slice(beginIndex, endIndex)); if (checkKey !== recoveryKey) { return encodeResponse( "400", "", "Sanity check with required number of shares failed" ); } checkKey = combineSecret(recoveryKeyShares.slice(0, 1)); if (checkKey === recoveryKey) { return encodeResponse( "400", "", "Sanity check with less than required shares failed" ); } checkKey = combineSecret(recoveryKeyShares); if (checkKey !== recoveryKey) { return encodeResponse("400", "", "Sanity check with all shares failed"); } return encodeResponse("200", "", "Check passed"); };