A browser-based cryptographic seed generator that collects behavioral and temporal entropy from user interactions and fortifies it with CSPRNG output. Designed for scenarios where crypto.getRandomValues() may be compromised. Uses only native Web Crypto API (SHA-256/SHA-512) without external dependencies.
While crypto.getRandomValues() provides strong randomness for most purposes, it fully depends on the system’s hardware entropy sources (CPU RNG, TPM, Secure Boot, etc.).
In certain environments — such as sandboxed browsers, virtual machines, or low-latency servers where fTPM or hardware RNGs are disabled — these sources may be limited or unavailable.
ntrpRNG.js is designed to remain functional and verifiable even when hardware entropy is missing.
It collects timing and behavioral noise, applies multi-stage hashing, and maintains internal entropy pools to ensure consistent randomness quality across environments.
- Testing and benchmarking against
crypto.getRandomValues() - Environments with restricted or unreliable entropy (VMs, sandboxed browsers, air-gapped systems)
- Educational and research purposes: visualize and understand entropy dynamics
- Security testing: detect degraded RNG behavior or missing hardware entropy
- Hardcoded 500 minimum events (not configurable)
- Export name:
window.ntrpRng→window.ntrpRNG - Weighted event counting: keyboard=3, mouse_down/touch/motion=2, move/scroll=1
- Non-deterministic seeds: Path B introduces fresh randomness on every generation
- See CHANGELOG.md for migration guide
User Behavioral Entropy (Primary Trust Anchor):
- Mouse: Movements (weight 1), clicks (weight 2) - position + timing
- Keyboard: Key events (weight 3) - timing + choice
- Touch: Start (weight 2), move (weight 1) - position + pressure
- Scroll: Events (weight 1)
- Device Motion: Accelerometer/gyroscope (weight 2)
Temporal Entropy:
- High-frequency timer jitter:
requestAnimationFrame,setInterval, recursivesetTimeout - Microsecond precision:
performance.now()+Date.now()
Hardware Entropy (Whitening):
- Cryptographic salt via
crypto.getRandomValues() - Fresh random bytes in Path B for fortification
Path A - User Entropy (Primary):
Behavioral + Temporal
↓ Serialize Float64 big-endian
↓ SHA-256 pre-hash (remove IEEE 754 patterns)
↓ Combine with salt
↓ SHA-256 × 5000 iterations (batched)
↓ SHA-512 × 5000 iterations (batched, truncated)
↓ XOR
→ 32 bytes
Path B - CSPRNG Whitening:
crypto.getRandomValues(64)
↓ SHA-256
↓ SHA-512 (truncated)
↓ XOR
→ 32 bytes
Final Mixing:
Path A || Path B || Salt
↓ SHA-512
↓ SHA-512
→ 64-byte seed
- 500 minimum weighted events (~5-10 seconds interaction, ~150-200 bits entropy)
- Triple integrity checks: Prevents runtime tampering with security requirements
- Async batching: 100 iterations/batch, non-blocking UI
- Security margin: >256 bits even if CSPRNG compromised
- Configurable iterations: Balance security vs performance (default: 5000)
- Custom salt size: 16-128 bytes (default: 32)
- Progress tracking: New
getProgress()method for UX feedback - Real-time stats: Pool sizes, weighted event counts, entropy readiness
- Zero dependencies (native Web Crypto API only)
- ES Modules and global window export
- Simple async/await API
- Multiple output formats (raw bytes, hex, base64)
<!-- Direct include -->
<script src="ntrpRNG.js"></script>
<!-- ES Module -->
<script type="module">
import ntrpRNG from './ntrpRNG.js';
</script>// Create instance (500 minimum events enforced)
const rng = new ntrpRNG();
// Monitor progress
const monitor = setInterval(async () => {
const progress = rng.getProgress();
console.log(`Progress: ${progress.percentage.toFixed(1)}%`);
console.log(`Events: ${progress.currentEvents}/${progress.requiredEvents}`);
if (progress.ready) {
clearInterval(monitor);
// Generate seed
const seedHex = await rng.generateSeedHex();
console.log('Seed:', seedHex);
// Cleanup
rng.stopCollecting();
}
}, 500);new ntrpRNG(options)Options:
iterations(number): Hash iterations, default: 5000saltSize(number): Salt size in bytes, default: 32autoCollect(boolean): Auto-start collection, default: true
Note: minEvents is hardcoded to 500 and cannot be overridden.
await generateSeed(skipValidation = false)Returns Uint8Array (64 bytes). Non-deterministic output.
await generateSeedHex(skipValidation = false)Returns hex string (128 characters).
await generateSeedBase64(skipValidation = false)Returns base64 string (88 characters).
startCollecting()
stopCollecting()
clearEntropy()
hasMinimumEntropy() // Returns booleangetProgress()Returns:
{
currentEvents: 245, // Current weighted count
requiredEvents: 500, // Always 500
percentage: 49.0, // 0-100
ready: false // currentEvents >= 500
}getStats()Returns detailed statistics including weighted event counts, pool sizes, and collection status.
const rng = new ntrpRNG();
function updateUI() {
const progress = rng.getProgress();
document.getElementById('progress').style.width = progress.percentage + '%';
document.getElementById('status').textContent =
`${progress.currentEvents}/500 events`;
document.getElementById('generateBtn').disabled = !progress.ready;
}
setInterval(updateUI, 100);
document.getElementById('generateBtn').addEventListener('click', async () => {
const seed = await rng.generateSeedHex();
console.log('Generated:', seed);
rng.stopCollecting();
});async function generateMultipleSeeds(count) {
const rng = new ntrpRNG();
const seeds = [];
while (!rng.hasMinimumEntropy()) {
await new Promise(resolve => setTimeout(resolve, 100));
}
for (let i = 0; i < count; i++) {
seeds.push(await rng.generateSeedHex());
rng.clearEntropy();
await new Promise(resolve => setTimeout(resolve, 2000));
}
rng.stopCollecting();
return seeds;
}try {
const seed = await rng.generateSeedHex();
} catch (error) {
if (error.message.includes('Insufficient entropy')) {
const progress = rng.getProgress();
console.log(`Need ${500 - progress.currentEvents} more events`);
} else if (error.message.includes('integrity check')) {
console.error('Security violation detected');
}
}- API Reference: API.md - Complete API documentation
- Changelog: CHANGELOG.md - Version history and migration guide
- Examples: EXAMPLES.md - Additional usage examples
Designed for scenarios where crypto.getRandomValues() is suspected compromised or backdoored. User behavioral entropy serves as the primary trust anchor, with CSPRNG providing output whitening.
NOT a replacement for crypto.getRandomValues() in standard scenarios. For normal applications, native Web Crypto API is sufficient and faster.
- Keyboard events: ~8-10 bits per event (weight 3)
- Mouse/Touch down: ~4-6 bits per event (weight 2)
- Movement/Scroll: ~2-4 bits per event (weight 1)
- Total 500 weighted events: ~150-200 bits effective entropy
Combined with CSPRNG fortification: >256-bit security margin
- Triple Integrity Checks: Constructor, validation, and generation
- Hardcoded Requirements: No runtime override of 500 minimum events
- Pre-hash Entropy: Eliminates IEEE 754 floating-point patterns
- Dual-path Architecture: Security even if one path compromised
- Async Batching: 5000 iterations without UI blocking
- Never skip validation in production
- Wait for full 500 weighted events (~5-10 seconds interaction)
- Use
getProgress()for user feedback - Clear entropy between generations for unique seeds
- Stop collection after generation to free resources
- Use 10000 iterations for high-security scenarios
- Derive keys properly using KDF (PBKDF2, Argon2)
| Iterations | Desktop | Mobile | Notes |
|---|---|---|---|
| 5000 (default) | 300-700ms | 700-1400ms | +100-200ms from async batching |
| 10000 | 600-1400ms | 1400-3000ms | High security |
Async batching ensures UI remains responsive during generation.
- Entropy pool: Capped at 5000 values (~40KB)
- Timer deltas: Capped at 1000 values (~8KB)
- Total overhead: <100KB
Required APIs:
crypto.subtle.digest()(SHA-256/SHA-512)crypto.getRandomValues()(Hardware RNG)performance.now()(High-resolution timestamps)requestAnimationFrame()(High-frequency timer)DataView(Float64 serialization)
Supported Browsers:
- Chrome 37+
- Firefox 34+
- Safari 11+
- Edge 79+
- Opera 24+
Interactive web-based dashboard for testing and demonstrating ntrpRNG capabilities:
- Real-time monitoring: Progress bars, event statistics, performance charts
- Configuration presets: Quick, Standard, Secure modes
- Seed management: History, export (CSV/JSON), uniqueness testing
- Stress testing: Batch generation and validation
-
Remove
minEventsoption (now ignored, console warning)// Before const rng = new ntrpRNG({ minEvents: 50 }); // After const rng = new ntrpRNG();
-
Update export reference
// Before const RNG = window.ntrpRng; // After const RNG = window.ntrpRNG;
-
Account for weighted events
// Before: raw count if (stats.totalEvents >= 50) { ... } // After: weighted count if (rng.getProgress().ready) { ... }
-
Remove seed reproducibility assumptions
- v1.2.1: Same user entropy → same seed
- v1.3.0: Always unique due to Path B randomness
- Implement
getProgress()for progress bars - Increase
iterationsto 10000 for higher security - Add UI feedback during 5-10 second collection period
MIT License - See source file for details.
This library uses only native Web Crypto API without external dependencies. Contributions should maintain this constraint and adhere to the security-focused design principles.