spd-lib 1.4.2 → 1.4.3
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/index.d.mts +146 -72
- package/index.d.ts +146 -72
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -1367,111 +1367,185 @@ declare class SPDShamir {
|
|
|
1367
1367
|
}
|
|
1368
1368
|
|
|
1369
1369
|
/**
|
|
1370
|
-
* SPDHandshake —
|
|
1370
|
+
* SPDHandshake — Hybrid post-quantum ephemeral key agreement for SPD sessions.
|
|
1371
1371
|
*
|
|
1372
|
-
*
|
|
1373
|
-
*
|
|
1374
|
-
*
|
|
1375
|
-
*
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
1378
|
-
*
|
|
1379
|
-
*
|
|
1380
|
-
*
|
|
1381
|
-
*
|
|
1372
|
+
* ## Cryptographic design
|
|
1373
|
+
*
|
|
1374
|
+
* Uses a **X25519 + ML-KEM-768 hybrid** construction:
|
|
1375
|
+
*
|
|
1376
|
+
* x25519_ss = X25519(myPriv, theirPub) — classical ECDH
|
|
1377
|
+
* mlkem_ss = ML-KEM-768 encap/decap — post-quantum KEM (NIST FIPS 203)
|
|
1378
|
+
* transcript = SHA3-512(loNonce ∥ hiNonce) — session-binding salt
|
|
1379
|
+
* sessionKey = HKDF-SHA-512(
|
|
1380
|
+
* IKM = x25519_ss ∥ mlkem_ss,
|
|
1381
|
+
* salt = transcript,
|
|
1382
|
+
* info = 'spd-hs-session-v1'
|
|
1383
|
+
* )
|
|
1384
|
+
*
|
|
1385
|
+
* Breaking the session key requires breaking **both** X25519 (hard classically)
|
|
1386
|
+
* **and** ML-KEM-768 (hard for quantum computers) simultaneously.
|
|
1387
|
+
*
|
|
1388
|
+
* ## Security properties
|
|
1389
|
+
*
|
|
1390
|
+
* | Property | Mechanism |
|
|
1391
|
+
* |---------------------------------|--------------------------------------------------------|
|
|
1392
|
+
* | Classical hardness | X25519 ECDH — ~2^128 classical operations |
|
|
1393
|
+
* | Quantum hardness | ML-KEM-768 — NIST FIPS 203, ~2^178 quantum ops |
|
|
1394
|
+
* | Perfect forward secrecy | All keypairs ephemeral, zeroed after derive() |
|
|
1395
|
+
* | Memory safety | Private keys XOR-blinded immediately after creation |
|
|
1396
|
+
* | Key commitment (CMT-4) | SHA3-256(sessionKey ∥ transcript) — verify before use |
|
|
1397
|
+
* | Cross-session binding | 32-byte CSPRNG nonce per session mixed into HKDF |
|
|
1398
|
+
* | Domain separation | Distinct HKDF info strings per key purpose |
|
|
1399
|
+
* | Timing safety | timingSafeEqual for all sensitive comparisons |
|
|
1400
|
+
* | Low-order point rejection | All-zero DH output rejected before HKDF |
|
|
1401
|
+
* | Input validation | Type + length checked on all inputs |
|
|
1402
|
+
* | Zero-on-free | All key material zeroed explicitly via sodium.memzero |
|
|
1403
|
+
*
|
|
1404
|
+
* ## Handshake flow
|
|
1405
|
+
*
|
|
1406
|
+
* The initiator (e.g. client) drives ML-KEM encapsulation:
|
|
1407
|
+
*
|
|
1408
|
+
* ```
|
|
1409
|
+
* INITIATOR RESPONDER
|
|
1410
|
+
* ─────────────────────────────────────────────────────
|
|
1411
|
+
* hs = SPDHandshake.createInitiator()
|
|
1412
|
+
* send → { x25519Pub, kemPub, nonce }
|
|
1413
|
+
* hs = await SPDHandshake.createResponder(
|
|
1414
|
+
* initiatorHello)
|
|
1415
|
+
* send → { x25519Pub, kemCt, nonce }
|
|
1416
|
+
* result = await hs.finalizeInitiator(
|
|
1417
|
+
* responderHello)
|
|
1418
|
+
* result = hs.responderResult()
|
|
1419
|
+
* // result.commitment === responderResult.commitment
|
|
1420
|
+
* // exchange commitments to confirm matching keys
|
|
1421
|
+
* ```
|
|
1382
1422
|
*
|
|
1383
1423
|
* ## Usage
|
|
1384
1424
|
*
|
|
1385
1425
|
* ```ts
|
|
1386
|
-
*
|
|
1387
|
-
* const server = SPDHandshake.create();
|
|
1388
|
-
* // send to client: { publicKey: server.publicKey, nonce: server.sessionNonce }
|
|
1426
|
+
* import { SPDHandshake, SPD } from 'spd-lib';
|
|
1389
1427
|
*
|
|
1390
|
-
* // ──
|
|
1391
|
-
* const
|
|
1392
|
-
* //
|
|
1393
|
-
* const clientResult = client.derive(server.publicKey, server.sessionNonce);
|
|
1428
|
+
* // ── Initiator (client) ───────────────────────────────────────────────────────
|
|
1429
|
+
* const init = await SPDHandshake.createInitiator();
|
|
1430
|
+
* socket.send(JSON.stringify(init.hello)); // { x25519Pub, kemPub, nonce }
|
|
1394
1431
|
*
|
|
1395
|
-
*
|
|
1396
|
-
* const
|
|
1432
|
+
* const respHello = JSON.parse(await socket.recv());
|
|
1433
|
+
* const initResult = await init.finalizeInitiator(respHello);
|
|
1397
1434
|
*
|
|
1398
|
-
* //
|
|
1399
|
-
*
|
|
1435
|
+
* // ── Responder (server) ───────────────────────────────────────────────────────
|
|
1436
|
+
* const resp = await SPDHandshake.createResponder(initHello);
|
|
1437
|
+
* socket.send(JSON.stringify(resp.hello)); // { x25519Pub, kemCt, nonce }
|
|
1438
|
+
* const respResult = resp.responderResult();
|
|
1400
1439
|
*
|
|
1401
|
-
* //
|
|
1402
|
-
*
|
|
1403
|
-
*
|
|
1404
|
-
* await spd.setPassKey(serverResult.sessionKey);
|
|
1440
|
+
* // ── Both sides: verify commitment matches before using key ───────────────────
|
|
1441
|
+
* // exchange initResult.commitment <→ respResult.commitment over the wire
|
|
1442
|
+
* // if they match, both sides have the same session key
|
|
1405
1443
|
*
|
|
1406
|
-
*
|
|
1407
|
-
*
|
|
1444
|
+
* const spd = new SPD();
|
|
1445
|
+
* spd.setKeyProfile('standard'); // session key is already 256-bit entropy
|
|
1446
|
+
* await spd.setPassKey(initResult.sessionKey);
|
|
1447
|
+
* initResult.destroy(); // zero raw key bytes from memory
|
|
1408
1448
|
* ```
|
|
1409
1449
|
*/
|
|
1450
|
+
/** Message sent during the handshake exchange. */
|
|
1451
|
+
interface SPDHandshakeHello {
|
|
1452
|
+
/** Base64url-encoded X25519 public key (32 bytes). */
|
|
1453
|
+
x25519Pub: string;
|
|
1454
|
+
/**
|
|
1455
|
+
* Initiator hello: base64url-encoded ML-KEM-768 public key (1184 bytes).
|
|
1456
|
+
* Responder hello: base64url-encoded ML-KEM-768 ciphertext (1088 bytes).
|
|
1457
|
+
*/
|
|
1458
|
+
kemData: string;
|
|
1459
|
+
/** Base64url-encoded random session nonce (32 bytes). */
|
|
1460
|
+
nonce: string;
|
|
1461
|
+
}
|
|
1410
1462
|
/**
|
|
1411
|
-
*
|
|
1412
|
-
*
|
|
1413
|
-
* Call `destroy()` once the passphrase has been handed to SPD's `setPassKey`.
|
|
1463
|
+
* Completed handshake result.
|
|
1464
|
+
* Call `destroy()` immediately after passing `sessionKey` to `spd.setPassKey()`.
|
|
1414
1465
|
*/
|
|
1415
1466
|
declare class SPDHandshakeResult {
|
|
1416
|
-
/**
|
|
1467
|
+
/**
|
|
1468
|
+
* 64-character hex session passphrase (256 bits of entropy).
|
|
1469
|
+
* Pass directly to `spd.setPassKey()`.
|
|
1470
|
+
*/
|
|
1417
1471
|
readonly sessionKey: string;
|
|
1418
1472
|
/**
|
|
1419
|
-
* CMT-4 key commitment: SHA3-256(sessionKeyBytes ∥
|
|
1420
|
-
* Base64url-encoded
|
|
1421
|
-
*
|
|
1473
|
+
* CMT-4 key commitment: SHA3-256(sessionKeyBytes ∥ transcriptHash).
|
|
1474
|
+
* Base64url-encoded (32 bytes).
|
|
1475
|
+
*
|
|
1476
|
+
* Exchange this with the other party and verify they match BEFORE using
|
|
1477
|
+
* `sessionKey`. If they differ, abort — a MITM substituted a key.
|
|
1422
1478
|
*/
|
|
1423
1479
|
readonly commitment: string;
|
|
1424
1480
|
private _raw;
|
|
1425
1481
|
/** @internal */
|
|
1426
|
-
constructor(raw: Buffer,
|
|
1427
|
-
/**
|
|
1482
|
+
constructor(raw: Buffer, transcript: Buffer);
|
|
1483
|
+
/**
|
|
1484
|
+
* Zero the raw session key bytes from memory.
|
|
1485
|
+
* The `sessionKey` hex string may still exist in the JS heap
|
|
1486
|
+
* (strings are immutable in V8); call this as soon as `setPassKey()` is done.
|
|
1487
|
+
*/
|
|
1428
1488
|
destroy(): void;
|
|
1429
1489
|
}
|
|
1430
|
-
/**
|
|
1431
|
-
declare class
|
|
1490
|
+
/** Initiator state returned by `SPDHandshake.createInitiator()`. */
|
|
1491
|
+
declare class SPDHandshakeInitiator {
|
|
1492
|
+
/** Send this to the responder. */
|
|
1493
|
+
readonly hello: SPDHandshakeHello;
|
|
1494
|
+
private _x25519Priv;
|
|
1495
|
+
private _kemSecretMask;
|
|
1496
|
+
private _blindedKemSK;
|
|
1497
|
+
private _nonceRaw;
|
|
1498
|
+
private _done;
|
|
1499
|
+
/** @internal */
|
|
1500
|
+
constructor(x25519PrivRaw: Buffer, x25519PubRaw: Buffer, kemSecretKey: Uint8Array, kemPublicKey: Uint8Array, nonce: Buffer);
|
|
1432
1501
|
/**
|
|
1433
|
-
*
|
|
1434
|
-
*
|
|
1502
|
+
* Complete the initiator side of the handshake using the responder's hello.
|
|
1503
|
+
*
|
|
1504
|
+
* @param responderHello The `hello` object received from the responder.
|
|
1505
|
+
* @returns `SPDHandshakeResult` — call `.destroy()` after `setPassKey()`.
|
|
1506
|
+
* @throws If already called, or if any input is malformed.
|
|
1435
1507
|
*/
|
|
1436
|
-
|
|
1508
|
+
finalizeInitiator(responderHello: SPDHandshakeHello): Promise<SPDHandshakeResult>;
|
|
1509
|
+
/** Zero all key material. Call if abandoning the handshake. */
|
|
1510
|
+
destroy(): void;
|
|
1511
|
+
}
|
|
1512
|
+
/** Responder state returned by `SPDHandshake.createResponder()`. */
|
|
1513
|
+
declare class SPDHandshakeResponder {
|
|
1514
|
+
/** Send this to the initiator. */
|
|
1515
|
+
readonly hello: SPDHandshakeHello;
|
|
1516
|
+
private _result;
|
|
1517
|
+
/** @internal */
|
|
1518
|
+
constructor(hello: SPDHandshakeHello, result: SPDHandshakeResult);
|
|
1437
1519
|
/**
|
|
1438
|
-
*
|
|
1439
|
-
*
|
|
1440
|
-
*
|
|
1441
|
-
* somehow reused.
|
|
1520
|
+
* Return the completed session result.
|
|
1521
|
+
* The responder derives its key during `createResponder()` — call this
|
|
1522
|
+
* after sending `hello` to the initiator.
|
|
1442
1523
|
*/
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
private _nonceRaw;
|
|
1524
|
+
responderResult(): SPDHandshakeResult;
|
|
1525
|
+
}
|
|
1526
|
+
declare class SPDHandshake {
|
|
1447
1527
|
private constructor();
|
|
1448
1528
|
/**
|
|
1449
|
-
* Create
|
|
1450
|
-
* and a random session nonce.
|
|
1451
|
-
*/
|
|
1452
|
-
static create(): SPDHandshake;
|
|
1453
|
-
/**
|
|
1454
|
-
* Derive the shared session key from the other party's public key and nonce.
|
|
1529
|
+
* Create the initiator side of the handshake.
|
|
1455
1530
|
*
|
|
1456
|
-
*
|
|
1457
|
-
*
|
|
1458
|
-
* match if and only if both sides derived the same key.
|
|
1531
|
+
* Generates an ephemeral X25519 keypair and ML-KEM-768 keypair.
|
|
1532
|
+
* Send `initiator.hello` to the responder.
|
|
1459
1533
|
*
|
|
1460
|
-
* @
|
|
1461
|
-
* @param theirSessionNonce The other party's `sessionNonce` string.
|
|
1462
|
-
* @returns `SPDHandshakeResult` containing the session passphrase and
|
|
1463
|
-
* CMT-4 key commitment. Call `.destroy()` after handing the
|
|
1464
|
-
* passphrase to `spd.setPassKey()`.
|
|
1465
|
-
* @throws If `derive()` has already been called on this instance.
|
|
1466
|
-
* @throws If the public key is malformed or the low-order point check fails.
|
|
1534
|
+
* @returns `SPDHandshakeInitiator` instance.
|
|
1467
1535
|
*/
|
|
1468
|
-
|
|
1536
|
+
static createInitiator(): Promise<SPDHandshakeInitiator>;
|
|
1469
1537
|
/**
|
|
1470
|
-
*
|
|
1471
|
-
*
|
|
1472
|
-
*
|
|
1538
|
+
* Create the responder side of the handshake from the initiator's hello.
|
|
1539
|
+
*
|
|
1540
|
+
* Generates an ephemeral X25519 keypair, encapsulates against the
|
|
1541
|
+
* initiator's ML-KEM public key, and derives the session key.
|
|
1542
|
+
* Send `responder.hello` to the initiator.
|
|
1543
|
+
*
|
|
1544
|
+
* @param initiatorHello The `hello` object received from the initiator.
|
|
1545
|
+
* @returns `SPDHandshakeResponder` instance.
|
|
1546
|
+
* @throws If any input is malformed or a low-order point is detected.
|
|
1473
1547
|
*/
|
|
1474
|
-
|
|
1548
|
+
static createResponder(initiatorHello: SPDHandshakeHello): Promise<SPDHandshakeResponder>;
|
|
1475
1549
|
}
|
|
1476
1550
|
|
|
1477
|
-
export { ARGON2_MEMORY_HIGH, ARGON2_MEMORY_PARANOID, ARGON2_TIME_HIGH, ARGON2_TIME_PARANOID, type DataInput, type EncryptedDataEntry, type EncryptedSaltResult, type HashAlgorithm, type PBKResult, type PQCKey, type PQCKeyResult, SPD, type SPDBenchmarkResult, type SPDChunkManifest, type SPDClientConnectOptions, type SPDClientHandshake, type SPDDiffResult, type SPDGetEntryResult, SPDHandshake, SPDHandshakeResult, type SPDIndexEntry, type SPDInspectResult, type SPDKeyProfile, type SPDKeyProvider, SPDLegacy, type SPDLegacyPayload, type SPDLogEvent, type SPDMergeOptions, type SPDPayload, type SPDRepairResult, type SPDServerIdentity, type SPDSession, SPDShamir, type SPDShamirShare, type SPDSigningKeyPair, type SPDSnapshot, SPDTransport, SPDVault, type SPDVerifyResult, SPDWriter, type SPDWriterOptions, SPDLegacy as SPD_LEG, SPDVault as SPD_Vault, type SerializedDataEntry, type SerializedWrappedPayload, type SupportedDataType, type SupportedValue, type TypedArray, type WrappedPayload };
|
|
1551
|
+
export { ARGON2_MEMORY_HIGH, ARGON2_MEMORY_PARANOID, ARGON2_TIME_HIGH, ARGON2_TIME_PARANOID, type DataInput, type EncryptedDataEntry, type EncryptedSaltResult, type HashAlgorithm, type PBKResult, type PQCKey, type PQCKeyResult, SPD, type SPDBenchmarkResult, type SPDChunkManifest, type SPDClientConnectOptions, type SPDClientHandshake, type SPDDiffResult, type SPDGetEntryResult, SPDHandshake, type SPDHandshakeHello, SPDHandshakeInitiator, SPDHandshakeResponder, SPDHandshakeResult, type SPDIndexEntry, type SPDInspectResult, type SPDKeyProfile, type SPDKeyProvider, SPDLegacy, type SPDLegacyPayload, type SPDLogEvent, type SPDMergeOptions, type SPDPayload, type SPDRepairResult, type SPDServerIdentity, type SPDSession, SPDShamir, type SPDShamirShare, type SPDSigningKeyPair, type SPDSnapshot, SPDTransport, SPDVault, type SPDVerifyResult, SPDWriter, type SPDWriterOptions, SPDLegacy as SPD_LEG, SPDVault as SPD_Vault, type SerializedDataEntry, type SerializedWrappedPayload, type SupportedDataType, type SupportedValue, type TypedArray, type WrappedPayload };
|
package/index.d.ts
CHANGED
|
@@ -1367,111 +1367,185 @@ declare class SPDShamir {
|
|
|
1367
1367
|
}
|
|
1368
1368
|
|
|
1369
1369
|
/**
|
|
1370
|
-
* SPDHandshake —
|
|
1370
|
+
* SPDHandshake — Hybrid post-quantum ephemeral key agreement for SPD sessions.
|
|
1371
1371
|
*
|
|
1372
|
-
*
|
|
1373
|
-
*
|
|
1374
|
-
*
|
|
1375
|
-
*
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
1378
|
-
*
|
|
1379
|
-
*
|
|
1380
|
-
*
|
|
1381
|
-
*
|
|
1372
|
+
* ## Cryptographic design
|
|
1373
|
+
*
|
|
1374
|
+
* Uses a **X25519 + ML-KEM-768 hybrid** construction:
|
|
1375
|
+
*
|
|
1376
|
+
* x25519_ss = X25519(myPriv, theirPub) — classical ECDH
|
|
1377
|
+
* mlkem_ss = ML-KEM-768 encap/decap — post-quantum KEM (NIST FIPS 203)
|
|
1378
|
+
* transcript = SHA3-512(loNonce ∥ hiNonce) — session-binding salt
|
|
1379
|
+
* sessionKey = HKDF-SHA-512(
|
|
1380
|
+
* IKM = x25519_ss ∥ mlkem_ss,
|
|
1381
|
+
* salt = transcript,
|
|
1382
|
+
* info = 'spd-hs-session-v1'
|
|
1383
|
+
* )
|
|
1384
|
+
*
|
|
1385
|
+
* Breaking the session key requires breaking **both** X25519 (hard classically)
|
|
1386
|
+
* **and** ML-KEM-768 (hard for quantum computers) simultaneously.
|
|
1387
|
+
*
|
|
1388
|
+
* ## Security properties
|
|
1389
|
+
*
|
|
1390
|
+
* | Property | Mechanism |
|
|
1391
|
+
* |---------------------------------|--------------------------------------------------------|
|
|
1392
|
+
* | Classical hardness | X25519 ECDH — ~2^128 classical operations |
|
|
1393
|
+
* | Quantum hardness | ML-KEM-768 — NIST FIPS 203, ~2^178 quantum ops |
|
|
1394
|
+
* | Perfect forward secrecy | All keypairs ephemeral, zeroed after derive() |
|
|
1395
|
+
* | Memory safety | Private keys XOR-blinded immediately after creation |
|
|
1396
|
+
* | Key commitment (CMT-4) | SHA3-256(sessionKey ∥ transcript) — verify before use |
|
|
1397
|
+
* | Cross-session binding | 32-byte CSPRNG nonce per session mixed into HKDF |
|
|
1398
|
+
* | Domain separation | Distinct HKDF info strings per key purpose |
|
|
1399
|
+
* | Timing safety | timingSafeEqual for all sensitive comparisons |
|
|
1400
|
+
* | Low-order point rejection | All-zero DH output rejected before HKDF |
|
|
1401
|
+
* | Input validation | Type + length checked on all inputs |
|
|
1402
|
+
* | Zero-on-free | All key material zeroed explicitly via sodium.memzero |
|
|
1403
|
+
*
|
|
1404
|
+
* ## Handshake flow
|
|
1405
|
+
*
|
|
1406
|
+
* The initiator (e.g. client) drives ML-KEM encapsulation:
|
|
1407
|
+
*
|
|
1408
|
+
* ```
|
|
1409
|
+
* INITIATOR RESPONDER
|
|
1410
|
+
* ─────────────────────────────────────────────────────
|
|
1411
|
+
* hs = SPDHandshake.createInitiator()
|
|
1412
|
+
* send → { x25519Pub, kemPub, nonce }
|
|
1413
|
+
* hs = await SPDHandshake.createResponder(
|
|
1414
|
+
* initiatorHello)
|
|
1415
|
+
* send → { x25519Pub, kemCt, nonce }
|
|
1416
|
+
* result = await hs.finalizeInitiator(
|
|
1417
|
+
* responderHello)
|
|
1418
|
+
* result = hs.responderResult()
|
|
1419
|
+
* // result.commitment === responderResult.commitment
|
|
1420
|
+
* // exchange commitments to confirm matching keys
|
|
1421
|
+
* ```
|
|
1382
1422
|
*
|
|
1383
1423
|
* ## Usage
|
|
1384
1424
|
*
|
|
1385
1425
|
* ```ts
|
|
1386
|
-
*
|
|
1387
|
-
* const server = SPDHandshake.create();
|
|
1388
|
-
* // send to client: { publicKey: server.publicKey, nonce: server.sessionNonce }
|
|
1426
|
+
* import { SPDHandshake, SPD } from 'spd-lib';
|
|
1389
1427
|
*
|
|
1390
|
-
* // ──
|
|
1391
|
-
* const
|
|
1392
|
-
* //
|
|
1393
|
-
* const clientResult = client.derive(server.publicKey, server.sessionNonce);
|
|
1428
|
+
* // ── Initiator (client) ───────────────────────────────────────────────────────
|
|
1429
|
+
* const init = await SPDHandshake.createInitiator();
|
|
1430
|
+
* socket.send(JSON.stringify(init.hello)); // { x25519Pub, kemPub, nonce }
|
|
1394
1431
|
*
|
|
1395
|
-
*
|
|
1396
|
-
* const
|
|
1432
|
+
* const respHello = JSON.parse(await socket.recv());
|
|
1433
|
+
* const initResult = await init.finalizeInitiator(respHello);
|
|
1397
1434
|
*
|
|
1398
|
-
* //
|
|
1399
|
-
*
|
|
1435
|
+
* // ── Responder (server) ───────────────────────────────────────────────────────
|
|
1436
|
+
* const resp = await SPDHandshake.createResponder(initHello);
|
|
1437
|
+
* socket.send(JSON.stringify(resp.hello)); // { x25519Pub, kemCt, nonce }
|
|
1438
|
+
* const respResult = resp.responderResult();
|
|
1400
1439
|
*
|
|
1401
|
-
* //
|
|
1402
|
-
*
|
|
1403
|
-
*
|
|
1404
|
-
* await spd.setPassKey(serverResult.sessionKey);
|
|
1440
|
+
* // ── Both sides: verify commitment matches before using key ───────────────────
|
|
1441
|
+
* // exchange initResult.commitment <→ respResult.commitment over the wire
|
|
1442
|
+
* // if they match, both sides have the same session key
|
|
1405
1443
|
*
|
|
1406
|
-
*
|
|
1407
|
-
*
|
|
1444
|
+
* const spd = new SPD();
|
|
1445
|
+
* spd.setKeyProfile('standard'); // session key is already 256-bit entropy
|
|
1446
|
+
* await spd.setPassKey(initResult.sessionKey);
|
|
1447
|
+
* initResult.destroy(); // zero raw key bytes from memory
|
|
1408
1448
|
* ```
|
|
1409
1449
|
*/
|
|
1450
|
+
/** Message sent during the handshake exchange. */
|
|
1451
|
+
interface SPDHandshakeHello {
|
|
1452
|
+
/** Base64url-encoded X25519 public key (32 bytes). */
|
|
1453
|
+
x25519Pub: string;
|
|
1454
|
+
/**
|
|
1455
|
+
* Initiator hello: base64url-encoded ML-KEM-768 public key (1184 bytes).
|
|
1456
|
+
* Responder hello: base64url-encoded ML-KEM-768 ciphertext (1088 bytes).
|
|
1457
|
+
*/
|
|
1458
|
+
kemData: string;
|
|
1459
|
+
/** Base64url-encoded random session nonce (32 bytes). */
|
|
1460
|
+
nonce: string;
|
|
1461
|
+
}
|
|
1410
1462
|
/**
|
|
1411
|
-
*
|
|
1412
|
-
*
|
|
1413
|
-
* Call `destroy()` once the passphrase has been handed to SPD's `setPassKey`.
|
|
1463
|
+
* Completed handshake result.
|
|
1464
|
+
* Call `destroy()` immediately after passing `sessionKey` to `spd.setPassKey()`.
|
|
1414
1465
|
*/
|
|
1415
1466
|
declare class SPDHandshakeResult {
|
|
1416
|
-
/**
|
|
1467
|
+
/**
|
|
1468
|
+
* 64-character hex session passphrase (256 bits of entropy).
|
|
1469
|
+
* Pass directly to `spd.setPassKey()`.
|
|
1470
|
+
*/
|
|
1417
1471
|
readonly sessionKey: string;
|
|
1418
1472
|
/**
|
|
1419
|
-
* CMT-4 key commitment: SHA3-256(sessionKeyBytes ∥
|
|
1420
|
-
* Base64url-encoded
|
|
1421
|
-
*
|
|
1473
|
+
* CMT-4 key commitment: SHA3-256(sessionKeyBytes ∥ transcriptHash).
|
|
1474
|
+
* Base64url-encoded (32 bytes).
|
|
1475
|
+
*
|
|
1476
|
+
* Exchange this with the other party and verify they match BEFORE using
|
|
1477
|
+
* `sessionKey`. If they differ, abort — a MITM substituted a key.
|
|
1422
1478
|
*/
|
|
1423
1479
|
readonly commitment: string;
|
|
1424
1480
|
private _raw;
|
|
1425
1481
|
/** @internal */
|
|
1426
|
-
constructor(raw: Buffer,
|
|
1427
|
-
/**
|
|
1482
|
+
constructor(raw: Buffer, transcript: Buffer);
|
|
1483
|
+
/**
|
|
1484
|
+
* Zero the raw session key bytes from memory.
|
|
1485
|
+
* The `sessionKey` hex string may still exist in the JS heap
|
|
1486
|
+
* (strings are immutable in V8); call this as soon as `setPassKey()` is done.
|
|
1487
|
+
*/
|
|
1428
1488
|
destroy(): void;
|
|
1429
1489
|
}
|
|
1430
|
-
/**
|
|
1431
|
-
declare class
|
|
1490
|
+
/** Initiator state returned by `SPDHandshake.createInitiator()`. */
|
|
1491
|
+
declare class SPDHandshakeInitiator {
|
|
1492
|
+
/** Send this to the responder. */
|
|
1493
|
+
readonly hello: SPDHandshakeHello;
|
|
1494
|
+
private _x25519Priv;
|
|
1495
|
+
private _kemSecretMask;
|
|
1496
|
+
private _blindedKemSK;
|
|
1497
|
+
private _nonceRaw;
|
|
1498
|
+
private _done;
|
|
1499
|
+
/** @internal */
|
|
1500
|
+
constructor(x25519PrivRaw: Buffer, x25519PubRaw: Buffer, kemSecretKey: Uint8Array, kemPublicKey: Uint8Array, nonce: Buffer);
|
|
1432
1501
|
/**
|
|
1433
|
-
*
|
|
1434
|
-
*
|
|
1502
|
+
* Complete the initiator side of the handshake using the responder's hello.
|
|
1503
|
+
*
|
|
1504
|
+
* @param responderHello The `hello` object received from the responder.
|
|
1505
|
+
* @returns `SPDHandshakeResult` — call `.destroy()` after `setPassKey()`.
|
|
1506
|
+
* @throws If already called, or if any input is malformed.
|
|
1435
1507
|
*/
|
|
1436
|
-
|
|
1508
|
+
finalizeInitiator(responderHello: SPDHandshakeHello): Promise<SPDHandshakeResult>;
|
|
1509
|
+
/** Zero all key material. Call if abandoning the handshake. */
|
|
1510
|
+
destroy(): void;
|
|
1511
|
+
}
|
|
1512
|
+
/** Responder state returned by `SPDHandshake.createResponder()`. */
|
|
1513
|
+
declare class SPDHandshakeResponder {
|
|
1514
|
+
/** Send this to the initiator. */
|
|
1515
|
+
readonly hello: SPDHandshakeHello;
|
|
1516
|
+
private _result;
|
|
1517
|
+
/** @internal */
|
|
1518
|
+
constructor(hello: SPDHandshakeHello, result: SPDHandshakeResult);
|
|
1437
1519
|
/**
|
|
1438
|
-
*
|
|
1439
|
-
*
|
|
1440
|
-
*
|
|
1441
|
-
* somehow reused.
|
|
1520
|
+
* Return the completed session result.
|
|
1521
|
+
* The responder derives its key during `createResponder()` — call this
|
|
1522
|
+
* after sending `hello` to the initiator.
|
|
1442
1523
|
*/
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
private _nonceRaw;
|
|
1524
|
+
responderResult(): SPDHandshakeResult;
|
|
1525
|
+
}
|
|
1526
|
+
declare class SPDHandshake {
|
|
1447
1527
|
private constructor();
|
|
1448
1528
|
/**
|
|
1449
|
-
* Create
|
|
1450
|
-
* and a random session nonce.
|
|
1451
|
-
*/
|
|
1452
|
-
static create(): SPDHandshake;
|
|
1453
|
-
/**
|
|
1454
|
-
* Derive the shared session key from the other party's public key and nonce.
|
|
1529
|
+
* Create the initiator side of the handshake.
|
|
1455
1530
|
*
|
|
1456
|
-
*
|
|
1457
|
-
*
|
|
1458
|
-
* match if and only if both sides derived the same key.
|
|
1531
|
+
* Generates an ephemeral X25519 keypair and ML-KEM-768 keypair.
|
|
1532
|
+
* Send `initiator.hello` to the responder.
|
|
1459
1533
|
*
|
|
1460
|
-
* @
|
|
1461
|
-
* @param theirSessionNonce The other party's `sessionNonce` string.
|
|
1462
|
-
* @returns `SPDHandshakeResult` containing the session passphrase and
|
|
1463
|
-
* CMT-4 key commitment. Call `.destroy()` after handing the
|
|
1464
|
-
* passphrase to `spd.setPassKey()`.
|
|
1465
|
-
* @throws If `derive()` has already been called on this instance.
|
|
1466
|
-
* @throws If the public key is malformed or the low-order point check fails.
|
|
1534
|
+
* @returns `SPDHandshakeInitiator` instance.
|
|
1467
1535
|
*/
|
|
1468
|
-
|
|
1536
|
+
static createInitiator(): Promise<SPDHandshakeInitiator>;
|
|
1469
1537
|
/**
|
|
1470
|
-
*
|
|
1471
|
-
*
|
|
1472
|
-
*
|
|
1538
|
+
* Create the responder side of the handshake from the initiator's hello.
|
|
1539
|
+
*
|
|
1540
|
+
* Generates an ephemeral X25519 keypair, encapsulates against the
|
|
1541
|
+
* initiator's ML-KEM public key, and derives the session key.
|
|
1542
|
+
* Send `responder.hello` to the initiator.
|
|
1543
|
+
*
|
|
1544
|
+
* @param initiatorHello The `hello` object received from the initiator.
|
|
1545
|
+
* @returns `SPDHandshakeResponder` instance.
|
|
1546
|
+
* @throws If any input is malformed or a low-order point is detected.
|
|
1473
1547
|
*/
|
|
1474
|
-
|
|
1548
|
+
static createResponder(initiatorHello: SPDHandshakeHello): Promise<SPDHandshakeResponder>;
|
|
1475
1549
|
}
|
|
1476
1550
|
|
|
1477
|
-
export { ARGON2_MEMORY_HIGH, ARGON2_MEMORY_PARANOID, ARGON2_TIME_HIGH, ARGON2_TIME_PARANOID, type DataInput, type EncryptedDataEntry, type EncryptedSaltResult, type HashAlgorithm, type PBKResult, type PQCKey, type PQCKeyResult, SPD, type SPDBenchmarkResult, type SPDChunkManifest, type SPDClientConnectOptions, type SPDClientHandshake, type SPDDiffResult, type SPDGetEntryResult, SPDHandshake, SPDHandshakeResult, type SPDIndexEntry, type SPDInspectResult, type SPDKeyProfile, type SPDKeyProvider, SPDLegacy, type SPDLegacyPayload, type SPDLogEvent, type SPDMergeOptions, type SPDPayload, type SPDRepairResult, type SPDServerIdentity, type SPDSession, SPDShamir, type SPDShamirShare, type SPDSigningKeyPair, type SPDSnapshot, SPDTransport, SPDVault, type SPDVerifyResult, SPDWriter, type SPDWriterOptions, SPDLegacy as SPD_LEG, SPDVault as SPD_Vault, type SerializedDataEntry, type SerializedWrappedPayload, type SupportedDataType, type SupportedValue, type TypedArray, type WrappedPayload };
|
|
1551
|
+
export { ARGON2_MEMORY_HIGH, ARGON2_MEMORY_PARANOID, ARGON2_TIME_HIGH, ARGON2_TIME_PARANOID, type DataInput, type EncryptedDataEntry, type EncryptedSaltResult, type HashAlgorithm, type PBKResult, type PQCKey, type PQCKeyResult, SPD, type SPDBenchmarkResult, type SPDChunkManifest, type SPDClientConnectOptions, type SPDClientHandshake, type SPDDiffResult, type SPDGetEntryResult, SPDHandshake, type SPDHandshakeHello, SPDHandshakeInitiator, SPDHandshakeResponder, SPDHandshakeResult, type SPDIndexEntry, type SPDInspectResult, type SPDKeyProfile, type SPDKeyProvider, SPDLegacy, type SPDLegacyPayload, type SPDLogEvent, type SPDMergeOptions, type SPDPayload, type SPDRepairResult, type SPDServerIdentity, type SPDSession, SPDShamir, type SPDShamirShare, type SPDSigningKeyPair, type SPDSnapshot, SPDTransport, SPDVault, type SPDVerifyResult, SPDWriter, type SPDWriterOptions, SPDLegacy as SPD_LEG, SPDVault as SPD_Vault, type SerializedDataEntry, type SerializedWrappedPayload, type SupportedDataType, type SupportedValue, type TypedArray, type WrappedPayload };
|