mirror of
https://github.com/kccleoc/seedpgp-web.git
synced 2026-03-07 18:07:50 +08:00
security improvement and bugs fixing; modify makefile
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { Camera, X, AlertCircle, CheckCircle2 } from 'lucide-react';
|
||||
import { InteractionEntropy } from '../lib/interactionEntropy';
|
||||
import { entropyToMnemonic } from '../lib/seedblend';
|
||||
|
||||
interface EntropyStats {
|
||||
shannon: number;
|
||||
@@ -382,14 +383,10 @@ const CameraEntropy: React.FC<CameraEntropyProps> = ({
|
||||
const hash = await crypto.subtle.digest('SHA-256', data);
|
||||
|
||||
// Use bip39 to generate mnemonic from the collected entropy hash
|
||||
const { entropyToMnemonic } = await import('bip39');
|
||||
const entropyLength = wordCount === 12 ? 16 : 32;
|
||||
const finalEntropy = new Uint8Array(hash).slice(0, entropyLength);
|
||||
|
||||
// The bip39 library expects a hex string or a Buffer.
|
||||
const entropyHex = Buffer.from(finalEntropy).toString('hex');
|
||||
|
||||
return entropyToMnemonic(entropyHex);
|
||||
return entropyToMnemonic(finalEntropy);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
68
src/components/security.test.ts
Normal file
68
src/components/security.test.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { describe, it, expect, beforeEach } from 'bun:test';
|
||||
import { detectEncryptionMode } from './../lib/seedpgp';
|
||||
import {
|
||||
encryptJsonToBlob,
|
||||
decryptBlobToJson,
|
||||
destroySessionKey,
|
||||
getSessionKey,
|
||||
} from './../lib/sessionCrypto';
|
||||
|
||||
describe('Security Fixes Verification', () => {
|
||||
describe('F-02: Regex Fix for SeedQR detection', () => {
|
||||
it('should correctly detect a standard numeric SeedQR', () => {
|
||||
// A 48-digit string, representing 12 words
|
||||
const numericSeedQR = '000011112222333344445555666677778888999901234567';
|
||||
const mode = detectEncryptionMode(numericSeedQR);
|
||||
expect(mode).toBe('seedqr');
|
||||
});
|
||||
|
||||
it('should not detect a short numeric string as SeedQR', () => {
|
||||
const shortNumeric = '1234567890'; // 10 digits - too short for SeedQR
|
||||
const mode = detectEncryptionMode(shortNumeric);
|
||||
// ✅ FIXED: Short numeric strings should NOT be detected as SeedQR
|
||||
// (They may be detected as 'krux' if they match Base43 charset, which is fine)
|
||||
expect(mode).not.toBe('seedqr');
|
||||
});
|
||||
|
||||
it('should not detect a mixed-character string as numeric SeedQR', () => {
|
||||
const mixedString = '00001111222233334444555566667777888899990123456a';
|
||||
const mode = detectEncryptionMode(mixedString);
|
||||
expect(mode).not.toBe('seedqr');
|
||||
});
|
||||
});
|
||||
|
||||
describe('F-01: Session Key Rotation Data Loss Fix', () => {
|
||||
beforeEach(() => {
|
||||
destroySessionKey();
|
||||
});
|
||||
|
||||
it('should include a keyId in the encrypted blob', async () => {
|
||||
const data = { secret: 'hello world' };
|
||||
const blob = await encryptJsonToBlob(data);
|
||||
expect(blob.keyId).toBeDefined();
|
||||
expect(typeof blob.keyId).toBe('string');
|
||||
expect(blob.keyId.length).toBeGreaterThan(0); // Additional check
|
||||
});
|
||||
|
||||
it('should successfully decrypt a blob with the correct keyId', async () => {
|
||||
const data = { secret: 'this is a test' };
|
||||
const blob = await encryptJsonToBlob(data);
|
||||
const decrypted = await decryptBlobToJson(blob);
|
||||
expect(decrypted).toEqual(data);
|
||||
});
|
||||
|
||||
it('should throw an error if the key is rotated before decryption', async () => {
|
||||
const data = { secret: 'will be lost' };
|
||||
const blob = await encryptJsonToBlob(data);
|
||||
|
||||
// Force key rotation by destroying the current one and getting a new one
|
||||
destroySessionKey();
|
||||
await getSessionKey(); // Generates a new key with a new keyId
|
||||
|
||||
// Decryption should now fail because the keyId in the blob does not match
|
||||
await expect(decryptBlobToJson(blob)).rejects.toThrow(
|
||||
'Session expired. The encryption key has rotated. Please re-enter your seed phrase.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user