@mindpeeker/entropy 0.1.0
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/LICENSE +21 -0
- package/README.md +496 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/bits.d.ts +9 -0
- package/dist/internal/bits.d.ts.map +1 -0
- package/dist/internal/bits.js +29 -0
- package/dist/internal/bits.js.map +1 -0
- package/dist/internal/byte-source.d.ts +16 -0
- package/dist/internal/byte-source.d.ts.map +1 -0
- package/dist/internal/byte-source.js +96 -0
- package/dist/internal/byte-source.js.map +1 -0
- package/dist/internal/bytes.d.ts +5 -0
- package/dist/internal/bytes.d.ts.map +1 -0
- package/dist/internal/bytes.js +56 -0
- package/dist/internal/bytes.js.map +1 -0
- package/dist/internal/composite.d.ts +15 -0
- package/dist/internal/composite.d.ts.map +1 -0
- package/dist/internal/composite.js +36 -0
- package/dist/internal/composite.js.map +1 -0
- package/dist/internal/condition.d.ts +38 -0
- package/dist/internal/condition.d.ts.map +1 -0
- package/dist/internal/condition.js +49 -0
- package/dist/internal/condition.js.map +1 -0
- package/dist/internal/encoding.d.ts +14 -0
- package/dist/internal/encoding.d.ts.map +1 -0
- package/dist/internal/encoding.js +91 -0
- package/dist/internal/encoding.js.map +1 -0
- package/dist/internal/health.d.ts +25 -0
- package/dist/internal/health.d.ts.map +1 -0
- package/dist/internal/health.js +84 -0
- package/dist/internal/health.js.map +1 -0
- package/dist/internal/http.d.ts +25 -0
- package/dist/internal/http.d.ts.map +1 -0
- package/dist/internal/http.js +76 -0
- package/dist/internal/http.js.map +1 -0
- package/dist/internal/nist-pulse.d.ts +31 -0
- package/dist/internal/nist-pulse.d.ts.map +1 -0
- package/dist/internal/nist-pulse.js +62 -0
- package/dist/internal/nist-pulse.js.map +1 -0
- package/dist/internal/provider.d.ts +19 -0
- package/dist/internal/provider.d.ts.map +1 -0
- package/dist/internal/provider.js +62 -0
- package/dist/internal/provider.js.map +1 -0
- package/dist/internal/rate-limit.d.ts +15 -0
- package/dist/internal/rate-limit.d.ts.map +1 -0
- package/dist/internal/rate-limit.js +47 -0
- package/dist/internal/rate-limit.js.map +1 -0
- package/dist/internal/sampled.d.ts +25 -0
- package/dist/internal/sampled.d.ts.map +1 -0
- package/dist/internal/sampled.js +49 -0
- package/dist/internal/sampled.js.map +1 -0
- package/dist/internal/stream.d.ts +29 -0
- package/dist/internal/stream.d.ts.map +1 -0
- package/dist/internal/stream.js +78 -0
- package/dist/internal/stream.js.map +1 -0
- package/dist/internal/validate.d.ts +5 -0
- package/dist/internal/validate.d.ts.map +1 -0
- package/dist/internal/validate.js +39 -0
- package/dist/internal/validate.js.map +1 -0
- package/dist/node/ffmpeg-frames.d.ts +27 -0
- package/dist/node/ffmpeg-frames.d.ts.map +1 -0
- package/dist/node/ffmpeg-frames.js +102 -0
- package/dist/node/ffmpeg-frames.js.map +1 -0
- package/dist/node/ffmpeg-samples.d.ts +21 -0
- package/dist/node/ffmpeg-samples.d.ts.map +1 -0
- package/dist/node/ffmpeg-samples.js +81 -0
- package/dist/node/ffmpeg-samples.js.map +1 -0
- package/dist/node/hwrng.d.ts +12 -0
- package/dist/node/hwrng.d.ts.map +1 -0
- package/dist/node/hwrng.js +43 -0
- package/dist/node/hwrng.js.map +1 -0
- package/dist/node/index.d.ts +9 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +7 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/rtl-sdr.d.ts +31 -0
- package/dist/node/rtl-sdr.d.ts.map +1 -0
- package/dist/node/rtl-sdr.js +63 -0
- package/dist/node/rtl-sdr.js.map +1 -0
- package/dist/node/serial-source.d.ts +22 -0
- package/dist/node/serial-source.d.ts.map +1 -0
- package/dist/node/serial-source.js +63 -0
- package/dist/node/serial-source.js.map +1 -0
- package/dist/providers/anu-legacy.d.ts +17 -0
- package/dist/providers/anu-legacy.d.ts.map +1 -0
- package/dist/providers/anu-legacy.js +56 -0
- package/dist/providers/anu-legacy.js.map +1 -0
- package/dist/providers/anu.d.ts +14 -0
- package/dist/providers/anu.d.ts.map +1 -0
- package/dist/providers/anu.js +42 -0
- package/dist/providers/anu.js.map +1 -0
- package/dist/providers/bitcoin.d.ts +14 -0
- package/dist/providers/bitcoin.d.ts.map +1 -0
- package/dist/providers/bitcoin.js +95 -0
- package/dist/providers/bitcoin.js.map +1 -0
- package/dist/providers/camera.d.ts +49 -0
- package/dist/providers/camera.d.ts.map +1 -0
- package/dist/providers/camera.js +123 -0
- package/dist/providers/camera.js.map +1 -0
- package/dist/providers/crypto.d.ts +8 -0
- package/dist/providers/crypto.d.ts.map +1 -0
- package/dist/providers/crypto.js +26 -0
- package/dist/providers/crypto.js.map +1 -0
- package/dist/providers/curby.d.ts +17 -0
- package/dist/providers/curby.d.ts.map +1 -0
- package/dist/providers/curby.js +113 -0
- package/dist/providers/curby.js.map +1 -0
- package/dist/providers/drand.d.ts +19 -0
- package/dist/providers/drand.d.ts.map +1 -0
- package/dist/providers/drand.js +87 -0
- package/dist/providers/drand.js.map +1 -0
- package/dist/providers/flow.d.ts +15 -0
- package/dist/providers/flow.d.ts.map +1 -0
- package/dist/providers/flow.js +82 -0
- package/dist/providers/flow.js.map +1 -0
- package/dist/providers/index.d.ts +56 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +32 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/inmetro.d.ts +17 -0
- package/dist/providers/inmetro.d.ts.map +1 -0
- package/dist/providers/inmetro.js +25 -0
- package/dist/providers/inmetro.js.map +1 -0
- package/dist/providers/jitter.d.ts +33 -0
- package/dist/providers/jitter.d.ts.map +1 -0
- package/dist/providers/jitter.js +81 -0
- package/dist/providers/jitter.js.map +1 -0
- package/dist/providers/lfdr.d.ts +11 -0
- package/dist/providers/lfdr.d.ts.map +1 -0
- package/dist/providers/lfdr.js +34 -0
- package/dist/providers/lfdr.js.map +1 -0
- package/dist/providers/microphone.d.ts +26 -0
- package/dist/providers/microphone.d.ts.map +1 -0
- package/dist/providers/microphone.js +120 -0
- package/dist/providers/microphone.js.map +1 -0
- package/dist/providers/nist-beacon.d.ts +11 -0
- package/dist/providers/nist-beacon.d.ts.map +1 -0
- package/dist/providers/nist-beacon.js +20 -0
- package/dist/providers/nist-beacon.js.map +1 -0
- package/dist/providers/nqsn.d.ts +11 -0
- package/dist/providers/nqsn.d.ts.map +1 -0
- package/dist/providers/nqsn.js +16 -0
- package/dist/providers/nqsn.js.map +1 -0
- package/dist/providers/outshift.d.ts +14 -0
- package/dist/providers/outshift.d.ts.map +1 -0
- package/dist/providers/outshift.js +52 -0
- package/dist/providers/outshift.js.map +1 -0
- package/dist/providers/padova.d.ts +12 -0
- package/dist/providers/padova.d.ts.map +1 -0
- package/dist/providers/padova.js +56 -0
- package/dist/providers/padova.js.map +1 -0
- package/dist/providers/qbck.d.ts +13 -0
- package/dist/providers/qbck.d.ts.map +1 -0
- package/dist/providers/qbck.js +62 -0
- package/dist/providers/qbck.js.map +1 -0
- package/dist/providers/qci.d.ts +14 -0
- package/dist/providers/qci.d.ts.map +1 -0
- package/dist/providers/qci.js +91 -0
- package/dist/providers/qci.js.map +1 -0
- package/dist/providers/qrandom.d.ts +12 -0
- package/dist/providers/qrandom.d.ts.map +1 -0
- package/dist/providers/qrandom.js +39 -0
- package/dist/providers/qrandom.js.map +1 -0
- package/dist/providers/randao.d.ts +14 -0
- package/dist/providers/randao.d.ts.map +1 -0
- package/dist/providers/randao.js +81 -0
- package/dist/providers/randao.js.map +1 -0
- package/dist/providers/random-org.d.ts +13 -0
- package/dist/providers/random-org.d.ts.map +1 -0
- package/dist/providers/random-org.js +89 -0
- package/dist/providers/random-org.js.map +1 -0
- package/dist/providers/sdr.d.ts +21 -0
- package/dist/providers/sdr.d.ts.map +1 -0
- package/dist/providers/sdr.js +63 -0
- package/dist/providers/sdr.js.map +1 -0
- package/dist/providers/sensor.d.ts +24 -0
- package/dist/providers/sensor.d.ts.map +1 -0
- package/dist/providers/sensor.js +119 -0
- package/dist/providers/sensor.js.map +1 -0
- package/dist/providers/serial.d.ts +35 -0
- package/dist/providers/serial.d.ts.map +1 -0
- package/dist/providers/serial.js +78 -0
- package/dist/providers/serial.js.map +1 -0
- package/dist/providers/solana.d.ts +13 -0
- package/dist/providers/solana.d.ts.map +1 -0
- package/dist/providers/solana.js +83 -0
- package/dist/providers/solana.js.map +1 -0
- package/dist/providers/superrand.d.ts +35 -0
- package/dist/providers/superrand.d.ts.map +1 -0
- package/dist/providers/superrand.js +215 -0
- package/dist/providers/superrand.js.map +1 -0
- package/dist/providers/tezos.d.ts +13 -0
- package/dist/providers/tezos.d.ts.map +1 -0
- package/dist/providers/tezos.js +92 -0
- package/dist/providers/tezos.js.map +1 -0
- package/dist/providers/uchile.d.ts +11 -0
- package/dist/providers/uchile.d.ts.map +1 -0
- package/dist/providers/uchile.js +22 -0
- package/dist/providers/uchile.js.map +1 -0
- package/dist/strategies/fallback.d.ts +12 -0
- package/dist/strategies/fallback.d.ts.map +1 -0
- package/dist/strategies/fallback.js +45 -0
- package/dist/strategies/fallback.js.map +1 -0
- package/dist/strategies/race.d.ts +7 -0
- package/dist/strategies/race.d.ts.map +1 -0
- package/dist/strategies/race.js +41 -0
- package/dist/strategies/race.js.map +1 -0
- package/dist/strategies/xor.d.ts +9 -0
- package/dist/strategies/xor.d.ts.map +1 -0
- package/dist/strategies/xor.js +56 -0
- package/dist/strategies/xor.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { packBits } from '../internal/bits.js';
|
|
2
|
+
import { sampledProvider } from '../internal/sampled.js';
|
|
3
|
+
/** Extract the lowest `bitsPerSample` bits of each sample (Float32 scaled to int16 first). */
|
|
4
|
+
export function sampleLsbBits(samples, bitsPerSample) {
|
|
5
|
+
const isFloat = samples instanceof Float32Array;
|
|
6
|
+
const bits = [];
|
|
7
|
+
for (let i = 0; i < samples.length; i++) {
|
|
8
|
+
let value = samples[i];
|
|
9
|
+
if (isFloat) {
|
|
10
|
+
value = Math.round(Math.max(-1, Math.min(1, value)) * 32_767);
|
|
11
|
+
}
|
|
12
|
+
for (let b = bitsPerSample - 1; b >= 0; b--) {
|
|
13
|
+
bits.push((value >> b) & 1);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return bits;
|
|
17
|
+
}
|
|
18
|
+
const CAPTURE_BUFFER_SAMPLES = 4096;
|
|
19
|
+
function browserSampleSource() {
|
|
20
|
+
return {
|
|
21
|
+
async *samples(signal) {
|
|
22
|
+
const mediaDevices = globalThis.navigator?.mediaDevices;
|
|
23
|
+
if (typeof mediaDevices?.getUserMedia !== 'function') {
|
|
24
|
+
throw new TypeError('micEntropy: no microphone in this runtime — pass a { source } (in Node: ffmpegSampleSource from @mindpeeker/entropy/node)');
|
|
25
|
+
}
|
|
26
|
+
// Disable all DSP the platform lets us disable; browsers do not always
|
|
27
|
+
// honor these, which is exactly what the health tests guard against.
|
|
28
|
+
const stream = await mediaDevices.getUserMedia({
|
|
29
|
+
audio: { echoCancellation: false, noiseSuppression: false, autoGainControl: false },
|
|
30
|
+
});
|
|
31
|
+
const AudioContextCtor = globalThis.AudioContext;
|
|
32
|
+
if (!AudioContextCtor) {
|
|
33
|
+
for (const track of stream.getTracks())
|
|
34
|
+
track.stop();
|
|
35
|
+
throw new TypeError('micEntropy: AudioContext unavailable in this runtime');
|
|
36
|
+
}
|
|
37
|
+
const context = new AudioContextCtor();
|
|
38
|
+
const queue = [];
|
|
39
|
+
let notify = null;
|
|
40
|
+
const push = (chunk) => {
|
|
41
|
+
queue.push(chunk);
|
|
42
|
+
notify?.();
|
|
43
|
+
};
|
|
44
|
+
const sourceNode = context.createMediaStreamSource(stream);
|
|
45
|
+
// ScriptProcessorNode is deprecated but universal and asset-free; an
|
|
46
|
+
// AudioWorklet would need a module URL. Entropy harvesting does not
|
|
47
|
+
// care about the latency drawbacks.
|
|
48
|
+
const processor = context.createScriptProcessor(CAPTURE_BUFFER_SAMPLES, 1, 1);
|
|
49
|
+
processor.onaudioprocess = (event) => {
|
|
50
|
+
push(new Float32Array(event.inputBuffer.getChannelData(0)));
|
|
51
|
+
};
|
|
52
|
+
sourceNode.connect(processor);
|
|
53
|
+
processor.connect(context.destination);
|
|
54
|
+
try {
|
|
55
|
+
while (true) {
|
|
56
|
+
if (signal?.aborted)
|
|
57
|
+
throw signal.reason;
|
|
58
|
+
const chunk = queue.shift();
|
|
59
|
+
if (chunk) {
|
|
60
|
+
yield chunk;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
await new Promise((resolve) => {
|
|
64
|
+
notify = resolve;
|
|
65
|
+
});
|
|
66
|
+
notify = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
processor.disconnect();
|
|
72
|
+
sourceNode.disconnect();
|
|
73
|
+
for (const track of stream.getTracks())
|
|
74
|
+
track.stop();
|
|
75
|
+
await context.close().catch(() => { });
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Microphone ADC noise — the least significant bits of the audio samples.
|
|
82
|
+
* MEMS microphones and browser DSP can interfere; keep expectations modest
|
|
83
|
+
* and rely on the health tests to catch dead or processed inputs.
|
|
84
|
+
*/
|
|
85
|
+
export function micEntropy(opts = {}) {
|
|
86
|
+
const { bitsPerSample = 1, warmupMs = 200, sampleRate = 48_000 } = opts;
|
|
87
|
+
const source = opts.source ?? browserSampleSource();
|
|
88
|
+
const warmupSamples = Math.ceil((warmupMs / 1000) * sampleRate);
|
|
89
|
+
async function* open(signal) {
|
|
90
|
+
let skipped = 0;
|
|
91
|
+
let leftover = [];
|
|
92
|
+
for await (let chunk of source.samples(signal)) {
|
|
93
|
+
if (signal?.aborted)
|
|
94
|
+
throw signal.reason ?? new DOMException('aborted', 'AbortError');
|
|
95
|
+
if (skipped < warmupSamples) {
|
|
96
|
+
const need = warmupSamples - skipped;
|
|
97
|
+
if (chunk.length <= need) {
|
|
98
|
+
skipped += chunk.length;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
skipped = warmupSamples;
|
|
102
|
+
chunk = chunk.slice(need);
|
|
103
|
+
}
|
|
104
|
+
const [bytes, rest] = packBits(leftover.concat(sampleLsbBits(chunk, bitsPerSample)));
|
|
105
|
+
leftover = rest;
|
|
106
|
+
if (bytes.length > 0)
|
|
107
|
+
yield bytes;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return sampledProvider({
|
|
111
|
+
name: 'microphone',
|
|
112
|
+
kind: 'trng',
|
|
113
|
+
privacy: 'private',
|
|
114
|
+
open,
|
|
115
|
+
defaultMinEntropyPerSample: 2,
|
|
116
|
+
defaultSafetyFactor: 4,
|
|
117
|
+
defaultTimeoutMs: 30_000, // permission prompt + warmup
|
|
118
|
+
}, opts);
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=microphone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"microphone.js","sourceRoot":"","sources":["../../src/providers/microphone.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type NistFamilyOptions } from '../internal/nist-pulse.js';
|
|
2
|
+
import type { EntropyProvider } from '../types.js';
|
|
3
|
+
export interface NistBeaconOptions extends NistFamilyOptions {
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* NIST Randomness Beacon 2.0 — 512 signed bits every 60 seconds. PUBLIC
|
|
7
|
+
* randomness; NIST's own warning applies: never use beacon values as secret
|
|
8
|
+
* keys. Useful for audits, lotteries and as an `xorMix` auditability input.
|
|
9
|
+
*/
|
|
10
|
+
export declare function nistBeacon(opts?: NistBeaconOptions): EntropyProvider;
|
|
11
|
+
//# sourceMappingURL=nist-beacon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nist-beacon.d.ts","sourceRoot":"","sources":["../../src/providers/nist-beacon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAmB,MAAM,2BAA2B,CAAA;AACnF,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,aAAa,CAAA;AAQrE,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;CAAG;AAE/D;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,eAAe,CAUxE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { nistPulseBeacon } from '../internal/nist-pulse.js';
|
|
2
|
+
const INFO = Object.freeze({
|
|
3
|
+
name: 'nist-beacon',
|
|
4
|
+
kind: 'beacon',
|
|
5
|
+
privacy: 'public',
|
|
6
|
+
});
|
|
7
|
+
/**
|
|
8
|
+
* NIST Randomness Beacon 2.0 — 512 signed bits every 60 seconds. PUBLIC
|
|
9
|
+
* randomness; NIST's own warning applies: never use beacon values as secret
|
|
10
|
+
* keys. Useful for audits, lotteries and as an `xorMix` auditability input.
|
|
11
|
+
*/
|
|
12
|
+
export function nistBeacon(opts = {}) {
|
|
13
|
+
return nistPulseBeacon({
|
|
14
|
+
info: INFO,
|
|
15
|
+
defaultBaseUrl: 'https://beacon.nist.gov/beacon/2.0',
|
|
16
|
+
latestPath: '/pulse/last',
|
|
17
|
+
defaultPollIntervalMs: 60_000,
|
|
18
|
+
}, opts);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=nist-beacon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nist-beacon.js","sourceRoot":"","sources":["../../src/providers/nist-beacon.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAGnF,MAAM,IAAI,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,QAAQ;CAClB,CAAC,CAAA;AAIF;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,OAA0B,EAAE;IACrD,OAAO,eAAe,CACpB;QACE,IAAI,EAAE,IAAI;QACV,cAAc,EAAE,oCAAoC;QACpD,UAAU,EAAE,aAAa;QACzB,qBAAqB,EAAE,MAAM;KAC9B,EACD,IAAI,CACL,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type NistFamilyOptions } from '../internal/nist-pulse.js';
|
|
2
|
+
import type { EntropyProvider } from '../types.js';
|
|
3
|
+
export interface NqsnOptions extends NistFamilyOptions {
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* NQSN Singapore quantum randomness beacon (National Quantum-Safe Network) —
|
|
7
|
+
* NIST IR 8213 format, 512 bits every 60 seconds. PUBLIC randomness.
|
|
8
|
+
* The latest-pulse route answers with a 303 redirect that fetch follows.
|
|
9
|
+
*/
|
|
10
|
+
export declare function nqsn(opts?: NqsnOptions): EntropyProvider;
|
|
11
|
+
//# sourceMappingURL=nqsn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nqsn.d.ts","sourceRoot":"","sources":["../../src/providers/nqsn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAmB,MAAM,2BAA2B,CAAA;AACnF,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,aAAa,CAAA;AAIrE,MAAM,WAAW,WAAY,SAAQ,iBAAiB;CAAG;AAEzD;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,IAAI,GAAE,WAAgB,GAAG,eAAe,CAU5D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { nistPulseBeacon } from '../internal/nist-pulse.js';
|
|
2
|
+
const INFO = Object.freeze({ name: 'nqsn', kind: 'beacon', privacy: 'public' });
|
|
3
|
+
/**
|
|
4
|
+
* NQSN Singapore quantum randomness beacon (National Quantum-Safe Network) —
|
|
5
|
+
* NIST IR 8213 format, 512 bits every 60 seconds. PUBLIC randomness.
|
|
6
|
+
* The latest-pulse route answers with a 303 redirect that fetch follows.
|
|
7
|
+
*/
|
|
8
|
+
export function nqsn(opts = {}) {
|
|
9
|
+
return nistPulseBeacon({
|
|
10
|
+
info: INFO,
|
|
11
|
+
defaultBaseUrl: 'https://quantum-entropy.sg/beacon/2.0',
|
|
12
|
+
latestPath: '/pulse',
|
|
13
|
+
defaultPollIntervalMs: 60_000,
|
|
14
|
+
}, opts);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=nqsn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nqsn.js","sourceRoot":"","sources":["../../src/providers/nqsn.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAGnF,MAAM,IAAI,GAAsB,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAA;AAIlG;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAC,OAAoB,EAAE;IACzC,OAAO,eAAe,CACpB;QACE,IAAI,EAAE,IAAI;QACV,cAAc,EAAE,uCAAuC;QACvD,UAAU,EAAE,QAAQ;QACpB,qBAAqB,EAAE,MAAM;KAC9B,EACD,IAAI,CACL,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { EntropyProvider } from '../types.js';
|
|
2
|
+
export interface OutshiftOptions {
|
|
3
|
+
/** Free key from https://qrng.outshift.com (Cisco account). */
|
|
4
|
+
apiKey: string;
|
|
5
|
+
fetch?: typeof fetch;
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Outshift by Cisco QRNG (photonic hardware). Free tier: 100k bits/day.
|
|
10
|
+
* Blocks are requested in `format: 'all'` and read from the string-valued
|
|
11
|
+
* `decimal` field — the one response shape verified in the wild.
|
|
12
|
+
*/
|
|
13
|
+
export declare function outshift(opts: OutshiftOptions): EntropyProvider;
|
|
14
|
+
//# sourceMappingURL=outshift.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outshift.d.ts","sourceRoot":"","sources":["../../src/providers/outshift.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,aAAa,CAAA;AAUrE,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAMD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,CAmC/D"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { EntropyError } from '../errors.js';
|
|
2
|
+
import { concatBytes } from '../internal/bytes.js';
|
|
3
|
+
import { fetchJson } from '../internal/http.js';
|
|
4
|
+
import { defineProvider } from '../internal/provider.js';
|
|
5
|
+
import { byteArrayFrom } from '../internal/validate.js';
|
|
6
|
+
const INFO = Object.freeze({
|
|
7
|
+
name: 'outshift',
|
|
8
|
+
kind: 'qrng',
|
|
9
|
+
privacy: 'private',
|
|
10
|
+
});
|
|
11
|
+
const MAX_PER_REQUEST = 1000; // documented cap: 1000 numbers per call
|
|
12
|
+
const DEFAULT_BASE_URL = 'https://api.qrng.outshift.com/api/v1/random_numbers';
|
|
13
|
+
/**
|
|
14
|
+
* Outshift by Cisco QRNG (photonic hardware). Free tier: 100k bits/day.
|
|
15
|
+
* Blocks are requested in `format: 'all'` and read from the string-valued
|
|
16
|
+
* `decimal` field — the one response shape verified in the wild.
|
|
17
|
+
*/
|
|
18
|
+
export function outshift(opts) {
|
|
19
|
+
if (!opts?.apiKey)
|
|
20
|
+
throw new TypeError('outshift({ apiKey }) requires a non-empty apiKey');
|
|
21
|
+
const { apiKey, baseUrl = DEFAULT_BASE_URL, fetch: fetchImpl } = opts;
|
|
22
|
+
return defineProvider({
|
|
23
|
+
...INFO,
|
|
24
|
+
async getBytes(length, reqOpts) {
|
|
25
|
+
const chunks = [];
|
|
26
|
+
for (let remaining = length; remaining > 0;) {
|
|
27
|
+
const n = Math.min(MAX_PER_REQUEST, remaining);
|
|
28
|
+
const res = await fetchJson(baseUrl, {
|
|
29
|
+
provider: INFO.name,
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: { 'x-id-api-key': apiKey },
|
|
32
|
+
body: { encoding: 'raw', format: 'all', bits_per_block: 8, number_of_blocks: n },
|
|
33
|
+
signal: reqOpts?.signal,
|
|
34
|
+
fetchImpl,
|
|
35
|
+
});
|
|
36
|
+
const entries = res?.random_numbers;
|
|
37
|
+
if (!Array.isArray(entries)) {
|
|
38
|
+
throw new EntropyError('bad_response', 'missing random_numbers array', {
|
|
39
|
+
provider: INFO.name,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const values = entries.map((entry) => typeof entry?.decimal === 'string'
|
|
43
|
+
? Number.parseInt(entry.decimal, 10)
|
|
44
|
+
: Number.NaN);
|
|
45
|
+
chunks.push(byteArrayFrom(values, n, INFO.name));
|
|
46
|
+
remaining -= n;
|
|
47
|
+
}
|
|
48
|
+
return { bytes: concatBytes(chunks), sources: [INFO] };
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=outshift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outshift.js","sourceRoot":"","sources":["../../src/providers/outshift.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAGvD,MAAM,IAAI,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;CACnB,CAAC,CAAA;AACF,MAAM,eAAe,GAAG,IAAI,CAAA,CAAC,wCAAwC;AACrE,MAAM,gBAAgB,GAAG,qDAAqD,CAAA;AAa9E;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAqB;IAC5C,IAAI,CAAC,IAAI,EAAE,MAAM;QAAE,MAAM,IAAI,SAAS,CAAC,kDAAkD,CAAC,CAAA;IAC1F,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,gBAAgB,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAA;IAErE,OAAO,cAAc,CAAC;QACpB,GAAG,IAAI;QACP,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO;YAC5B,MAAM,MAAM,GAAiB,EAAE,CAAA;YAC/B,KAAK,IAAI,SAAS,GAAG,MAAM,EAAE,SAAS,GAAG,CAAC,GAAI,CAAC;gBAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,SAAS,CAAC,CAAA;gBAC9C,MAAM,GAAG,GAAG,MAAM,SAAS,CAAmB,OAAO,EAAE;oBACrD,QAAQ,EAAE,IAAI,CAAC,IAAI;oBACnB,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE;oBACnC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE;oBAChF,MAAM,EAAE,OAAO,EAAE,MAAM;oBACvB,SAAS;iBACV,CAAC,CAAA;gBACF,MAAM,OAAO,GAAG,GAAG,EAAE,cAAc,CAAA;gBACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC5B,MAAM,IAAI,YAAY,CAAC,cAAc,EAAE,8BAA8B,EAAE;wBACrE,QAAQ,EAAE,IAAI,CAAC,IAAI;qBACpB,CAAC,CAAA;gBACJ,CAAC;gBACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACnC,OAAQ,KAA+B,EAAE,OAAO,KAAK,QAAQ;oBAC3D,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAE,KAA6B,CAAC,OAAO,EAAE,EAAE,CAAC;oBAC7D,CAAC,CAAC,MAAM,CAAC,GAAG,CACf,CAAA;gBACD,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;gBAChD,SAAS,IAAI,CAAC,CAAA;YAChB,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAA;QACxD,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EntropyProvider } from '../types.js';
|
|
2
|
+
export interface PadovaOptions {
|
|
3
|
+
fetch?: typeof fetch;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* University of Padova QRNG hosted at the VSIX internet exchange — keyless
|
|
8
|
+
* PRIVATE quantum draws, the simplest QRNG API in the wild: one GET returning
|
|
9
|
+
* base64 bytes. Academic service without an SLA.
|
|
10
|
+
*/
|
|
11
|
+
export declare function padova(opts?: PadovaOptions): EntropyProvider;
|
|
12
|
+
//# sourceMappingURL=padova.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"padova.d.ts","sourceRoot":"","sources":["../../src/providers/padova.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,aAAa,CAAA;AAWrE,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAMD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,IAAI,GAAE,aAAkB,GAAG,eAAe,CAqChE"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { EntropyError } from '../errors.js';
|
|
2
|
+
import { base64ToBytes, concatBytes } from '../internal/bytes.js';
|
|
3
|
+
import { fetchJson } from '../internal/http.js';
|
|
4
|
+
import { defineProvider } from '../internal/provider.js';
|
|
5
|
+
const INFO = Object.freeze({
|
|
6
|
+
name: 'padova',
|
|
7
|
+
kind: 'qrng',
|
|
8
|
+
privacy: 'private',
|
|
9
|
+
});
|
|
10
|
+
// No documented cap — conservative politeness limit per request.
|
|
11
|
+
const MAX_PER_REQUEST = 256;
|
|
12
|
+
const DEFAULT_BASE_URL = 'https://qrng-qtech.vs-ix.net/api/get_string_get';
|
|
13
|
+
/**
|
|
14
|
+
* University of Padova QRNG hosted at the VSIX internet exchange — keyless
|
|
15
|
+
* PRIVATE quantum draws, the simplest QRNG API in the wild: one GET returning
|
|
16
|
+
* base64 bytes. Academic service without an SLA.
|
|
17
|
+
*/
|
|
18
|
+
export function padova(opts = {}) {
|
|
19
|
+
const { baseUrl = DEFAULT_BASE_URL, fetch: fetchImpl } = opts;
|
|
20
|
+
return defineProvider({
|
|
21
|
+
...INFO,
|
|
22
|
+
async getBytes(length, reqOpts) {
|
|
23
|
+
const chunks = [];
|
|
24
|
+
for (let remaining = length; remaining > 0;) {
|
|
25
|
+
const n = Math.min(MAX_PER_REQUEST, remaining);
|
|
26
|
+
const res = await fetchJson(`${baseUrl}?string_length=${n}`, {
|
|
27
|
+
provider: INFO.name,
|
|
28
|
+
signal: reqOpts?.signal,
|
|
29
|
+
fetchImpl,
|
|
30
|
+
});
|
|
31
|
+
if (typeof res?.string !== 'string') {
|
|
32
|
+
throw new EntropyError('bad_response', 'missing string field', { provider: INFO.name });
|
|
33
|
+
}
|
|
34
|
+
let bytes;
|
|
35
|
+
try {
|
|
36
|
+
bytes = base64ToBytes(res.string);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new EntropyError('bad_response', 'invalid base64 payload', {
|
|
40
|
+
provider: INFO.name,
|
|
41
|
+
cause: error,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (bytes.length !== n) {
|
|
45
|
+
throw new EntropyError('bad_response', `expected ${n} bytes, got ${bytes.length}`, {
|
|
46
|
+
provider: INFO.name,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
chunks.push(bytes);
|
|
50
|
+
remaining -= n;
|
|
51
|
+
}
|
|
52
|
+
return { bytes: concatBytes(chunks), sources: [INFO] };
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=padova.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"padova.js","sourceRoot":"","sources":["../../src/providers/padova.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGxD,MAAM,IAAI,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;CACnB,CAAC,CAAA;AACF,iEAAiE;AACjE,MAAM,eAAe,GAAG,GAAG,CAAA;AAC3B,MAAM,gBAAgB,GAAG,iDAAiD,CAAA;AAW1E;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,OAAsB,EAAE;IAC7C,MAAM,EAAE,OAAO,GAAG,gBAAgB,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAA;IAE7D,OAAO,cAAc,CAAC;QACpB,GAAG,IAAI;QACP,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO;YAC5B,MAAM,MAAM,GAAiB,EAAE,CAAA;YAC/B,KAAK,IAAI,SAAS,GAAG,MAAM,EAAE,SAAS,GAAG,CAAC,GAAI,CAAC;gBAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,SAAS,CAAC,CAAA;gBAC9C,MAAM,GAAG,GAAG,MAAM,SAAS,CAAiB,GAAG,OAAO,kBAAkB,CAAC,EAAE,EAAE;oBAC3E,QAAQ,EAAE,IAAI,CAAC,IAAI;oBACnB,MAAM,EAAE,OAAO,EAAE,MAAM;oBACvB,SAAS;iBACV,CAAC,CAAA;gBACF,IAAI,OAAO,GAAG,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACpC,MAAM,IAAI,YAAY,CAAC,cAAc,EAAE,sBAAsB,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;gBACzF,CAAC;gBACD,IAAI,KAAiB,CAAA;gBACrB,IAAI,CAAC;oBACH,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;gBACnC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,IAAI,YAAY,CAAC,cAAc,EAAE,wBAAwB,EAAE;wBAC/D,QAAQ,EAAE,IAAI,CAAC,IAAI;wBACnB,KAAK,EAAE,KAAK;qBACb,CAAC,CAAA;gBACJ,CAAC;gBACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,MAAM,IAAI,YAAY,CAAC,cAAc,EAAE,YAAY,CAAC,eAAe,KAAK,CAAC,MAAM,EAAE,EAAE;wBACjF,QAAQ,EAAE,IAAI,CAAC,IAAI;qBACpB,CAAC,CAAA;gBACJ,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAClB,SAAS,IAAI,CAAC,CAAA;YAChB,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAA;QACxD,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EntropyProvider } from '../types.js';
|
|
2
|
+
export interface QbckOptions {
|
|
3
|
+
/** Free key by email registration at quantumblockchains.io. Sits in the URL path. */
|
|
4
|
+
apiKey: string;
|
|
5
|
+
fetch?: typeof fetch;
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Quantum Blockchains QRNG aggregator (IDQ Quantis, qStream, SeQRNG, Tropos
|
|
10
|
+
* hardware behind one API). PRIVATE draws; free key by email registration.
|
|
11
|
+
*/
|
|
12
|
+
export declare function qbck(opts: QbckOptions): EntropyProvider;
|
|
13
|
+
//# sourceMappingURL=qbck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qbck.d.ts","sourceRoot":"","sources":["../../src/providers/qbck.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,aAAa,CAAA;AAMrE,MAAM,WAAW,WAAW;IAC1B,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAyCD;;;GAGG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe,CAqBvD"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { EntropyError } from '../errors.js';
|
|
2
|
+
import { concatBytes, hexToBytes } from '../internal/bytes.js';
|
|
3
|
+
import { fetchJson } from '../internal/http.js';
|
|
4
|
+
import { defineProvider } from '../internal/provider.js';
|
|
5
|
+
const INFO = Object.freeze({ name: 'qbck', kind: 'qrng', privacy: 'private' });
|
|
6
|
+
const MAX_PER_REQUEST = 256;
|
|
7
|
+
const DEFAULT_BASE_URL = 'https://qrng.qbck.io';
|
|
8
|
+
// NOTE: the qbck response schema is documented only in their PDF and the
|
|
9
|
+
// exact success shape is unverified without a registered key. The parse below
|
|
10
|
+
// tolerates the two plausible shapes (array of hex strings / single hex
|
|
11
|
+
// string, under data.result or result). VERIFY-WITH-KEY before production.
|
|
12
|
+
function parseHexResult(res, expected) {
|
|
13
|
+
const raw = res?.data?.result ?? res?.result;
|
|
14
|
+
const joined = Array.isArray(raw) ? raw.join('') : typeof raw === 'string' ? raw : null;
|
|
15
|
+
if (joined === null) {
|
|
16
|
+
const detail = typeof res?.message === 'string' ? res.message : 'missing result field';
|
|
17
|
+
throw new EntropyError('bad_response', `qbck: ${detail}`, { provider: INFO.name });
|
|
18
|
+
}
|
|
19
|
+
let bytes;
|
|
20
|
+
try {
|
|
21
|
+
bytes = hexToBytes(joined);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
throw new EntropyError('bad_response', 'qbck: invalid hex payload', {
|
|
25
|
+
provider: INFO.name,
|
|
26
|
+
cause: error,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (bytes.length !== expected) {
|
|
30
|
+
throw new EntropyError('bad_response', `qbck: expected ${expected} bytes, got ${bytes.length}`, {
|
|
31
|
+
provider: INFO.name,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return bytes;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Quantum Blockchains QRNG aggregator (IDQ Quantis, qStream, SeQRNG, Tropos
|
|
38
|
+
* hardware behind one API). PRIVATE draws; free key by email registration.
|
|
39
|
+
*/
|
|
40
|
+
export function qbck(opts) {
|
|
41
|
+
if (!opts?.apiKey)
|
|
42
|
+
throw new TypeError('qbck({ apiKey }) requires a non-empty apiKey');
|
|
43
|
+
const { apiKey, baseUrl = DEFAULT_BASE_URL, fetch: fetchImpl } = opts;
|
|
44
|
+
return defineProvider({
|
|
45
|
+
...INFO,
|
|
46
|
+
async getBytes(length, reqOpts) {
|
|
47
|
+
const chunks = [];
|
|
48
|
+
for (let remaining = length; remaining > 0;) {
|
|
49
|
+
const n = Math.min(MAX_PER_REQUEST, remaining);
|
|
50
|
+
const res = await fetchJson(`${baseUrl}/${apiKey}/qbck/block/hex?size=${n}`, {
|
|
51
|
+
provider: INFO.name,
|
|
52
|
+
signal: reqOpts?.signal,
|
|
53
|
+
fetchImpl,
|
|
54
|
+
});
|
|
55
|
+
chunks.push(parseHexResult(res, n));
|
|
56
|
+
remaining -= n;
|
|
57
|
+
}
|
|
58
|
+
return { bytes: concatBytes(chunks), sources: [INFO] };
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=qbck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qbck.js","sourceRoot":"","sources":["../../src/providers/qbck.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { EntropyProvider } from '../types.js';
|
|
2
|
+
export interface QciOptions {
|
|
3
|
+
/** QCi API token (exchanged for a short-lived bearer token). */
|
|
4
|
+
apiToken: string;
|
|
5
|
+
fetch?: typeof fetch;
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Quantum Computing Inc. uQRNG (photonic). OAuth2-style flow: the long-lived
|
|
10
|
+
* API token is exchanged for a bearer token, cached until expiry, and
|
|
11
|
+
* refreshed once automatically when a request comes back 401.
|
|
12
|
+
*/
|
|
13
|
+
export declare function qci(opts: QciOptions): EntropyProvider;
|
|
14
|
+
//# sourceMappingURL=qci.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qci.d.ts","sourceRoot":"","sources":["../../src/providers/qci.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAA4C,MAAM,aAAa,CAAA;AAQ5F,MAAM,WAAW,UAAU;IACzB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAOD;;;;GAIG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,CAgFrD"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { EntropyError } from '../errors.js';
|
|
2
|
+
import { concatBytes } from '../internal/bytes.js';
|
|
3
|
+
import { fetchJson } from '../internal/http.js';
|
|
4
|
+
import { defineProvider } from '../internal/provider.js';
|
|
5
|
+
import { byteArrayFrom } from '../internal/validate.js';
|
|
6
|
+
const INFO = Object.freeze({ name: 'qci', kind: 'qrng', privacy: 'private' });
|
|
7
|
+
// API allows up to 1M samples/request; stay well below.
|
|
8
|
+
const MAX_PER_REQUEST = 100_000;
|
|
9
|
+
const DEFAULT_BASE_URL = 'https://api.qci-prod.com';
|
|
10
|
+
const TOKEN_SAFETY_MARGIN_MS = 30_000;
|
|
11
|
+
/**
|
|
12
|
+
* Quantum Computing Inc. uQRNG (photonic). OAuth2-style flow: the long-lived
|
|
13
|
+
* API token is exchanged for a bearer token, cached until expiry, and
|
|
14
|
+
* refreshed once automatically when a request comes back 401.
|
|
15
|
+
*/
|
|
16
|
+
export function qci(opts) {
|
|
17
|
+
if (!opts?.apiToken)
|
|
18
|
+
throw new TypeError('qci({ apiToken }) requires a non-empty apiToken');
|
|
19
|
+
const { apiToken, baseUrl = DEFAULT_BASE_URL, fetch: fetchImpl } = opts;
|
|
20
|
+
let cached = null;
|
|
21
|
+
let inflight = null;
|
|
22
|
+
async function getToken(signal) {
|
|
23
|
+
if (cached && Date.now() < cached.expiresAt - TOKEN_SAFETY_MARGIN_MS)
|
|
24
|
+
return cached.token;
|
|
25
|
+
if (!inflight) {
|
|
26
|
+
inflight = fetchJson(`${baseUrl}/auth/v1/access-tokens`, {
|
|
27
|
+
provider: INFO.name,
|
|
28
|
+
method: 'POST',
|
|
29
|
+
body: { refresh_token: apiToken },
|
|
30
|
+
signal,
|
|
31
|
+
fetchImpl,
|
|
32
|
+
})
|
|
33
|
+
.then((res) => {
|
|
34
|
+
const token = res?.access_token;
|
|
35
|
+
if (typeof token !== 'string' || token.length === 0) {
|
|
36
|
+
throw new EntropyError('auth', 'QCi token exchange returned no access_token', {
|
|
37
|
+
provider: INFO.name,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// Observed in the wild as an absolute unix timestamp despite the
|
|
41
|
+
// OAuth-style name; handle both interpretations.
|
|
42
|
+
const raw = res?.expires_in;
|
|
43
|
+
const expiresAt = typeof raw === 'number'
|
|
44
|
+
? raw > 1_000_000_000
|
|
45
|
+
? raw * 1000
|
|
46
|
+
: Date.now() + raw * 1000
|
|
47
|
+
: Date.now() + 300_000;
|
|
48
|
+
return { token, expiresAt };
|
|
49
|
+
})
|
|
50
|
+
.finally(() => {
|
|
51
|
+
inflight = null;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
cached = await inflight;
|
|
55
|
+
return cached.token;
|
|
56
|
+
}
|
|
57
|
+
async function fetchSamples(n, reqOpts, retried) {
|
|
58
|
+
const token = await getToken(reqOpts?.signal);
|
|
59
|
+
try {
|
|
60
|
+
const res = await fetchJson(`${baseUrl}/qrng/random_numbers`, {
|
|
61
|
+
provider: INFO.name,
|
|
62
|
+
method: 'POST',
|
|
63
|
+
headers: { authorization: `Bearer ${token}` },
|
|
64
|
+
body: { distribution: 'uniform_discrete', output_type: 'decimal', n_samples: n, n_bits: 8 },
|
|
65
|
+
signal: reqOpts?.signal,
|
|
66
|
+
fetchImpl,
|
|
67
|
+
});
|
|
68
|
+
return byteArrayFrom(res, n, INFO.name);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (!retried && error instanceof EntropyError && error.code === 'auth') {
|
|
72
|
+
cached = null; // token expired server-side — re-authenticate once
|
|
73
|
+
return fetchSamples(n, reqOpts, true);
|
|
74
|
+
}
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return defineProvider({
|
|
79
|
+
...INFO,
|
|
80
|
+
async getBytes(length, reqOpts) {
|
|
81
|
+
const chunks = [];
|
|
82
|
+
for (let remaining = length; remaining > 0;) {
|
|
83
|
+
const n = Math.min(MAX_PER_REQUEST, remaining);
|
|
84
|
+
chunks.push(await fetchSamples(n, reqOpts, false));
|
|
85
|
+
remaining -= n;
|
|
86
|
+
}
|
|
87
|
+
return { bytes: concatBytes(chunks), sources: [INFO] };
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=qci.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qci.js","sourceRoot":"","sources":["../../src/providers/qci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAGvD,MAAM,IAAI,GAAsB,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAA;AAChG,wDAAwD;AACxD,MAAM,eAAe,GAAG,OAAO,CAAA;AAC/B,MAAM,gBAAgB,GAAG,0BAA0B,CAAA;AACnD,MAAM,sBAAsB,GAAG,MAAM,CAAA;AAcrC;;;;GAIG;AACH,MAAM,UAAU,GAAG,CAAC,IAAgB;IAClC,IAAI,CAAC,IAAI,EAAE,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAA;IAC3F,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,gBAAgB,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAA;IAEvE,IAAI,MAAM,GAAgD,IAAI,CAAA;IAC9D,IAAI,QAAQ,GAAyD,IAAI,CAAA;IAEzE,KAAK,UAAU,QAAQ,CAAC,MAAoB;QAC1C,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,sBAAsB;YAAE,OAAO,MAAM,CAAC,KAAK,CAAA;QACzF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,GAAG,SAAS,CAAgB,GAAG,OAAO,wBAAwB,EAAE;gBACtE,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE;gBACjC,MAAM;gBACN,SAAS;aACV,CAAC;iBACC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;gBACZ,MAAM,KAAK,GAAG,GAAG,EAAE,YAAY,CAAA;gBAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACpD,MAAM,IAAI,YAAY,CAAC,MAAM,EAAE,6CAA6C,EAAE;wBAC5E,QAAQ,EAAE,IAAI,CAAC,IAAI;qBACpB,CAAC,CAAA;gBACJ,CAAC;gBACD,iEAAiE;gBACjE,iDAAiD;gBACjD,MAAM,GAAG,GAAG,GAAG,EAAE,UAAU,CAAA;gBAC3B,MAAM,SAAS,GACb,OAAO,GAAG,KAAK,QAAQ;oBACrB,CAAC,CAAC,GAAG,GAAG,aAAa;wBACnB,CAAC,CAAC,GAAG,GAAG,IAAI;wBACZ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI;oBAC3B,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAA;gBAC1B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;YAC7B,CAAC,CAAC;iBACD,OAAO,CAAC,GAAG,EAAE;gBACZ,QAAQ,GAAG,IAAI,CAAA;YACjB,CAAC,CAAC,CAAA;QACN,CAAC;QACD,MAAM,GAAG,MAAM,QAAQ,CAAA;QACvB,OAAO,MAAM,CAAC,KAAK,CAAA;IACrB,CAAC;IAED,KAAK,UAAU,YAAY,CACzB,CAAS,EACT,OAA0C,EAC1C,OAAgB;QAEhB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC7C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAU,GAAG,OAAO,sBAAsB,EAAE;gBACrE,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;gBAC7C,IAAI,EAAE,EAAE,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;gBAC3F,MAAM,EAAE,OAAO,EAAE,MAAM;gBACvB,SAAS;aACV,CAAC,CAAA;YACF,OAAO,aAAa,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACvE,MAAM,GAAG,IAAI,CAAA,CAAC,mDAAmD;gBACjE,OAAO,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;YACvC,CAAC;YACD,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAC;QACpB,GAAG,IAAI;QACP,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO;YAC5B,MAAM,MAAM,GAAiB,EAAE,CAAA;YAC/B,KAAK,IAAI,SAAS,GAAG,MAAM,EAAE,SAAS,GAAG,CAAC,GAAI,CAAC;gBAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,SAAS,CAAC,CAAA;gBAC9C,MAAM,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;gBAClD,SAAS,IAAI,CAAC,CAAA;YAChB,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAA;QACxD,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EntropyProvider } from '../types.js';
|
|
2
|
+
export interface QrandomIoOptions {
|
|
3
|
+
fetch?: typeof fetch;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* qrandom.io — free, keyless QRNG backed by ID Quantique Quantis hardware.
|
|
8
|
+
* Responses are Falcon-512-signed by the service (signature not verified
|
|
9
|
+
* here in v1). Anonymous operator: fine in a mix, not as a trust anchor.
|
|
10
|
+
*/
|
|
11
|
+
export declare function qrandomIo(opts?: QrandomIoOptions): EntropyProvider;
|
|
12
|
+
//# sourceMappingURL=qrandom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qrandom.d.ts","sourceRoot":"","sources":["../../src/providers/qrandom.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,aAAa,CAAA;AAWrE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAMD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,GAAE,gBAAqB,GAAG,eAAe,CAqBtE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { concatBytes } from '../internal/bytes.js';
|
|
2
|
+
import { fetchJson } from '../internal/http.js';
|
|
3
|
+
import { defineProvider } from '../internal/provider.js';
|
|
4
|
+
import { byteArrayFrom } from '../internal/validate.js';
|
|
5
|
+
const INFO = Object.freeze({
|
|
6
|
+
name: 'qrandom.io',
|
|
7
|
+
kind: 'qrng',
|
|
8
|
+
privacy: 'private',
|
|
9
|
+
});
|
|
10
|
+
// Undocumented cap — stay at a polite request size.
|
|
11
|
+
const MAX_PER_REQUEST = 1000;
|
|
12
|
+
const DEFAULT_BASE_URL = 'https://qrandom.io/api/random/ints';
|
|
13
|
+
/**
|
|
14
|
+
* qrandom.io — free, keyless QRNG backed by ID Quantique Quantis hardware.
|
|
15
|
+
* Responses are Falcon-512-signed by the service (signature not verified
|
|
16
|
+
* here in v1). Anonymous operator: fine in a mix, not as a trust anchor.
|
|
17
|
+
*/
|
|
18
|
+
export function qrandomIo(opts = {}) {
|
|
19
|
+
const { baseUrl = DEFAULT_BASE_URL, fetch: fetchImpl } = opts;
|
|
20
|
+
return defineProvider({
|
|
21
|
+
...INFO,
|
|
22
|
+
async getBytes(length, reqOpts) {
|
|
23
|
+
const chunks = [];
|
|
24
|
+
for (let remaining = length; remaining > 0;) {
|
|
25
|
+
const n = Math.min(MAX_PER_REQUEST, remaining);
|
|
26
|
+
const query = new URLSearchParams({ n: String(n), min: '0', max: '255' });
|
|
27
|
+
const res = await fetchJson(`${baseUrl}?${query}`, {
|
|
28
|
+
provider: INFO.name,
|
|
29
|
+
signal: reqOpts?.signal,
|
|
30
|
+
fetchImpl,
|
|
31
|
+
});
|
|
32
|
+
chunks.push(byteArrayFrom(res?.numbers, n, INFO.name));
|
|
33
|
+
remaining -= n;
|
|
34
|
+
}
|
|
35
|
+
return { bytes: concatBytes(chunks), sources: [INFO] };
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=qrandom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qrandom.js","sourceRoot":"","sources":["../../src/providers/qrandom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAGvD,MAAM,IAAI,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;CACnB,CAAC,CAAA;AACF,oDAAoD;AACpD,MAAM,eAAe,GAAG,IAAI,CAAA;AAC5B,MAAM,gBAAgB,GAAG,oCAAoC,CAAA;AAW7D;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,OAAyB,EAAE;IACnD,MAAM,EAAE,OAAO,GAAG,gBAAgB,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAA;IAE7D,OAAO,cAAc,CAAC;QACpB,GAAG,IAAI;QACP,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO;YAC5B,MAAM,MAAM,GAAiB,EAAE,CAAA;YAC/B,KAAK,IAAI,SAAS,GAAG,MAAM,EAAE,SAAS,GAAG,CAAC,GAAI,CAAC;gBAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,SAAS,CAAC,CAAA;gBAC9C,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAA;gBACzE,MAAM,GAAG,GAAG,MAAM,SAAS,CAAkB,GAAG,OAAO,IAAI,KAAK,EAAE,EAAE;oBAClE,QAAQ,EAAE,IAAI,CAAC,IAAI;oBACnB,MAAM,EAAE,OAAO,EAAE,MAAM;oBACvB,SAAS;iBACV,CAAC,CAAA;gBACF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;gBACtD,SAAS,IAAI,CAAC,CAAA;YAChB,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAA;QACxD,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|