mirror of
https://github.com/kccleoc/seedpgp-web.git
synced 2026-03-07 09:57:50 +08:00
- Fix videoRef timing issue by using useEffect for video setup - Stop animation loop on capture to prevent infinite warnings - Fix null canvas reference in generateMnemonicFromEntropy - Add stats review panel with continue/retake options - Add seed generation explanation and blurred preview - Implement seed generation from camera noise/entropy bits and enhance dice rolls with detailed statistical analysis
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
/**
|
|
* Collects entropy from user interactions (mouse, keyboard, touch)
|
|
* Runs in background to enhance any entropy generation method
|
|
*/
|
|
export class InteractionEntropy {
|
|
private samples: number[] = [];
|
|
private lastEvent = 0;
|
|
private startTime = performance.now();
|
|
private sources = { mouse: 0, keyboard: 0, touch: 0 };
|
|
|
|
constructor() {
|
|
this.initListeners();
|
|
}
|
|
|
|
private initListeners() {
|
|
const handleEvent = (e: MouseEvent | KeyboardEvent | TouchEvent) => {
|
|
const now = performance.now();
|
|
const delta = now - this.lastEvent;
|
|
|
|
if (delta > 0 && delta < 10000) { // Ignore huge gaps
|
|
this.samples.push(delta);
|
|
|
|
if (e instanceof MouseEvent) {
|
|
this.samples.push(e.clientX ^ e.clientY);
|
|
this.sources.mouse++;
|
|
} else if (e instanceof KeyboardEvent) {
|
|
this.samples.push(e.key.codePointAt(0) ?? 0);
|
|
this.sources.keyboard++;
|
|
} else if (e instanceof TouchEvent && e.touches[0]) {
|
|
this.samples.push(e.touches[0].clientX ^ e.touches[0].clientY);
|
|
this.sources.touch++;
|
|
}
|
|
}
|
|
this.lastEvent = now;
|
|
|
|
// Keep last 256 samples (128 pairs)
|
|
if (this.samples.length > 256) {
|
|
this.samples.splice(0, this.samples.length - 256);
|
|
}
|
|
};
|
|
|
|
document.addEventListener('mousemove', handleEvent);
|
|
document.addEventListener('keydown', handleEvent);
|
|
document.addEventListener('touchmove', handleEvent);
|
|
}
|
|
|
|
async getEntropyBytes(): Promise<Uint8Array> {
|
|
// Convert samples to entropy via SHA-256
|
|
const data = new TextEncoder().encode(
|
|
this.samples.join(',') + performance.now()
|
|
);
|
|
const hash = await crypto.subtle.digest('SHA-256', data);
|
|
return new Uint8Array(hash);
|
|
}
|
|
|
|
getSampleCount(): { mouse: number; keyboard: number; touch: number; total: number } {
|
|
return {
|
|
...this.sources,
|
|
total: this.sources.mouse + this.sources.keyboard + this.sources.touch
|
|
};
|
|
}
|
|
|
|
getCollectionTime(): number {
|
|
return performance.now() - this.startTime;
|
|
}
|
|
|
|
clear() {
|
|
this.samples = [];
|
|
this.lastEvent = 0;
|
|
this.startTime = performance.now();
|
|
this.sources = { mouse: 0, keyboard: 0, touch: 0 };
|
|
}
|
|
} |