UNPKG

capacitor-shamir

Version:

Provides Shamir's Secret Sharing (SSS) functionality for secure splitting and recovering secrets natively on iOS, Android, and Web.

138 lines 6.16 kB
import { WebPlugin } from '@capacitor/core'; import { FileSystemMock } from './web/file-system.mock'; import { join, restorePart, split } from './web/scheme'; import { fromBase64, toBase64 } from './web/base64.utils'; export class ShamirWeb extends WebPlugin { constructor() { super(...arguments); this.fs = FileSystemMock.getInstance(); } async generateShards({ totalShards, threshold, inputDataBase64 }, callback) { const randomBytes = (len) => crypto.getRandomValues(new Uint8Array(len)); const parts = split(randomBytes, totalShards, threshold, fromBase64(inputDataBase64)); const shards = Object.entries(parts).map(([shardIdx, shardData]) => { const shardIdxBytes = new Uint8Array([parseInt(shardIdx)]); const shardBytes = new Uint8Array(1 + shardData.length); shardBytes.set(shardIdxBytes); shardBytes.set(shardData, shardIdxBytes.length); return shardBytes; }); callback({ progress: 100, shardsBase64: shards.map(shard => toBase64(shard)) }); } async restoreFromShards({ inputShardsBase64 }, callback) { const inputShards = inputShardsBase64.map(shardBase64 => fromBase64(shardBase64)); const parts = inputShards.reduce((acc, shardBytes) => { const shardIdx = shardBytes.subarray(0, 1)[0]; const shardData = shardBytes.subarray(1); acc[shardIdx] = shardData; return acc; }, {}); const result = join(parts); callback({ progress: 100, dataBase64: toBase64(result) }); } async restoreShard({ shardIndex, inputShardsBase64 }, callback) { const inputShards = inputShardsBase64.map(shardBase64 => fromBase64(shardBase64)); const parts = inputShards.reduce((acc, shardBytes) => { const shardIdx = shardBytes.subarray(0, 1)[0]; const shardData = shardBytes.subarray(1); acc[shardIdx] = shardData; return acc; }, {}); const restoredPart = restorePart(parts, shardIndex); const restoredShard = new Uint8Array(1 + restoredPart.length); const shardIdxBytes = new Uint8Array([shardIndex]); restoredShard.set(shardIdxBytes); restoredShard.set(restoredPart, shardIdxBytes.length); callback({ progress: 100, dataBase64: toBase64(restoredShard) }); } async generateFileShards({ totalShards, threshold, srcPath, dstPathRoot }, callback) { const inputData = await this.fs.read(srcPath); const inputDataBase64 = toBase64(inputData); await this.generateShardsToFiles({ totalShards, threshold, inputDataBase64, dstPathRoot }, callback); } async generateShardsToFiles({ totalShards, threshold, inputDataBase64, dstPathRoot }, callback) { await new Promise((resolve, reject) => { this.generateShards({ totalShards, threshold, inputDataBase64 }, async ({ progress, shardsBase64 }, error) => { if (error) { reject(error); } else { const shards = shardsBase64.map(shardBase64 => fromBase64(shardBase64)); const id = this.generateJobId(); const shardsPaths = []; for (let i = 0; i < shards.length; i++) { const path = this.formatShardPath(dstPathRoot, id, i); shardsPaths.push(path); await this.fs.write(path, shards[i]); } callback({ progress, shardsPaths }); resolve(); } }); }); } async restoreFromFileShards({ shardsPaths, dstPath }, callback) { await new Promise((resolve, reject) => { this.restoreFromFileShardsToData({ shardsPaths }, async ({ progress, dataBase64 }, error) => { if (error) { reject(error); } else { await this.fs.write(dstPath, fromBase64(dataBase64)); callback({ progress, dstPath }); resolve(); } }); }); } async restoreFromFileShardsToData({ shardsPaths }, callback) { const shardsBase64 = []; for (const path of shardsPaths) { const data = await this.fs.read(path); shardsBase64.push(toBase64(data)); } await new Promise((resolve, reject) => { this.restoreFromShards({ inputShardsBase64: shardsBase64 }, async ({ progress, dataBase64 }, error) => { if (error) { reject(error); } else { callback({ progress, dataBase64 }); resolve(); } }); }); } async restoreFileShard({ shardIndex, shardsPaths, dstPathRoot }, callback) { const shardsBase64 = []; for (const shardPath of shardsPaths) { const data = await this.fs.read(shardPath); shardsBase64.push(toBase64(data)); } await new Promise((resolve, reject) => { this.restoreShard({ shardIndex, inputShardsBase64: shardsBase64 }, async ({ progress, dataBase64 }, error) => { if (error) { reject(error); } else { const id = this.generateJobId(); const shardPath = this.formatShardPath(dstPathRoot, id, shardIndex); await this.fs.write(shardPath, fromBase64(dataBase64)); callback({ progress, shardPath }); resolve(); } }); }); } formatShardPath(dirPath, id, index) { return `${dirPath}/${id}_${index}.bin`; } generateJobId() { return Math.random().toString(36).substring(2, 15); } /** Web Filesystem Configuration */ updateShamirWebFsIndexedDbConfig(config) { this.fs.updateIndexedDbConfig(config); } } //# sourceMappingURL=web.js.map