UNPKG

smartledger-sdk

Version:

A comprehensive blockchain and cryptographic operations SDK for JavaScript

104 lines (91 loc) 3.42 kB
import sss from "shamirs-secret-sharing"; import { Buffer } from "buffer"; export class SecretSharer { constructor() { this.sss = sss; } /** * Split a secret into multiple shares using Shamir's Secret Sharing * @param {string} secret - The secret to split * @param {number} shares - Number of shares to create * @param {number} threshold - Minimum number of shares needed to reconstruct * @returns {Array<Buffer>} Array of secret shares */ splitSecret(secret, shares, threshold) { if (!secret || typeof secret !== "string") { throw new Error("Secret must be a non-empty string"); } if (!Number.isInteger(shares) || shares < 2) { throw new Error("Number of shares must be an integer >= 2"); } if (!Number.isInteger(threshold) || threshold < 2 || threshold > shares) { throw new Error( "Threshold must be an integer >= 2 and <= number of shares" ); } const secretBuffer = Buffer.from(secret, "utf8"); const result = this.sss.split(secretBuffer, { shares, threshold }); return Array.from(result); } /** * Combine shares to reconstruct the original secret * @param {Array<Buffer>} shares - Array of shares to combine * @returns {string} The reconstructed secret */ combineShares(shares) { if (!Array.isArray(shares) || shares.length < 2) { throw new Error("Must provide at least 2 shares"); } try { const recoveredBuffer = this.sss.combine(shares); return recoveredBuffer.toString("utf8"); } catch (error) { throw new Error("Failed to reconstruct secret: " + error.message); } } /** * Convert a share to a hex string for storage or transmission * @param {Buffer} share - The share to convert * @returns {string} Hex string representation of the share */ shareToHex(share) { if (!Buffer.isBuffer(share)) { // Convert Uint8Array to Buffer if needed if (share instanceof Uint8Array) { share = Buffer.from(share); } else { throw new Error("Share must be a Buffer or Uint8Array"); } } return share.toString("hex"); } /** * Convert a hex string back to a share Buffer * @param {string} hexShare - Hex string representation of a share * @returns {Buffer} The share as a Buffer */ hexToShare(hexShare) { if (typeof hexShare !== "string" || !/^[0-9a-fA-F]+$/.test(hexShare)) { throw new Error("Invalid hex string"); } return Buffer.from(hexShare, "hex"); } } // Example usage if (import.meta.url === `file://${process.cwd()}/SecretSharer.js`) { const sharer = new SecretSharer(); const secret = "my secret"; console.log("\nExample of Shamir's Secret Sharing:"); console.log("-----------------------------------"); console.log("Original secret:", secret); // Split the secret into 3 shares (need 2 to reconstruct) const shares = sharer.splitSecret(secret, 3, 2); console.log("\nGenerated", shares.length, "shares (need 2 to reconstruct):"); const hexShares = shares.map((share) => sharer.shareToHex(share)); hexShares.forEach((share, i) => console.log(`Share ${i + 1}:`, share)); // Reconstruct using just 2 of the 3 shares const sharesToUse = shares.slice(0, 2); const reconstructed = sharer.combineShares(sharesToUse); console.log("\nReconstructed secret using 2 shares:", reconstructed); } export default SecretSharer;