feat(blender): add Seed Blender feature

Implements a new 'Seed Blender' feature that allows users to securely combine multiple BIP39 mnemonics and enhance them with dice roll entropy.

- Adds a new 'Seed Blender' tab to the main UI.
- Implements a multi-step workflow for inputting mnemonics (manual/QR) and dice rolls.
- Provides live validation and previews for blended seeds and dice-only entropy.
- Includes statistical analysis of dice rolls (chi-square, distribution) and pattern detection for quality assessment.
- The core logic is a 1-to-1 port of the reference Python implementation, using the Web Crypto API for browser compatibility and Node.js for testing.
- A full suite of unit tests ported from the reference implementation ensures correctness and deterministic outputs.
This commit is contained in:
LC mac
2026-02-04 02:37:32 +08:00
parent e3ade8eab1
commit ec722befef
6 changed files with 3003 additions and 4 deletions

View File

@@ -22,6 +22,7 @@ import Header from './components/Header';
import { StorageDetails } from './components/StorageDetails';
import { ClipboardDetails } from './components/ClipboardDetails';
import Footer from './components/Footer';
import { SeedBlender } from './components/SeedBlender';
console.log("OpenPGP.js version:", openpgp.config.versionString);
@@ -39,11 +40,12 @@ interface ClipboardEvent {
}
function App() {
const [activeTab, setActiveTab] = useState<'backup' | 'restore'>('backup');
const [activeTab, setActiveTab] = useState<'backup' | 'restore' | 'seedblender'>('backup');
const [mnemonic, setMnemonic] = useState('');
const [backupMessagePassword, setBackupMessagePassword] = useState('');
const [restoreMessagePassword, setRestoreMessagePassword] = useState('');
const [publicKeyInput, setPublicKeyInput] = useState('');
const [privateKeyInput, setPrivateKeyInput] = useState('');
const [privateKeyPassphrase, setPrivateKeyPassphrase] = useState('');
@@ -418,7 +420,7 @@ function App() {
readOnly={isReadOnly}
/>
</>
) : (
) : activeTab === 'restore' ? (
<>
<div className="flex gap-2">
<button
@@ -475,6 +477,8 @@ function App() {
</div>
)}
</>
) : (
<SeedBlender />
)}
</div>