ths-csprng 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -34
- package/package.json +3 -2
- package/src/index.js +17 -10
- package/src/util.js +4 -4
package/README.md
CHANGED
|
@@ -4,17 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
<br />
|
|
6
6
|
|
|
7
|
-
Standard RNGs
|
|
7
|
+
Standard RNGs assume that once you’ve seeded them, the whole history of how that seed was created just disappears. In reality, if someone can reconstruct the exact physical state of your system—or somehow “look back” in time—your randomness stops being random.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
If you buy into a **block universe** or **[superdeterminism](https://en.wikipedia.org/wiki/Superdeterminism)**, that “random” seed was never random at all. It’s just a fixed point in spacetime. To an observer with enough computing power or a view further down the timeline, your private key isn’t secret — it’s already history.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
If you are on to a **Block Universe** or **Superdeterministic** model, your "random" seed is just a static coordinate in spacetime. To an observer with enough compute or a vantage point further down the temporal axis, your private key isn't a secret — it’s a historical fact.
|
|
11
|
+
**THS (Temporal-Hardening Solution)** is an attempt to push back against that. It’s a cryptographic wrapper that turns the problem from “break the math” into “do a massive amount of physical work.” It makes retrocausal attacks or precise state reconstruction much harder by forcing the attacker to simulate real-world chaos.
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
To put it simply, it is a “Macroscopic Chaos as a defense against Microscopic Observation.”
|
|
13
|
+
In short: it uses macroscopic messiness as a defense against microscopic observation.
|
|
18
14
|
|
|
19
15
|
<br />
|
|
20
16
|
|
|
@@ -28,19 +24,13 @@ To put it simply, it is a “Macroscopic Chaos as a defense against Microscopic
|
|
|
28
24
|
|
|
29
25
|
<br />
|
|
30
26
|
|
|
31
|
-
## The
|
|
27
|
+
## The “Observer from the Future” Problem
|
|
32
28
|
|
|
33
|
-
Information doesn
|
|
29
|
+
Information doesn’t just vanish (see the **[Quantum No-Hiding Theorem](https://en.wikipedia.org/wiki/No-hiding_theorem)**). It spreads into the environment. If an adversary can reconstruct past states—whether through retrocausality, solving hidden variables, or digging through micro-architectural leaks—traditional seeds become vulnerable.
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
Normally, a seed is generated at a single point in time (T=0). If that moment is reconstructed, your entropy is gone.
|
|
36
32
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
### How it actually works:
|
|
40
|
-
|
|
41
|
-
* **Micro-Architectural Jitter:** Harvesting the tiny, unpredictable timing variances in your CPU clock caused by interrupts and thread scheduling.
|
|
42
|
-
* **Physical Binding:** Capturing "ghost data" from uninitialized memory, we inject artifacts of the machine's immediate past into the entropy pool.
|
|
43
|
-
* **Memory-Hardened Anchors:** We use **Argon2id** to spin up a shifting memory state. This forces an attacker to simulate a massive slice of physical RAM history just to see what happened in that one millisecond.
|
|
33
|
+
THS fixes this by replacing a single seed with a temporal sequence of many moments (T₁, T₂, …, Tₙ). To recover your secret, an attacker doesn’t just need to glance at the past—they have to accurately simulate the entire noisy evolution of the machine across hundreds of layers of timing jitter, memory state, and CPU behavior.
|
|
44
34
|
|
|
45
35
|
<br />
|
|
46
36
|
|
|
@@ -48,7 +38,7 @@ THS creates **Computational Fog**. Instead of a mathematical point, it binds you
|
|
|
48
38
|
|
|
49
39
|
<br />
|
|
50
40
|
|
|
51
|
-
|
|
41
|
+
### 🚀 Getting Started
|
|
52
42
|
|
|
53
43
|
```bash
|
|
54
44
|
npm install ths-csprng
|
|
@@ -56,35 +46,126 @@ npm install ths-csprng
|
|
|
56
46
|
|
|
57
47
|
<br />
|
|
58
48
|
|
|
59
|
-
### Quick Start
|
|
49
|
+
### 🛠️ Quick Start
|
|
60
50
|
|
|
61
51
|
```javascript
|
|
62
52
|
import THS from 'ths-csprng';
|
|
63
53
|
|
|
64
54
|
(async () => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
55
|
+
// Standard 256-bit secure random buffer
|
|
56
|
+
const entropy = await THS.random(32);
|
|
57
|
+
|
|
58
|
+
// High-security hardened key
|
|
59
|
+
const masterKey = await THS.random(64, {
|
|
60
|
+
layers: 512, // 512 temporal slices
|
|
61
|
+
harden: 3, // Heavy Argon2id hardening
|
|
62
|
+
mem: 65536, // 64MB memory cost
|
|
63
|
+
trng: true // Try reading directly from /dev/urandom
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
console.log(masterKey.toString('hex'));
|
|
76
67
|
})();
|
|
77
68
|
```
|
|
78
69
|
|
|
79
70
|
<br />
|
|
80
71
|
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### 💎 The Hardening Levels
|
|
75
|
+
|
|
76
|
+
You can dial the security up or down depending on how much “weight” you want the key to have.
|
|
77
|
+
|
|
78
|
+
| Level | Mode | Description |
|
|
79
|
+
| :--- | :--- | :--- |
|
|
80
|
+
| **0** | **Basic** | High-resolution hardware timing (`hrtime`) per slice. |
|
|
81
|
+
| **1** | **Entropy** | Level 0 + supplemental CSPRNG entropy injection. |
|
|
82
|
+
| **2** | **Internal** | Level 1 + metabolic collection (Internal state snapshots). |
|
|
83
|
+
| **3** | **Heavy** | Level 2 + **Argon2id** memory-hardened processing. |
|
|
84
|
+
|
|
85
|
+
<br />
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### ⚙️ Full Configuration Options
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
const options = {
|
|
93
|
+
layers: 128, // Number of temporal slices (2 to 65536)
|
|
94
|
+
harden: 2, // 0–3 (hardening depth)
|
|
95
|
+
trng: false, // Fallback to internal CSPRNG or /dev/urandom
|
|
96
|
+
hashOut: true, // SHA3-512 hash each slice to avoid raw memory leaks
|
|
97
|
+
memoryH: 1, // Argon2id iterations (only with harden: 3)
|
|
98
|
+
mem: 16384, // Argon2id memory cost in KB (default 16MB)
|
|
99
|
+
label: 'THS-Default-v1' // KMAC personalization string
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const bytes = await THS.random(32, options);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
<br />
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### 🧬 Advanced API
|
|
110
|
+
|
|
111
|
+
#### Direct Utils
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
import Utils from 'ths-csprng/utils';
|
|
115
|
+
import THS from 'ths-csprng';
|
|
116
|
+
|
|
117
|
+
// Get a raw metabolic snapshot (T=n)
|
|
118
|
+
const snap = await Utils.snapshot(2);
|
|
119
|
+
|
|
120
|
+
// Direct access to the internal TRNG/CSPRNG source
|
|
121
|
+
const raw = await THS.raw(32);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
#### Browser Support
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
const buf = new Uint8Array(32);
|
|
129
|
+
THS.fillRandom(buf);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
#### Convenient Aliases
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
import { randomBytes } from 'ths-csprng';
|
|
137
|
+
|
|
138
|
+
await randomBytes(32);
|
|
139
|
+
await THS.rand(32);
|
|
140
|
+
await THS.rnd(32);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
<br />
|
|
144
|
+
|
|
81
145
|
## Why should you care?
|
|
82
146
|
|
|
83
|
-
Most
|
|
147
|
+
Most of the crypto world acts like randomness is a solved problem. But in 2026, with hardware backdoors, VM cloning, and advanced side-channel attacks, standard entropy sources might be more fragile than they look.
|
|
148
|
+
|
|
149
|
+
THS tries to bridge raw hardware chaos with solid cryptographic primitives.
|
|
150
|
+
|
|
151
|
+
<br />
|
|
152
|
+
|
|
153
|
+
## Use Cases
|
|
154
|
+
|
|
155
|
+
* **Everyday apps:** Use `THS.fillRandom()` or `THS.raw()` for fast, reliable randomness.
|
|
156
|
+
* **Entropy Research / Custom PRNGs:** Import the subpath `ths-csprng/utils` to feed metabolic snapshots directly into your own DRBGs as a source of high-variance, hardware-bound entropy.
|
|
157
|
+
* **High-value keys:** Use `THS.random()` with `harden: 3` when you want seeds that are computationally irreducible — an attacker would need to reconstruct exact nanosecond-level CPU and memory states across hundreds of noisy iterations.
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
<br />
|
|
161
|
+
|
|
162
|
+
## Threat Model
|
|
84
163
|
|
|
85
|
-
|
|
164
|
+
THS is aimed at situations where the attacker might try to:
|
|
86
165
|
|
|
87
|
-
|
|
166
|
+
1. Reconstruct the historical state of your machine when the key was generated.
|
|
167
|
+
2. Exploit VM snapshots that cause cloned instances to produce identical “random” output.
|
|
168
|
+
3. Bypass or predict hardware entropy sources through backdoors or manufacturer influence.
|
|
88
169
|
|
|
89
170
|
<br />
|
|
90
171
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ths-csprng",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Temporal-Hardening Solution: A CSPRNG wrapper designed to resist historical state reconstruction and hardware backdoors.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"exports": {
|
|
8
|
-
".": "./src/index.js"
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./utils": "./src/util.js"
|
|
9
10
|
},
|
|
10
11
|
"author": "Aries Harbinger",
|
|
11
12
|
"license": "Apache-2.0",
|
package/src/index.js
CHANGED
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
|
|
19
19
|
import Utils from './util.js';
|
|
20
20
|
import { kmac256 } from '@noble/hashes/sha3-addons.js';
|
|
21
|
-
import { createHash } from 'node:crypto';
|
|
21
|
+
import { createHash, webcrypto } from 'node:crypto';
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Temporal-Hardening Solution - Applied in Random Number Generator
|
|
26
26
|
*/
|
|
27
|
-
export const THS = {
|
|
27
|
+
export const THS = Object.freeze({
|
|
28
28
|
/**
|
|
29
29
|
* Generates cryptographically secure random bytes with temporal hardening.
|
|
30
30
|
*/
|
|
@@ -109,16 +109,23 @@ export const THS = {
|
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
rand(len, o) { return THS.random(len, o) },
|
|
113
|
+
rnd (len, o) { return THS.random(len, o) },
|
|
114
114
|
|
|
115
|
-
//
|
|
116
|
-
async raw(len) { return await Utils.getRandom(len, true) }
|
|
117
|
-
|
|
115
|
+
// Direct use of /dev/urandom (fallback to randomBytes)
|
|
116
|
+
async raw(len) { return await Utils.getRandom(len, true) },
|
|
117
|
+
|
|
118
|
+
// Direct Webcrypto access
|
|
119
|
+
fillRandom(arr) {
|
|
120
|
+
return (
|
|
121
|
+
(typeof window !== 'undefined' && window.crypto)
|
|
122
|
+
? window.crypto
|
|
123
|
+
: webcrypto
|
|
124
|
+
).getRandomValues(arr)
|
|
125
|
+
}
|
|
126
|
+
});
|
|
118
127
|
|
|
119
128
|
// Must use await
|
|
120
|
-
export const randomBytes =
|
|
121
|
-
return await THS.random(len, o);
|
|
122
|
-
};
|
|
129
|
+
export const randomBytes = (len, o) => THS.random(len, o);
|
|
123
130
|
|
|
124
131
|
export default THS;
|
package/src/util.js
CHANGED
|
@@ -24,7 +24,7 @@ const argon2 = promisify(_argon2);
|
|
|
24
24
|
const defined_past = process.hrtime.bigint();
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
export const Utils = {
|
|
27
|
+
export const Utils = Object.freeze({
|
|
28
28
|
/**
|
|
29
29
|
* Captures a high-resolution snapshot of the Node.js metabolic state.
|
|
30
30
|
* Uses concatenation to prevent entropy collisions.
|
|
@@ -40,7 +40,7 @@ export const Utils = {
|
|
|
40
40
|
// We use an array to preserve individual entropy of each metric
|
|
41
41
|
const metrics = [
|
|
42
42
|
process.hrtime.bigint(), // CPU Nanoseconds
|
|
43
|
-
BigInt(Math.round(process.uptime() * 1_000_000)),
|
|
43
|
+
BigInt(Math.round(process.uptime() * 1_000_000)),
|
|
44
44
|
BigInt(u.userCPUTime), // User-space CPU usage
|
|
45
45
|
BigInt(u.systemCPUTime), // Kernel-space CPU usage
|
|
46
46
|
BigInt(u.minorPageFault), // Soft memory faults
|
|
@@ -55,7 +55,7 @@ export const Utils = {
|
|
|
55
55
|
BigInt(Math.round(performance.now() * 1_000_000)),
|
|
56
56
|
defined_past, // Process start anchor
|
|
57
57
|
BigInt(Date.now()), // Wall clock (Temporal anchor)
|
|
58
|
-
BigInt(s)
|
|
58
|
+
BigInt(s || 0) // Sequential salt
|
|
59
59
|
].map(n => this.bigIntToBuffer(n));
|
|
60
60
|
|
|
61
61
|
// Map metrics to uniquely structured buffers
|
|
@@ -164,6 +164,6 @@ export const Utils = {
|
|
|
164
164
|
if (typeof input === 'string') return new TextEncoder().encode(input);
|
|
165
165
|
return new TextEncoder().encode(JSON.stringify(input) || '');
|
|
166
166
|
}
|
|
167
|
-
};
|
|
167
|
+
});
|
|
168
168
|
|
|
169
169
|
export default Utils;
|