quantum-resistant-rustykey 0.13.9 → 0.14.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/README.md +5 -0
- package/dist/index.d.ts +93 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +594 -121
- package/dist/index.js.map +1 -1
- package/dist/opfs-sk-worker.js +5185 -0
- package/dist/opfs-sk-worker.js.map +7 -0
- package/dist/sqisign-accel-worker.js +118 -59
- package/dist/sqisign-accel-worker.js.map +3 -3
- package/package.json +4 -2
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
// src/opfs-sk/browser-gate.ts
|
|
2
|
+
var OPFS_SK_WORKER_NAME = "qrr-opfs-sk";
|
|
3
|
+
var BROWSER_SK_CEREMONY_ERROR = "Browser keygen/sign requires WebAuthn userVerification:required, PRF, TEE, and loadOpfsSkWallet() (ciphertext in OPFS). Node and server REST loaders are unchanged. verify() remains available.";
|
|
4
|
+
function hasWorkerGlobalScope() {
|
|
5
|
+
return typeof globalThis.WorkerGlobalScope !== "undefined";
|
|
6
|
+
}
|
|
7
|
+
function hasWindow() {
|
|
8
|
+
return typeof globalThis.window !== "undefined";
|
|
9
|
+
}
|
|
10
|
+
function workerName() {
|
|
11
|
+
const name = globalThis.name;
|
|
12
|
+
return typeof name === "string" ? name : "";
|
|
13
|
+
}
|
|
14
|
+
function isUnconstrainedSigningRealm() {
|
|
15
|
+
return !hasWindow() && !hasWorkerGlobalScope();
|
|
16
|
+
}
|
|
17
|
+
function isOpfsSkWorkerRealm() {
|
|
18
|
+
return hasWorkerGlobalScope() && !hasWindow() && workerName() === OPFS_SK_WORKER_NAME;
|
|
19
|
+
}
|
|
20
|
+
function assertBrowserSkCeremonyAllowed() {
|
|
21
|
+
if (isUnconstrainedSigningRealm() || isOpfsSkWorkerRealm()) return;
|
|
22
|
+
throw new Error(BROWSER_SK_CEREMONY_ERROR);
|
|
23
|
+
}
|
|
24
|
+
|
|
1
25
|
// src/signature-common.ts
|
|
2
26
|
function fromHex(hex) {
|
|
3
27
|
const cleaned = hex.trim().replace(/^0x/i, "").replace(/\s+/g, "");
|
|
@@ -17,12 +41,36 @@ function asBytes(value) {
|
|
|
17
41
|
}
|
|
18
42
|
function withStack(module, run) {
|
|
19
43
|
const stack = module.stackSave();
|
|
44
|
+
const regions = [];
|
|
20
45
|
try {
|
|
21
|
-
return run((size) =>
|
|
46
|
+
return run((size) => {
|
|
47
|
+
const ptr = module.stackAlloc(size);
|
|
48
|
+
regions.push({ ptr, length: size });
|
|
49
|
+
return ptr;
|
|
50
|
+
});
|
|
22
51
|
} finally {
|
|
52
|
+
zeroizeStackAllocations(module, stack, regions);
|
|
23
53
|
module.stackRestore(stack);
|
|
24
54
|
}
|
|
25
55
|
}
|
|
56
|
+
function zeroizeBytes(bytes) {
|
|
57
|
+
bytes.fill(0);
|
|
58
|
+
}
|
|
59
|
+
function zeroizeStackAllocations(module, savedStack, regions) {
|
|
60
|
+
const heap = module.HEAPU8;
|
|
61
|
+
for (const { ptr, length } of regions) {
|
|
62
|
+
zeroizeHeapRange(heap, ptr, ptr + length);
|
|
63
|
+
}
|
|
64
|
+
const now = module.stackSave();
|
|
65
|
+
const lo = now < savedStack ? now : savedStack;
|
|
66
|
+
const hi = now < savedStack ? savedStack : now;
|
|
67
|
+
zeroizeHeapRange(heap, lo, hi);
|
|
68
|
+
}
|
|
69
|
+
function zeroizeHeapRange(heap, start, end) {
|
|
70
|
+
const lo = start < 0 ? 0 : start;
|
|
71
|
+
const hi = end > heap.length ? heap.length : end;
|
|
72
|
+
if (hi > lo) heap.fill(0, lo, hi);
|
|
73
|
+
}
|
|
26
74
|
function writeBytes(module, alloc, bytes) {
|
|
27
75
|
const ptr = alloc(bytes.length);
|
|
28
76
|
module.HEAPU8.set(bytes, ptr);
|
|
@@ -1440,43 +1488,47 @@ async function runKeygen(variant) {
|
|
|
1440
1488
|
)
|
|
1441
1489
|
)
|
|
1442
1490
|
);
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
module[`_sqisign_${p}_public_key_bytes`]
|
|
1447
|
-
)
|
|
1448
|
-
);
|
|
1449
|
-
const skPtr = alloc(
|
|
1450
|
-
wasmExport(
|
|
1451
|
-
module[`_sqisign_${p}_private_key_bytes`]
|
|
1452
|
-
)
|
|
1453
|
-
);
|
|
1454
|
-
const seedPtr = writeBytes(module, alloc, seed);
|
|
1455
|
-
const rc = wasmExportWithArgs(
|
|
1456
|
-
module[`_sqisign_${p}_keypair_seeded`],
|
|
1457
|
-
pkPtr,
|
|
1458
|
-
skPtr,
|
|
1459
|
-
seedPtr
|
|
1460
|
-
);
|
|
1461
|
-
if (rc !== 0)
|
|
1462
|
-
throw new Error(`SQISign ${variant} keypair failed with code ${rc}`);
|
|
1463
|
-
return {
|
|
1464
|
-
pk: readBytes(
|
|
1465
|
-
module,
|
|
1466
|
-
pkPtr,
|
|
1491
|
+
try {
|
|
1492
|
+
return withStack(module, (alloc) => {
|
|
1493
|
+
const pkPtr = alloc(
|
|
1467
1494
|
wasmExport(
|
|
1468
1495
|
module[`_sqisign_${p}_public_key_bytes`]
|
|
1469
1496
|
)
|
|
1470
|
-
)
|
|
1471
|
-
|
|
1472
|
-
module,
|
|
1473
|
-
skPtr,
|
|
1497
|
+
);
|
|
1498
|
+
const skPtr = alloc(
|
|
1474
1499
|
wasmExport(
|
|
1475
1500
|
module[`_sqisign_${p}_private_key_bytes`]
|
|
1476
1501
|
)
|
|
1477
|
-
)
|
|
1478
|
-
|
|
1479
|
-
|
|
1502
|
+
);
|
|
1503
|
+
const seedPtr = writeBytes(module, alloc, seed);
|
|
1504
|
+
const rc = wasmExportWithArgs(
|
|
1505
|
+
module[`_sqisign_${p}_keypair_seeded`],
|
|
1506
|
+
pkPtr,
|
|
1507
|
+
skPtr,
|
|
1508
|
+
seedPtr
|
|
1509
|
+
);
|
|
1510
|
+
if (rc !== 0)
|
|
1511
|
+
throw new Error(`SQISign ${variant} keypair failed with code ${rc}`);
|
|
1512
|
+
return {
|
|
1513
|
+
pk: readBytes(
|
|
1514
|
+
module,
|
|
1515
|
+
pkPtr,
|
|
1516
|
+
wasmExport(
|
|
1517
|
+
module[`_sqisign_${p}_public_key_bytes`]
|
|
1518
|
+
)
|
|
1519
|
+
),
|
|
1520
|
+
sk: readBytes(
|
|
1521
|
+
module,
|
|
1522
|
+
skPtr,
|
|
1523
|
+
wasmExport(
|
|
1524
|
+
module[`_sqisign_${p}_private_key_bytes`]
|
|
1525
|
+
)
|
|
1526
|
+
)
|
|
1527
|
+
};
|
|
1528
|
+
});
|
|
1529
|
+
} finally {
|
|
1530
|
+
zeroizeBytes(seed);
|
|
1531
|
+
}
|
|
1480
1532
|
}
|
|
1481
1533
|
async function runSign(variant, msg, sk) {
|
|
1482
1534
|
const module = await getModule(variant);
|
|
@@ -1488,33 +1540,37 @@ async function runSign(variant, msg, sk) {
|
|
|
1488
1540
|
)
|
|
1489
1541
|
)
|
|
1490
1542
|
);
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1543
|
+
try {
|
|
1544
|
+
return withStack(module, (alloc) => {
|
|
1545
|
+
const sigPtr = alloc(
|
|
1546
|
+
wasmExport(
|
|
1547
|
+
module[`_sqisign_${p}_signature_bytes`]
|
|
1548
|
+
)
|
|
1549
|
+
);
|
|
1550
|
+
const msgPtr = writeBytes(module, alloc, msg);
|
|
1551
|
+
const skPtr = writeBytes(module, alloc, sk);
|
|
1552
|
+
const seedPtr = writeBytes(module, alloc, seed);
|
|
1553
|
+
const rc = wasmExportWithArgs(
|
|
1554
|
+
module[`_sqisign_${p}_sign_seeded`],
|
|
1555
|
+
sigPtr,
|
|
1556
|
+
msgPtr,
|
|
1557
|
+
msg.length,
|
|
1558
|
+
skPtr,
|
|
1559
|
+
seedPtr
|
|
1560
|
+
);
|
|
1561
|
+
if (rc !== 0)
|
|
1562
|
+
throw new Error(`SQISign ${variant} sign failed with code ${rc}`);
|
|
1563
|
+
return readBytes(
|
|
1564
|
+
module,
|
|
1565
|
+
sigPtr,
|
|
1566
|
+
wasmExport(
|
|
1567
|
+
module[`_sqisign_${p}_signature_bytes`]
|
|
1568
|
+
)
|
|
1569
|
+
);
|
|
1570
|
+
});
|
|
1571
|
+
} finally {
|
|
1572
|
+
zeroizeBytes(seed);
|
|
1573
|
+
}
|
|
1518
1574
|
}
|
|
1519
1575
|
async function runVerify(variant, sig, msg, pk) {
|
|
1520
1576
|
const module = await getModule(variant);
|
|
@@ -1535,6 +1591,9 @@ async function runVerify(variant, sig, msg, pk) {
|
|
|
1535
1591
|
}
|
|
1536
1592
|
async function handleOp(request) {
|
|
1537
1593
|
try {
|
|
1594
|
+
if (request.op === "keygen" || request.op === "sign") {
|
|
1595
|
+
assertBrowserSkCeremonyAllowed();
|
|
1596
|
+
}
|
|
1538
1597
|
if (request.op === "keygen") {
|
|
1539
1598
|
const { pk, sk } = await runKeygen(request.variant);
|
|
1540
1599
|
return { id: request.id, ok: true, pk, sk };
|