A powerful Capacitor plugin for secure secret sharing using Shamir's Secret Sharing algorithm
Shamir's Secret Sharing is a cryptographic algorithm that divides a secret into multiple parts (shards), where a minimum threshold of shards is required to reconstruct the original secret. This ensures that:
- No single shard reveals any information about the secret
- Any threshold number of shards can reconstruct the secret
- Security through distribution - store shards separately for maximum security
Shamir's Secret Sharing provides information-theoretic security, which means the algorithm is mathematically proven to be unbreakable regardless of computational power. Key security advantages:
- Quantum Resistance: Security relies on mathematical impossibility rather than computational complexity, remaining secure against quantum computers
- No Key Management: There is no single master key to rotate or protect; instead, security hinges on distributing and safeguarding the individual shares
- Mathematical Foundation: Based on polynomial interpolation over finite fields, where reconstructing the secret without sufficient shards is mathematically impossible, not just computationally difficult
- Secure Secret Splitting: Split sensitive data into encrypted shards using Shamir's Secret Sharing
- Cross-Platform: Native support for iOS, Android, and Web
- Flexible Storage: Memory-based and filesystem-based operations
- Progress Tracking: Real-time progress callbacks for all operations
- Performance Optimized: Efficient handling of large files and data
- Recovery Options: Restore complete secrets or individual shards
This plugin is actively used in production by Vault12 Guard - a mobile app that provides secure, decentralized backup and recovery for crypto seed phrases and other sensitive data using Shamir's Secret Sharing.
npm install capacitor-shamir
npx cap sync
This plugin requires Capacitor 7 or higher.
The web implementation uses IndexedDB for file operations and includes all necessary polyfills.
import { Shamir } from 'capacitor-shamir';
// Split a secret into 5 shards, requiring 3 to reconstruct
const secret = btoa("My secret data");
await Shamir.generateShards({
totalShards: 5,
threshold: 3,
inputDataBase64: secret
}, (data, error) => {
if (error) {
console.error('Error:', error);
return;
}
if (data?.shardsBase64) {
console.log('Secret split into shards:', data.shardsBase64);
} else {
console.log('Progress:', data?.progress + '%');
}
});
This plugin provides both memory-based and file-based API methods for:
- Splitting secret data into cryptographic shards
- Restoring secret data from cryptographic shards
- Recovering individual N-th shard from a set of cryptographic shards
All methods use callback-based progress reporting to provide real-time updates during operations.
A job is complete when the callback's data
object contains a result property with a truthy value:
dataBase64
- for restored secret datashardsBase64
- for generated shards in memoryshardsPath
/shardsPaths
- for file-based operationsdstPath
- for file restoration
Important
Use progress
only for UI updates, not to detect completion. A job is done when !!dataBase64
(or other result property), not when progress === 100
.
Since Capacitor doesn't support blob data transfer, all data exchange uses Base64-encoded strings.
Category | Methods | Description |
---|---|---|
Memory Operations | generateShards , restoreFromShards , restoreShard |
Work with Base64 data in memory |
File Operations | generateFileShards , restoreFromFileShards , restoreFileShard |
Direct file-to-file operations |
Hybrid Operations | generateShardsToFiles , restoreFromFileShardsToData |
Convert between memory and file formats |
generateShards(...)
restoreFromShards(...)
restoreShard(...)
generateFileShards(...)
generateShardsToFiles(...)
restoreFromFileShards(...)
restoreFromFileShardsToData(...)
restoreFileShard(...)
- Interfaces
generateShards(options: { totalShards: number; threshold: number; inputDataBase64: string; }, callback: (data?: { progress: number; shardsBase64?: string[] | undefined; } | undefined, error?: Error | undefined) => void) => Promise<void>
Splits secret data (Base64) into encrypted shards in memory.
Param | Type | Description |
---|---|---|
options |
{ totalShards: number; threshold: number; inputDataBase64: string; } |
totalShards (≤255), threshold (≥2, ≤255), and inputDataBase64 (Base64-encoded secret) |
callback |
(data?: { progress: number; shardsBase64?: string[]; }, error?: Error) => void |
Reports progress and returns shards as Base64 strings |
restoreFromShards(options: { inputShardsBase64: string[]; }, callback: (data?: { progress: number; dataBase64?: string | undefined; } | undefined, error?: Error | undefined) => void) => Promise<void>
Restores secret data from encrypted shards (all in memory, Base64).
Param | Type | Description |
---|---|---|
options |
{ inputShardsBase64: string[]; } |
inputShardsBase64: array of Base64-encoded shards |
callback |
(data?: { progress: number; dataBase64?: string; }, error?: Error) => void |
Reports progress and returns restored secret as Base64 |
restoreShard(options: { shardIndex: number; inputShardsBase64: string[]; }, callback: (data?: { progress: number; dataBase64?: string | undefined; } | undefined, error?: Error | undefined) => void) => Promise<void>
Restores a specific shard from a set of encrypted shards (all in memory, Base64).
Param | Type | Description |
---|---|---|
options |
{ shardIndex: number; inputShardsBase64: string[]; } |
shardIndex (>0, ≤255) and inputShardsBase64 |
callback |
(data?: { progress: number; dataBase64?: string; }, error?: Error) => void |
Reports progress and returns the requested shard as Base64 |
generateFileShards(options: { totalShards: number; threshold: number; srcPath: string; dstPathRoot: string; }, callback: (data?: { progress: number; shardsPaths?: string[] | undefined; } | undefined, error?: Error | undefined) => void) => Promise<void>
Splits a file into encrypted shard files.
Param | Type | Description |
---|---|---|
options |
{ totalShards: number; threshold: number; srcPath: string; dstPathRoot: string; } |
totalShards (≤255), threshold (≥2, ≤255), srcPath (input file), dstPathRoot (output directory) |
callback |
(data?: { progress: number; shardsPaths?: string[]; }, error?: Error) => void |
Reports progress and returns paths to shard files |
generateShardsToFiles(options: { totalShards: number; threshold: number; inputDataBase64: string; dstPathRoot: string; }, callback: (data?: { progress: number; shardsPaths?: string[] | undefined; } | undefined, error?: Error | undefined) => void) => Promise<void>
Splits secret data (Base64) into encrypted shard files.
Param | Type | Description |
---|---|---|
options |
{ totalShards: number; threshold: number; inputDataBase64: string; dstPathRoot: string; } |
totalShards (≤255), threshold (≥2, ≤255), inputDataBase64, dstPathRoot (output directory) |
callback |
(data?: { progress: number; shardsPaths?: string[]; }, error?: Error) => void |
Reports progress and returns paths to shard files |
restoreFromFileShards(options: { shardsPaths: string[]; dstPath: string; }, callback: (data?: { progress: number; dstPath?: string | undefined; } | undefined, error?: Error | undefined) => void) => Promise<void>
Restores a file from encrypted shard files.
Param | Type | Description |
---|---|---|
options |
{ shardsPaths: string[]; dstPath: string; } |
shardsPaths (input files), dstPath (output file) |
callback |
(data?: { progress: number; dstPath?: string; }, error?: Error) => void |
Reports progress and returns the output file path |
restoreFromFileShardsToData(options: { shardsPaths: string[]; }, callback: (data?: { progress: number; dataBase64?: string | undefined; } | undefined, error?: Error | undefined) => void) => Promise<void>
Restores secret data (Base64) from encrypted shard files.
Param | Type | Description |
---|---|---|
options |
{ shardsPaths: string[]; } |
shardsPaths (input files) |
callback |
(data?: { progress: number; dataBase64?: string; }, error?: Error) => void |
Reports progress and returns restored secret as Base64 |
restoreFileShard(options: { shardIndex: number; shardsPaths: string[]; dstPathRoot: string; }, callback: (data?: { progress: number; shardPath?: string | undefined; } | undefined, error?: Error | undefined) => void) => Promise<void>
Restores a specific shard file from a set of encrypted shard files.
Param | Type | Description |
---|---|---|
options |
{ shardIndex: number; shardsPaths: string[]; dstPathRoot: string; } |
shardIndex (>0, ≤255), shardsPaths (input files), dstPathRoot (output directory) |
callback |
(data?: { progress: number; shardPath?: string; }, error?: Error) => void |
Reports progress and returns the path to the restored shard file |
Prop | Type |
---|---|
name |
string |
message |
string |
stack |
string |
This project is dual-licensed under MIT OR Apache-2.0. You may choose to use this project under the terms of either license.
This dual licensing approach is necessary because the web implementation includes code derived from simbo1905/shamir, which is licensed under the Apache License 2.0.
See the LICENSE file for the full legal text.
Large File Performance
- For files > 10MB, consider using file-based operations instead of memory-based
- Monitor progress callbacks to provide user feedback during long operations
Base64 Encoding
- Remember to encode/decode data properly when working with binary content
Platform Differences
- File paths vary between platforms - use absolute paths when possible
- iOS sandbox restrictions may limit file access locations
# Run unit tests
npm run test
# Run platform-specific test cases
npm run verify:ios
npm run verify:android
Platform | Version | Status |
---|---|---|
iOS | 14.0+ | ✅ Fully supported |
Android | API 23+ | ✅ Fully supported |
Web | Modern browsers | ✅ Fully supported |
We welcome contributions! Please see our Contributing Guide for details.
# Clone the repository
git clone https://github.com/vault12/capacitor-shamir.git
cd capacitor-shamir
# Install dependencies
npm install
# Build the plugin
npm run build
# Run tests
npm test
See Releases for detailed changelog.
- Web implementation includes code derived from simbo1905/shamir under the Apache License 2.0
- Finite field mathematics implementation based on The Laws of Cryptography: The Finite Field GF(28) by Neal R. Wagner
- Built for Capacitor framework
- Implements Shamir's Secret Sharing algorithm
Made with ❤️ by the Vault12 Team