@private.me/xbind 1.2.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/AGENTS.md +778 -0
- package/LICENSE.md +27 -0
- package/README.md +400 -0
- package/dist-standalone/_deps/crypto/base64.d.ts +29 -0
- package/dist-standalone/_deps/crypto/base64.js +97 -0
- package/dist-standalone/_deps/crypto/cjs/base64.js +103 -0
- package/dist-standalone/_deps/crypto/cjs/errors.js +119 -0
- package/dist-standalone/_deps/crypto/cjs/hmac.js +71 -0
- package/dist-standalone/_deps/crypto/cjs/index.js +86 -0
- package/dist-standalone/_deps/crypto/cjs/padding.js +57 -0
- package/dist-standalone/_deps/crypto/cjs/share-header.js +68 -0
- package/dist-standalone/_deps/crypto/cjs/shares.js +152 -0
- package/dist-standalone/_deps/crypto/cjs/tlv.js +199 -0
- package/dist-standalone/_deps/crypto/cjs/uuid.js +61 -0
- package/dist-standalone/_deps/crypto/cjs/verify.js +24 -0
- package/dist-standalone/_deps/crypto/cjs/xorida.js +221 -0
- package/dist-standalone/_deps/crypto/errors.d.ts +51 -0
- package/dist-standalone/_deps/crypto/errors.js +109 -0
- package/dist-standalone/_deps/crypto/hmac.d.ts +39 -0
- package/dist-standalone/_deps/crypto/hmac.js +66 -0
- package/dist-standalone/_deps/crypto/index.d.ts +20 -0
- package/dist-standalone/_deps/crypto/index.js +45 -0
- package/dist-standalone/_deps/crypto/padding.d.ts +19 -0
- package/dist-standalone/_deps/crypto/padding.js +53 -0
- package/dist-standalone/_deps/crypto/share-header.d.ts +44 -0
- package/dist-standalone/_deps/crypto/share-header.js +63 -0
- package/dist-standalone/_deps/crypto/shares.d.ts +27 -0
- package/dist-standalone/_deps/crypto/shares.js +148 -0
- package/dist-standalone/_deps/crypto/tlv.d.ts +26 -0
- package/dist-standalone/_deps/crypto/tlv.js +195 -0
- package/dist-standalone/_deps/crypto/uuid.d.ts +22 -0
- package/dist-standalone/_deps/crypto/uuid.js +56 -0
- package/dist-standalone/_deps/crypto/verify.d.ts +15 -0
- package/dist-standalone/_deps/crypto/verify.js +15 -0
- package/dist-standalone/_deps/crypto/xorida.d.ts +44 -0
- package/dist-standalone/_deps/crypto/xorida.js +215 -0
- package/dist-standalone/_deps/mldsa-wasm/LICENSE +24 -0
- package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1920 -0
- package/dist-standalone/_deps/mldsa-wasm/package.json +46 -0
- package/dist-standalone/_deps/mldsa-wasm/types/mldsa.d.ts +30 -0
- package/dist-standalone/_deps/shared/cjs/errors.js +582 -0
- package/dist-standalone/_deps/shared/cjs/index.js +492 -0
- package/dist-standalone/_deps/shared/cjs/package.json +1 -0
- package/dist-standalone/_deps/shared/cjs/types.js +403 -0
- package/dist-standalone/_deps/shared/errors.d.ts +48 -0
- package/dist-standalone/_deps/shared/errors.d.ts.map +1 -0
- package/dist-standalone/_deps/shared/errors.js +192 -0
- package/dist-standalone/_deps/shared/errors.js.map +1 -0
- package/dist-standalone/_deps/shared/index.d.ts +4 -0
- package/dist-standalone/_deps/shared/index.d.ts.map +1 -0
- package/dist-standalone/_deps/shared/index.js +78 -0
- package/dist-standalone/_deps/shared/index.js.map +1 -0
- package/dist-standalone/_deps/shared/types.d.ts +1097 -0
- package/dist-standalone/_deps/shared/types.d.ts.map +1 -0
- package/dist-standalone/_deps/shared/types.js +89 -0
- package/dist-standalone/_deps/shared/types.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/errors.d.ts +115 -0
- package/dist-standalone/_deps/ux-helpers/cjs/errors.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/errors.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/index.d.ts +13 -0
- package/dist-standalone/_deps/ux-helpers/cjs/index.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/index.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/package.json +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/pagination.d.ts +39 -0
- package/dist-standalone/_deps/ux-helpers/cjs/pagination.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +83 -0
- package/dist-standalone/_deps/ux-helpers/cjs/pagination.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/progress.d.ts +99 -0
- package/dist-standalone/_deps/ux-helpers/cjs/progress.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/progress.js +143 -0
- package/dist-standalone/_deps/ux-helpers/cjs/progress.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/search.d.ts +32 -0
- package/dist-standalone/_deps/ux-helpers/cjs/search.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/search.js +119 -0
- package/dist-standalone/_deps/ux-helpers/cjs/search.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/types.d.ts +109 -0
- package/dist-standalone/_deps/ux-helpers/cjs/types.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/cjs/types.js +8 -0
- package/dist-standalone/_deps/ux-helpers/cjs/types.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/errors.d.ts +115 -0
- package/dist-standalone/_deps/ux-helpers/errors.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/errors.js +253 -0
- package/dist-standalone/_deps/ux-helpers/errors.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/index.d.ts +13 -0
- package/dist-standalone/_deps/ux-helpers/index.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/index.js +16 -0
- package/dist-standalone/_deps/ux-helpers/index.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/pagination.d.ts +39 -0
- package/dist-standalone/_deps/ux-helpers/pagination.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/pagination.js +79 -0
- package/dist-standalone/_deps/ux-helpers/pagination.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/progress.d.ts +99 -0
- package/dist-standalone/_deps/ux-helpers/progress.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/progress.js +138 -0
- package/dist-standalone/_deps/ux-helpers/progress.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/search.d.ts +32 -0
- package/dist-standalone/_deps/ux-helpers/search.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/search.js +116 -0
- package/dist-standalone/_deps/ux-helpers/search.js.map +1 -0
- package/dist-standalone/_deps/ux-helpers/types.d.ts +109 -0
- package/dist-standalone/_deps/ux-helpers/types.d.ts.map +1 -0
- package/dist-standalone/_deps/ux-helpers/types.js +7 -0
- package/dist-standalone/_deps/ux-helpers/types.js.map +1 -0
- package/dist-standalone/_deps/xchange/auto-accept.d.ts +127 -0
- package/dist-standalone/_deps/xchange/auto-accept.js +1 -0
- package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -0
- package/dist-standalone/_deps/xchange/cjs/errors.js +1 -0
- package/dist-standalone/_deps/xchange/cjs/index.js +1 -0
- package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -0
- package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -0
- package/dist-standalone/_deps/xchange/cjs/package.json +1 -0
- package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -0
- package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -0
- package/dist-standalone/_deps/xchange/errors.d.ts +69 -0
- package/dist-standalone/_deps/xchange/errors.js +1 -0
- package/dist-standalone/_deps/xchange/index.d.ts +15 -0
- package/dist-standalone/_deps/xchange/index.js +1 -0
- package/dist-standalone/_deps/xchange/invite-client.d.ts +178 -0
- package/dist-standalone/_deps/xchange/invite-client.js +1 -0
- package/dist-standalone/_deps/xchange/lazy-init.d.ts +176 -0
- package/dist-standalone/_deps/xchange/lazy-init.js +1 -0
- package/dist-standalone/_deps/xchange/trust-integration.d.ts +102 -0
- package/dist-standalone/_deps/xchange/trust-integration.js +1 -0
- package/dist-standalone/_deps/xchange/xchange.d.ts +60 -0
- package/dist-standalone/_deps/xchange/xchange.js +1 -0
- package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -0
- package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -0
- package/dist-standalone/_deps/xregistry/cjs/index.js +1 -0
- package/dist-standalone/_deps/xregistry/cjs/package.json +1 -0
- package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -0
- package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -0
- package/dist-standalone/_deps/xregistry/cjs/types.js +1 -0
- package/dist-standalone/_deps/xregistry/discovery.d.ts +126 -0
- package/dist-standalone/_deps/xregistry/discovery.d.ts.map +1 -0
- package/dist-standalone/_deps/xregistry/discovery.js +1 -0
- package/dist-standalone/_deps/xregistry/discovery.js.map +1 -0
- package/dist-standalone/_deps/xregistry/errors.d.ts +41 -0
- package/dist-standalone/_deps/xregistry/errors.d.ts.map +1 -0
- package/dist-standalone/_deps/xregistry/errors.js +1 -0
- package/dist-standalone/_deps/xregistry/errors.js.map +1 -0
- package/dist-standalone/_deps/xregistry/index.d.ts +8 -0
- package/dist-standalone/_deps/xregistry/index.d.ts.map +1 -0
- package/dist-standalone/_deps/xregistry/index.js +1 -0
- package/dist-standalone/_deps/xregistry/index.js.map +1 -0
- package/dist-standalone/_deps/xregistry/registry.d.ts +85 -0
- package/dist-standalone/_deps/xregistry/registry.d.ts.map +1 -0
- package/dist-standalone/_deps/xregistry/registry.js +1 -0
- package/dist-standalone/_deps/xregistry/registry.js.map +1 -0
- package/dist-standalone/_deps/xregistry/schema.d.ts +81 -0
- package/dist-standalone/_deps/xregistry/schema.d.ts.map +1 -0
- package/dist-standalone/_deps/xregistry/schema.js +1 -0
- package/dist-standalone/_deps/xregistry/schema.js.map +1 -0
- package/dist-standalone/_deps/xregistry/types.d.ts +95 -0
- package/dist-standalone/_deps/xregistry/types.d.ts.map +1 -0
- package/dist-standalone/_deps/xregistry/types.js +1 -0
- package/dist-standalone/_deps/xregistry/types.js.map +1 -0
- package/dist-standalone/agent-call.d.ts +286 -0
- package/dist-standalone/agent-call.js +642 -0
- package/dist-standalone/agent-sdk.d.ts +207 -0
- package/dist-standalone/agent-sdk.js +328 -0
- package/dist-standalone/agent.d.ts +670 -0
- package/dist-standalone/agent.js +1529 -0
- package/dist-standalone/approval.d.ts +145 -0
- package/dist-standalone/approval.js +193 -0
- package/dist-standalone/auth.d.ts +75 -0
- package/dist-standalone/auth.js +219 -0
- package/dist-standalone/auto-accept.d.ts +102 -0
- package/dist-standalone/auto-accept.js +229 -0
- package/dist-standalone/backup-config.d.ts +150 -0
- package/dist-standalone/backup-config.js +201 -0
- package/dist-standalone/checkpoint.d.ts +125 -0
- package/dist-standalone/checkpoint.js +186 -0
- package/dist-standalone/cjs/agent-call.js +651 -0
- package/dist-standalone/cjs/agent-sdk.js +332 -0
- package/dist-standalone/cjs/agent.js +1566 -0
- package/dist-standalone/cjs/approval.js +199 -0
- package/dist-standalone/cjs/auth.js +225 -0
- package/dist-standalone/cjs/auto-accept.js +233 -0
- package/dist-standalone/cjs/backup-config.js +207 -0
- package/dist-standalone/cjs/checkpoint.js +193 -0
- package/dist-standalone/cjs/cli/init.js +487 -0
- package/dist-standalone/cjs/connect.js +312 -0
- package/dist-standalone/cjs/did-document.js +101 -0
- package/dist-standalone/cjs/did-privateme.js +130 -0
- package/dist-standalone/cjs/did-web.js +201 -0
- package/dist-standalone/cjs/discovery.js +462 -0
- package/dist-standalone/cjs/dual-mode.js +251 -0
- package/dist-standalone/cjs/email-templates.js +313 -0
- package/dist-standalone/cjs/email-transport.js +239 -0
- package/dist-standalone/cjs/envelope.js +510 -0
- package/dist-standalone/cjs/errors.js +562 -0
- package/dist-standalone/cjs/gateway-state.js +55 -0
- package/dist-standalone/cjs/gateway-transport.js +120 -0
- package/dist-standalone/cjs/guardrails.js +223 -0
- package/dist-standalone/cjs/http-compat.js +272 -0
- package/dist-standalone/cjs/identity.js +541 -0
- package/dist-standalone/cjs/index.js +224 -0
- package/dist-standalone/cjs/invitation.js +421 -0
- package/dist-standalone/cjs/invite.js +328 -0
- package/dist-standalone/cjs/key-agreement.js +246 -0
- package/dist-standalone/cjs/lazy-init.js +300 -0
- package/dist-standalone/cjs/mdns-discovery.js +202 -0
- package/dist-standalone/cjs/nonce-store.js +66 -0
- package/dist-standalone/cjs/package.json +3 -0
- package/dist-standalone/cjs/pairing-manager.js +223 -0
- package/dist-standalone/cjs/policy.js +320 -0
- package/dist-standalone/cjs/redis-nonce-store.js +76 -0
- package/dist-standalone/cjs/registry-middleware.js +50 -0
- package/dist-standalone/cjs/retry-transport.js +102 -0
- package/dist-standalone/cjs/security-policy.js +204 -0
- package/dist-standalone/cjs/split-channel.js +177 -0
- package/dist-standalone/cjs/subscription-proof.js +230 -0
- package/dist-standalone/cjs/succession.js +148 -0
- package/dist-standalone/cjs/transport.js +63 -0
- package/dist-standalone/cjs/trust-registry.js +742 -0
- package/dist-standalone/cjs/verify.js +25 -0
- package/dist-standalone/cjs/xfetch.js +252 -0
- package/dist-standalone/cli/init.d.ts +63 -0
- package/dist-standalone/cli/init.js +450 -0
- package/dist-standalone/connect.d.ts +143 -0
- package/dist-standalone/connect.js +274 -0
- package/dist-standalone/did-document.d.ts +65 -0
- package/dist-standalone/did-document.js +96 -0
- package/dist-standalone/did-privateme.d.ts +70 -0
- package/dist-standalone/did-privateme.js +121 -0
- package/dist-standalone/did-web.d.ts +73 -0
- package/dist-standalone/did-web.js +196 -0
- package/dist-standalone/discovery.d.ts +176 -0
- package/dist-standalone/discovery.js +458 -0
- package/dist-standalone/dual-mode.d.ts +145 -0
- package/dist-standalone/dual-mode.js +247 -0
- package/dist-standalone/email-templates.d.ts +41 -0
- package/dist-standalone/email-templates.js +309 -0
- package/dist-standalone/email-transport.d.ts +139 -0
- package/dist-standalone/email-transport.js +232 -0
- package/dist-standalone/envelope.d.ts +288 -0
- package/dist-standalone/envelope.js +497 -0
- package/dist-standalone/errors.d.ts +74 -0
- package/dist-standalone/errors.js +548 -0
- package/dist-standalone/gateway-state.d.ts +32 -0
- package/dist-standalone/gateway-state.js +51 -0
- package/dist-standalone/gateway-transport.d.ts +59 -0
- package/dist-standalone/gateway-transport.js +116 -0
- package/dist-standalone/guardrails.d.ts +136 -0
- package/dist-standalone/guardrails.js +216 -0
- package/dist-standalone/http-compat.d.ts +150 -0
- package/dist-standalone/http-compat.js +267 -0
- package/dist-standalone/identity.d.ts +176 -0
- package/dist-standalone/identity.js +516 -0
- package/dist-standalone/index.d.ts +83 -0
- package/dist-standalone/index.js +51 -0
- package/dist-standalone/invitation.d.ts +211 -0
- package/dist-standalone/invitation.js +415 -0
- package/dist-standalone/invite.d.ts +192 -0
- package/dist-standalone/invite.js +324 -0
- package/dist-standalone/key-agreement.d.ts +122 -0
- package/dist-standalone/key-agreement.js +236 -0
- package/dist-standalone/lazy-init.d.ts +167 -0
- package/dist-standalone/lazy-init.js +295 -0
- package/dist-standalone/mdns-discovery.d.ts +117 -0
- package/dist-standalone/mdns-discovery.js +195 -0
- package/dist-standalone/nonce-store.d.ts +39 -0
- package/dist-standalone/nonce-store.js +62 -0
- package/dist-standalone/package.json +11 -0
- package/dist-standalone/pairing-manager.d.ts +147 -0
- package/dist-standalone/pairing-manager.js +219 -0
- package/dist-standalone/policy.d.ts +150 -0
- package/dist-standalone/policy.js +315 -0
- package/dist-standalone/redis-nonce-store.d.ts +93 -0
- package/dist-standalone/redis-nonce-store.js +72 -0
- package/dist-standalone/registry-middleware.d.ts +38 -0
- package/dist-standalone/registry-middleware.js +47 -0
- package/dist-standalone/retry-transport.d.ts +76 -0
- package/dist-standalone/retry-transport.js +98 -0
- package/dist-standalone/security-policy.d.ts +146 -0
- package/dist-standalone/security-policy.js +198 -0
- package/dist-standalone/split-channel.d.ts +69 -0
- package/dist-standalone/split-channel.js +171 -0
- package/dist-standalone/subscription-proof.d.ts +103 -0
- package/dist-standalone/subscription-proof.js +224 -0
- package/dist-standalone/succession.d.ts +57 -0
- package/dist-standalone/succession.js +142 -0
- package/dist-standalone/transport.d.ts +50 -0
- package/dist-standalone/transport.js +59 -0
- package/dist-standalone/trust-registry.d.ts +286 -0
- package/dist-standalone/trust-registry.js +702 -0
- package/dist-standalone/verify.d.ts +16 -0
- package/dist-standalone/verify.js +16 -0
- package/dist-standalone/xfetch.d.ts +129 -0
- package/dist-standalone/xfetch.js +247 -0
- package/llms.txt +800 -0
- package/package.json +79 -0
- package/share1.dat +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HMAC-SHA256 integrity verification using Web Crypto API.
|
|
3
|
+
*
|
|
4
|
+
* Provides message-level integrity for the XorIDA pipeline.
|
|
5
|
+
* The HMAC is computed over the padded payload (after TLV serialization + PKCS#7 padding)
|
|
6
|
+
* and verified after reconstruction, before unpadding.
|
|
7
|
+
*
|
|
8
|
+
* Uses crypto.subtle for constant-time verification (no manual byte comparison).
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Generate a fresh random HMAC key and sign data with HMAC-SHA256.
|
|
12
|
+
*
|
|
13
|
+
* @param data - Bytes to sign (the padded payload)
|
|
14
|
+
* @returns Object containing the raw key bytes and the 32-byte signature
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateHMAC(data: Uint8Array): Promise<{
|
|
17
|
+
key: Uint8Array;
|
|
18
|
+
signature: Uint8Array;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Verify an HMAC-SHA256 signature using constant-time comparison.
|
|
22
|
+
*
|
|
23
|
+
* Uses crypto.subtle.verify() which is constant-time by specification.
|
|
24
|
+
* NEVER manually compare HMAC bytes (timing attack risk).
|
|
25
|
+
*
|
|
26
|
+
* @param key - Raw HMAC key bytes (32 bytes)
|
|
27
|
+
* @param data - Data that was signed
|
|
28
|
+
* @param signature - Expected HMAC-SHA256 signature (32 bytes)
|
|
29
|
+
* @returns true if signature is valid, false otherwise
|
|
30
|
+
*/
|
|
31
|
+
export declare function verifyHMAC(key: Uint8Array, data: Uint8Array, signature: Uint8Array): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* Sign data with a provided HMAC key (for cases where the key is already known).
|
|
34
|
+
*
|
|
35
|
+
* @param key - Raw HMAC key bytes (32 bytes)
|
|
36
|
+
* @param data - Bytes to sign
|
|
37
|
+
* @returns 32-byte HMAC-SHA256 signature
|
|
38
|
+
*/
|
|
39
|
+
export declare function signHMAC(key: Uint8Array, data: Uint8Array): Promise<Uint8Array>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HMAC-SHA256 integrity verification using Web Crypto API.
|
|
3
|
+
*
|
|
4
|
+
* Provides message-level integrity for the XorIDA pipeline.
|
|
5
|
+
* The HMAC is computed over the padded payload (after TLV serialization + PKCS#7 padding)
|
|
6
|
+
* and verified after reconstruction, before unpadding.
|
|
7
|
+
*
|
|
8
|
+
* Uses crypto.subtle for constant-time verification (no manual byte comparison).
|
|
9
|
+
*/
|
|
10
|
+
/** HMAC key length in bytes. */
|
|
11
|
+
const HMAC_KEY_LENGTH = 32;
|
|
12
|
+
/** HMAC algorithm config. */
|
|
13
|
+
const HMAC_ALGO = { name: 'HMAC', hash: 'SHA-256' };
|
|
14
|
+
/** Copy a Uint8Array into a fresh ArrayBuffer (avoids SharedArrayBuffer type issues). */
|
|
15
|
+
function toArrayBuffer(data) {
|
|
16
|
+
const buf = new ArrayBuffer(data.byteLength);
|
|
17
|
+
new Uint8Array(buf).set(data);
|
|
18
|
+
return buf;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Import a raw key buffer for HMAC operations.
|
|
22
|
+
* Copies to a fresh ArrayBuffer to satisfy Web Crypto API typing.
|
|
23
|
+
*/
|
|
24
|
+
async function importKey(keyBytes, usage) {
|
|
25
|
+
return crypto.subtle.importKey('raw', toArrayBuffer(keyBytes), HMAC_ALGO, false, [usage]);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Generate a fresh random HMAC key and sign data with HMAC-SHA256.
|
|
29
|
+
*
|
|
30
|
+
* @param data - Bytes to sign (the padded payload)
|
|
31
|
+
* @returns Object containing the raw key bytes and the 32-byte signature
|
|
32
|
+
*/
|
|
33
|
+
export async function generateHMAC(data) {
|
|
34
|
+
const keyBytes = new Uint8Array(HMAC_KEY_LENGTH);
|
|
35
|
+
crypto.getRandomValues(keyBytes);
|
|
36
|
+
const cryptoKey = await importKey(keyBytes, 'sign');
|
|
37
|
+
const sig = await crypto.subtle.sign('HMAC', cryptoKey, toArrayBuffer(data));
|
|
38
|
+
return { key: keyBytes, signature: new Uint8Array(sig) };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Verify an HMAC-SHA256 signature using constant-time comparison.
|
|
42
|
+
*
|
|
43
|
+
* Uses crypto.subtle.verify() which is constant-time by specification.
|
|
44
|
+
* NEVER manually compare HMAC bytes (timing attack risk).
|
|
45
|
+
*
|
|
46
|
+
* @param key - Raw HMAC key bytes (32 bytes)
|
|
47
|
+
* @param data - Data that was signed
|
|
48
|
+
* @param signature - Expected HMAC-SHA256 signature (32 bytes)
|
|
49
|
+
* @returns true if signature is valid, false otherwise
|
|
50
|
+
*/
|
|
51
|
+
export async function verifyHMAC(key, data, signature) {
|
|
52
|
+
const cryptoKey = await importKey(key, 'verify');
|
|
53
|
+
return crypto.subtle.verify('HMAC', cryptoKey, toArrayBuffer(signature), toArrayBuffer(data));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Sign data with a provided HMAC key (for cases where the key is already known).
|
|
57
|
+
*
|
|
58
|
+
* @param key - Raw HMAC key bytes (32 bytes)
|
|
59
|
+
* @param data - Bytes to sign
|
|
60
|
+
* @returns 32-byte HMAC-SHA256 signature
|
|
61
|
+
*/
|
|
62
|
+
export async function signHMAC(key, data) {
|
|
63
|
+
const cryptoKey = await importKey(key, 'sign');
|
|
64
|
+
const sig = await crypto.subtle.sign('HMAC', cryptoKey, toArrayBuffer(data));
|
|
65
|
+
return new Uint8Array(sig);
|
|
66
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export * from './errors.js';
|
|
2
|
+
export { splitXorIDA, reconstructXorIDA, nextOddPrime } from './xorida.js';
|
|
3
|
+
export { pkcs7Pad, pkcs7Unpad } from './padding.js';
|
|
4
|
+
export { generateHMAC, verifyHMAC, signHMAC } from './hmac.js';
|
|
5
|
+
export { serializeMessage, deserializeMessage } from './tlv.js';
|
|
6
|
+
export { generateUUID, uuidToBytes, bytesToUuid } from './uuid.js';
|
|
7
|
+
export { toBase64, fromBase64, toBase64Url, fromBase64Url } from './base64.js';
|
|
8
|
+
export { createShares, reconstructMessage } from './shares.js';
|
|
9
|
+
export { formatShareHeader, parseShareHeader, hasShareHeader } from './share-header.js';
|
|
10
|
+
/**
|
|
11
|
+
* Check if the runtime supports the required Web Crypto APIs.
|
|
12
|
+
*
|
|
13
|
+
* Verifies that `crypto.subtle` is available with HMAC, AES-GCM,
|
|
14
|
+
* and `crypto.getRandomValues`. Call this before using any crypto
|
|
15
|
+
* operations to provide a clear error message on unsupported runtimes.
|
|
16
|
+
*
|
|
17
|
+
* @returns `true` if the runtime has the required Web Crypto APIs.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isSupported(): boolean;
|
|
20
|
+
export { splitWithRandom } from './xorida.js';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// @private.me/crypto — public API
|
|
2
|
+
// Errors
|
|
3
|
+
export * from './errors.js';
|
|
4
|
+
// XorIDA Threshold Sharing
|
|
5
|
+
export { splitXorIDA, reconstructXorIDA, nextOddPrime } from './xorida.js';
|
|
6
|
+
// Padding
|
|
7
|
+
export { pkcs7Pad, pkcs7Unpad } from './padding.js';
|
|
8
|
+
// Integrity
|
|
9
|
+
export { generateHMAC, verifyHMAC, signHMAC } from './hmac.js';
|
|
10
|
+
// Serialization
|
|
11
|
+
export { serializeMessage, deserializeMessage } from './tlv.js';
|
|
12
|
+
// UUID
|
|
13
|
+
export { generateUUID, uuidToBytes, bytesToUuid } from './uuid.js';
|
|
14
|
+
// Base64
|
|
15
|
+
export { toBase64, fromBase64, toBase64Url, fromBase64Url } from './base64.js';
|
|
16
|
+
// High-level API
|
|
17
|
+
export { createShares, reconstructMessage } from './shares.js';
|
|
18
|
+
// Branded Share Header (IDA5 copyright layer)
|
|
19
|
+
export { formatShareHeader, parseShareHeader, hasShareHeader } from './share-header.js';
|
|
20
|
+
// Capability check
|
|
21
|
+
/**
|
|
22
|
+
* Check if the runtime supports the required Web Crypto APIs.
|
|
23
|
+
*
|
|
24
|
+
* Verifies that `crypto.subtle` is available with HMAC, AES-GCM,
|
|
25
|
+
* and `crypto.getRandomValues`. Call this before using any crypto
|
|
26
|
+
* operations to provide a clear error message on unsupported runtimes.
|
|
27
|
+
*
|
|
28
|
+
* @returns `true` if the runtime has the required Web Crypto APIs.
|
|
29
|
+
*/
|
|
30
|
+
export function isSupported() {
|
|
31
|
+
try {
|
|
32
|
+
return (typeof globalThis.crypto !== 'undefined' &&
|
|
33
|
+
typeof globalThis.crypto.subtle !== 'undefined' &&
|
|
34
|
+
typeof globalThis.crypto.subtle.importKey === 'function' &&
|
|
35
|
+
typeof globalThis.crypto.subtle.sign === 'function' &&
|
|
36
|
+
typeof globalThis.crypto.subtle.verify === 'function' &&
|
|
37
|
+
typeof globalThis.crypto.subtle.encrypt === 'function' &&
|
|
38
|
+
typeof globalThis.crypto.getRandomValues === 'function');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Re-export for testing (internal, not part of public API contract)
|
|
45
|
+
export { splitWithRandom } from './xorida.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Result, PaddingError } from '@private.me/shared';
|
|
2
|
+
/**
|
|
3
|
+
* PKCS#7 pad data to a multiple of blockSize bytes.
|
|
4
|
+
* Always adds at least 1 byte of padding, even when already aligned.
|
|
5
|
+
*
|
|
6
|
+
* @param data - Input bytes to pad
|
|
7
|
+
* @param blockSize - Block size in bytes (must be 1–255)
|
|
8
|
+
* @returns Padded byte array
|
|
9
|
+
*/
|
|
10
|
+
export declare function pkcs7Pad(data: Uint8Array, blockSize: number): Uint8Array;
|
|
11
|
+
/**
|
|
12
|
+
* Remove PKCS#7 padding. Validates that padding bytes are consistent.
|
|
13
|
+
* Returns an error if padding is invalid (possible tampering).
|
|
14
|
+
*
|
|
15
|
+
* @param data - Padded byte array
|
|
16
|
+
* @param blockSize - Block size used during padding (must be 1–255)
|
|
17
|
+
* @returns Unpadded bytes, or PaddingError if invalid
|
|
18
|
+
*/
|
|
19
|
+
export declare function pkcs7Unpad(data: Uint8Array, blockSize: number): Result<Uint8Array, PaddingError>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ok, err } from"../shared/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* PKCS#7 pad data to a multiple of blockSize bytes.
|
|
4
|
+
* Always adds at least 1 byte of padding, even when already aligned.
|
|
5
|
+
*
|
|
6
|
+
* @param data - Input bytes to pad
|
|
7
|
+
* @param blockSize - Block size in bytes (must be 1–255)
|
|
8
|
+
* @returns Padded byte array
|
|
9
|
+
*/
|
|
10
|
+
export function pkcs7Pad(data, blockSize) {
|
|
11
|
+
const padLen = blockSize - (data.length % blockSize);
|
|
12
|
+
const padded = new Uint8Array(data.length + padLen);
|
|
13
|
+
padded.set(data);
|
|
14
|
+
for (let i = data.length; i < padded.length; i++) {
|
|
15
|
+
padded[i] = padLen;
|
|
16
|
+
}
|
|
17
|
+
return padded;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Remove PKCS#7 padding. Validates that padding bytes are consistent.
|
|
21
|
+
* Returns an error if padding is invalid (possible tampering).
|
|
22
|
+
*
|
|
23
|
+
* @param data - Padded byte array
|
|
24
|
+
* @param blockSize - Block size used during padding (must be 1–255)
|
|
25
|
+
* @returns Unpadded bytes, or PaddingError if invalid
|
|
26
|
+
*/
|
|
27
|
+
export function pkcs7Unpad(data, blockSize) {
|
|
28
|
+
if (data.length === 0) {
|
|
29
|
+
return err({ code: 'INVALID_PADDING', message: 'Input is empty' });
|
|
30
|
+
}
|
|
31
|
+
if (data.length % blockSize !== 0) {
|
|
32
|
+
return err({
|
|
33
|
+
code: 'INVALID_PADDING',
|
|
34
|
+
message: 'Input length is not a multiple of block size',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const padLen = data[data.length - 1];
|
|
38
|
+
if (padLen === undefined || padLen < 1 || padLen > blockSize) {
|
|
39
|
+
return err({
|
|
40
|
+
code: 'INVALID_PADDING',
|
|
41
|
+
message: `Invalid padding value: ${padLen}`,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
for (let i = data.length - padLen; i < data.length; i++) {
|
|
45
|
+
if (data[i] !== padLen) {
|
|
46
|
+
return err({
|
|
47
|
+
code: 'INVALID_PADDING',
|
|
48
|
+
message: 'Inconsistent padding bytes',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return ok(data.slice(0, data.length - padLen));
|
|
53
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branded share header — IDA5 copyright layer.
|
|
3
|
+
*
|
|
4
|
+
* Wraps every XorIDA share output with the patent-locked branded string:
|
|
5
|
+
*
|
|
6
|
+
* Xecret (TM) -> PRIVATE .ME (R) -> IDA5 -> Encrypted:// [data] => Generated by Xecret (TM)
|
|
7
|
+
*
|
|
8
|
+
* This provides triple legal protection on every share artifact:
|
|
9
|
+
* - Patent (20 years): XorIDA algorithm and split-channel architecture
|
|
10
|
+
* - Copyright (95 years): the literal branded header expression
|
|
11
|
+
* - Trademark (indefinite): Xecret(TM) and PRIVATE .ME(R) marks
|
|
12
|
+
*
|
|
13
|
+
* NEVER modify the header format. It is patent-locked.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Wrap share data with the branded IDA5 copyright header.
|
|
17
|
+
*
|
|
18
|
+
* Output format (patent-locked, NEVER change):
|
|
19
|
+
* Xecret (TM) -> PRIVATE .ME (R) -> IDA5 -> Encrypted:// [data] => Generated by Xecret (TM)
|
|
20
|
+
*
|
|
21
|
+
* @param data - Base64-encoded share data (or any string payload)
|
|
22
|
+
* @returns Branded string with copyright header wrapping the data
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatShareHeader(data: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Extract share data from a branded IDA5 header string.
|
|
27
|
+
*
|
|
28
|
+
* Backward-compatible: if the branded markers are not found, returns
|
|
29
|
+
* the input string trimmed (handles legacy headerless shares).
|
|
30
|
+
*
|
|
31
|
+
* @param input - Branded share string or legacy raw data
|
|
32
|
+
* @returns Extracted share data with whitespace trimmed
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseShareHeader(input: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Check whether a string contains the branded IDA5 share header.
|
|
37
|
+
*
|
|
38
|
+
* Useful for format detection — distinguishing branded shares from
|
|
39
|
+
* legacy raw base64 shares.
|
|
40
|
+
*
|
|
41
|
+
* @param input - String to check
|
|
42
|
+
* @returns true if the branded markers are present
|
|
43
|
+
*/
|
|
44
|
+
export declare function hasShareHeader(input: string): boolean;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branded share header — IDA5 copyright layer.
|
|
3
|
+
*
|
|
4
|
+
* Wraps every XorIDA share output with the patent-locked branded string:
|
|
5
|
+
*
|
|
6
|
+
* Xecret (TM) -> PRIVATE .ME (R) -> IDA5 -> Encrypted:// [data] => Generated by Xecret (TM)
|
|
7
|
+
*
|
|
8
|
+
* This provides triple legal protection on every share artifact:
|
|
9
|
+
* - Patent (20 years): XorIDA algorithm and split-channel architecture
|
|
10
|
+
* - Copyright (95 years): the literal branded header expression
|
|
11
|
+
* - Trademark (indefinite): Xecret(TM) and PRIVATE .ME(R) marks
|
|
12
|
+
*
|
|
13
|
+
* NEVER modify the header format. It is patent-locked.
|
|
14
|
+
*/
|
|
15
|
+
/** Start marker for the branded share data region. */
|
|
16
|
+
const START_MARKER = 'Encrypted://';
|
|
17
|
+
/** End marker for the branded share data region. */
|
|
18
|
+
const END_MARKER = '=> Generated by Xecret (TM)';
|
|
19
|
+
/** Branded prefix before the start marker. */
|
|
20
|
+
const BRAND_PREFIX = 'Xecret (TM) -> PRIVATE .ME (R) -> IDA5 -> ';
|
|
21
|
+
/**
|
|
22
|
+
* Wrap share data with the branded IDA5 copyright header.
|
|
23
|
+
*
|
|
24
|
+
* Output format (patent-locked, NEVER change):
|
|
25
|
+
* Xecret (TM) -> PRIVATE .ME (R) -> IDA5 -> Encrypted:// [data] => Generated by Xecret (TM)
|
|
26
|
+
*
|
|
27
|
+
* @param data - Base64-encoded share data (or any string payload)
|
|
28
|
+
* @returns Branded string with copyright header wrapping the data
|
|
29
|
+
*/
|
|
30
|
+
export function formatShareHeader(data) {
|
|
31
|
+
return `${BRAND_PREFIX}${START_MARKER} ${data} ${END_MARKER}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Extract share data from a branded IDA5 header string.
|
|
35
|
+
*
|
|
36
|
+
* Backward-compatible: if the branded markers are not found, returns
|
|
37
|
+
* the input string trimmed (handles legacy headerless shares).
|
|
38
|
+
*
|
|
39
|
+
* @param input - Branded share string or legacy raw data
|
|
40
|
+
* @returns Extracted share data with whitespace trimmed
|
|
41
|
+
*/
|
|
42
|
+
export function parseShareHeader(input) {
|
|
43
|
+
const startIdx = input.indexOf(START_MARKER);
|
|
44
|
+
if (startIdx < 0)
|
|
45
|
+
return input.trim();
|
|
46
|
+
const dataStart = startIdx + START_MARKER.length;
|
|
47
|
+
const endIdx = input.indexOf(END_MARKER, dataStart);
|
|
48
|
+
if (endIdx < 0)
|
|
49
|
+
return input.trim();
|
|
50
|
+
return input.substring(dataStart, endIdx).trim();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Check whether a string contains the branded IDA5 share header.
|
|
54
|
+
*
|
|
55
|
+
* Useful for format detection — distinguishing branded shares from
|
|
56
|
+
* legacy raw base64 shares.
|
|
57
|
+
*
|
|
58
|
+
* @param input - String to check
|
|
59
|
+
* @returns true if the branded markers are present
|
|
60
|
+
*/
|
|
61
|
+
export function hasShareHeader(input) {
|
|
62
|
+
return input.includes(START_MARKER) && input.includes(END_MARKER);
|
|
63
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level share creation and reconstruction API.
|
|
3
|
+
*
|
|
4
|
+
* Sender pipeline: serialize (TLV) → pad (PKCS#7) → HMAC (sign) → split (XorIDA)
|
|
5
|
+
* Receiver pipeline: reconstruct (XorIDA) → verify (HMAC) → unpad (PKCS#7) → deserialize (TLV)
|
|
6
|
+
*/
|
|
7
|
+
import type { Result, XailMessage, XailShare, ReconstructionError } from '@private.me/shared';
|
|
8
|
+
/**
|
|
9
|
+
* Create shares from a XailMessage.
|
|
10
|
+
*
|
|
11
|
+
* Pipeline: serialize → pad → HMAC → split → package as XailShare[]
|
|
12
|
+
*
|
|
13
|
+
* @param message - The message to split into shares
|
|
14
|
+
* @param n - Total number of shares to produce
|
|
15
|
+
* @param k - Threshold: minimum shares needed for reconstruction
|
|
16
|
+
* @returns Array of n XailShare objects ready for transport
|
|
17
|
+
*/
|
|
18
|
+
export declare function createShares(message: XailMessage, n: number, k: number): Promise<XailShare[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Reconstruct a XailMessage from k shares.
|
|
21
|
+
*
|
|
22
|
+
* Pipeline: validate → reconstruct → verify HMAC → unpad → deserialize
|
|
23
|
+
*
|
|
24
|
+
* @param shares - Array of k XailShare objects (must share the same UUID)
|
|
25
|
+
* @returns Reconstructed message, or ReconstructionError
|
|
26
|
+
*/
|
|
27
|
+
export declare function reconstructMessage(shares: readonly XailShare[]): Promise<Result<XailMessage, ReconstructionError>>;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level share creation and reconstruction API.
|
|
3
|
+
*
|
|
4
|
+
* Sender pipeline: serialize (TLV) → pad (PKCS#7) → HMAC (sign) → split (XorIDA)
|
|
5
|
+
* Receiver pipeline: reconstruct (XorIDA) → verify (HMAC) → unpad (PKCS#7) → deserialize (TLV)
|
|
6
|
+
*/
|
|
7
|
+
import { ok, err } from"../shared/index.js";
|
|
8
|
+
import { serializeMessage, deserializeMessage } from './tlv.js';
|
|
9
|
+
import { pkcs7Pad, pkcs7Unpad } from './padding.js';
|
|
10
|
+
import { generateHMAC, verifyHMAC } from './hmac.js';
|
|
11
|
+
import { splitXorIDA, reconstructXorIDA, nextOddPrime } from './xorida.js';
|
|
12
|
+
import { generateUUID } from './uuid.js';
|
|
13
|
+
/**
|
|
14
|
+
* Create shares from a XailMessage.
|
|
15
|
+
*
|
|
16
|
+
* Pipeline: serialize → pad → HMAC → split → package as XailShare[]
|
|
17
|
+
*
|
|
18
|
+
* @param message - The message to split into shares
|
|
19
|
+
* @param n - Total number of shares to produce
|
|
20
|
+
* @param k - Threshold: minimum shares needed for reconstruction
|
|
21
|
+
* @returns Array of n XailShare objects ready for transport
|
|
22
|
+
*/
|
|
23
|
+
export async function createShares(message, n, k) {
|
|
24
|
+
// Ensure UUID is set before serialization so TLV and share headers match.
|
|
25
|
+
const uuid = message.uuid || generateUUID();
|
|
26
|
+
const messageWithUuid = uuid !== message.uuid ? { ...message, uuid } : message;
|
|
27
|
+
// Step 1: Serialize to TLV
|
|
28
|
+
const tlvPayload = serializeMessage(messageWithUuid);
|
|
29
|
+
// Step 2: Pad to XorIDA block boundary
|
|
30
|
+
const p = nextOddPrime(n);
|
|
31
|
+
const blockSize = p - 1;
|
|
32
|
+
const padded = pkcs7Pad(tlvPayload, blockSize);
|
|
33
|
+
// Step 3: HMAC the padded payload
|
|
34
|
+
const { key: hmacKey, signature: hmacSignature } = await generateHMAC(padded);
|
|
35
|
+
// Step 4: Split via XorIDA
|
|
36
|
+
const shareDataArrays = splitXorIDA(padded, n, k);
|
|
37
|
+
const shares = shareDataArrays.map((data, index) => ({
|
|
38
|
+
uuid,
|
|
39
|
+
index,
|
|
40
|
+
totalShares: n,
|
|
41
|
+
threshold: k,
|
|
42
|
+
data,
|
|
43
|
+
hmacKey: hmacKey.slice(), // each share carries a copy
|
|
44
|
+
hmacSignature: hmacSignature.slice(),
|
|
45
|
+
}));
|
|
46
|
+
return shares;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Reconstruct a XailMessage from k shares.
|
|
50
|
+
*
|
|
51
|
+
* Pipeline: validate → reconstruct → verify HMAC → unpad → deserialize
|
|
52
|
+
*
|
|
53
|
+
* @param shares - Array of k XailShare objects (must share the same UUID)
|
|
54
|
+
* @returns Reconstructed message, or ReconstructionError
|
|
55
|
+
*/
|
|
56
|
+
export async function reconstructMessage(shares) {
|
|
57
|
+
// Validation: need at least k shares
|
|
58
|
+
if (shares.length === 0) {
|
|
59
|
+
return err({ code: 'INSUFFICIENT_SHARES', message: 'No shares provided' });
|
|
60
|
+
}
|
|
61
|
+
const first = shares[0];
|
|
62
|
+
const k = first.threshold;
|
|
63
|
+
const n = first.totalShares;
|
|
64
|
+
if (shares.length < k) {
|
|
65
|
+
return err({
|
|
66
|
+
code: 'INSUFFICIENT_SHARES',
|
|
67
|
+
message: `Need ${k} shares, got ${shares.length}`,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// Validate consistency
|
|
71
|
+
const indices = [];
|
|
72
|
+
const indexSet = new Set();
|
|
73
|
+
for (const share of shares) {
|
|
74
|
+
if (share.uuid !== first.uuid) {
|
|
75
|
+
return err({
|
|
76
|
+
code: 'INVALID_SHARES',
|
|
77
|
+
message: 'Shares have different UUIDs',
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (share.totalShares !== n || share.threshold !== k) {
|
|
81
|
+
return err({
|
|
82
|
+
code: 'INVALID_SHARES',
|
|
83
|
+
message: 'Shares have inconsistent n/k values',
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (share.index < 0 || share.index >= n) {
|
|
87
|
+
return err({
|
|
88
|
+
code: 'INVALID_INDEX',
|
|
89
|
+
message: `Share index ${share.index} out of range [0, ${n})`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (indexSet.has(share.index)) {
|
|
93
|
+
return err({
|
|
94
|
+
code: 'INVALID_INDEX',
|
|
95
|
+
message: `Duplicate share index ${share.index}`,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
indexSet.add(share.index);
|
|
99
|
+
indices.push(share.index);
|
|
100
|
+
}
|
|
101
|
+
// Take first k shares
|
|
102
|
+
const usedShares = shares.slice(0, k);
|
|
103
|
+
const usedIndices = indices.slice(0, k);
|
|
104
|
+
const shareData = usedShares.map((s) => s.data);
|
|
105
|
+
// Step 1: Reconstruct padded payload
|
|
106
|
+
const padded = reconstructXorIDA(shareData, usedIndices, n, k);
|
|
107
|
+
// Step 2: Verify HMAC (before unpadding — fail closed)
|
|
108
|
+
const hmacValid = await verifyHMAC(first.hmacKey, padded, first.hmacSignature);
|
|
109
|
+
if (!hmacValid) {
|
|
110
|
+
return err({
|
|
111
|
+
code: 'HMAC_FAILURE',
|
|
112
|
+
message: 'HMAC verification failed — data may be corrupted or tampered',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// Step 3: Unpad
|
|
116
|
+
const p = nextOddPrime(n);
|
|
117
|
+
const blockSize = p - 1;
|
|
118
|
+
const unpadResult = pkcs7Unpad(padded, blockSize);
|
|
119
|
+
if (!unpadResult.ok) {
|
|
120
|
+
return err({
|
|
121
|
+
code: 'HMAC_FAILURE',
|
|
122
|
+
message: `Unpadding failed: ${unpadResult.error.message}`,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// Step 4: Deserialize TLV
|
|
126
|
+
const msgResult = deserializeMessage(unpadResult.value);
|
|
127
|
+
if (!msgResult.ok) {
|
|
128
|
+
return err({
|
|
129
|
+
code: 'INVALID_SHARES',
|
|
130
|
+
message: `Deserialization failed: ${msgResult.error.message}`,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// UUID cross-check: if the TLV payload contains a UUID, it must match the envelope UUID.
|
|
134
|
+
// Normalize both to lowercase+trimmed — bytesToUuid() always returns lowercase,
|
|
135
|
+
// but envelope UUIDs from email headers may differ in casing or have whitespace.
|
|
136
|
+
const tlvUuid = msgResult.value.uuid;
|
|
137
|
+
if (tlvUuid && tlvUuid.toLowerCase().trim() !== first.uuid.toLowerCase().trim()) {
|
|
138
|
+
return err({
|
|
139
|
+
code: 'UUID_MISMATCH',
|
|
140
|
+
message: 'TLV UUID does not match envelope UUID',
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// The share headers carry the authoritative UUID (X-Xail-UUID).
|
|
144
|
+
// The TLV payload may have a stale or empty UUID if the sender didn't
|
|
145
|
+
// pre-populate message.uuid before calling createShares(). Stamp the
|
|
146
|
+
// share-header UUID onto the reconstructed message.
|
|
147
|
+
return ok({ ...msgResult.value, uuid: first.uuid });
|
|
148
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TLV (Type-Length-Value) serialization for Xail messages.
|
|
3
|
+
*
|
|
4
|
+
* Format: [Type: 1 byte][Length: 4 bytes uint32 BE][Value: Length bytes]
|
|
5
|
+
*
|
|
6
|
+
* Serialization order: MESSAGE_UUID, SENDER_ID, TIMESTAMP, CONTENT_TYPE,
|
|
7
|
+
* MESSAGE_BODY, ATTACHMENT(s).
|
|
8
|
+
*
|
|
9
|
+
* HMAC key/signature and per-share metadata are NOT in the TLV payload —
|
|
10
|
+
* they travel in the share envelope.
|
|
11
|
+
*/
|
|
12
|
+
import type { Result, SerializationError, XailMessage } from '@private.me/shared';
|
|
13
|
+
/**
|
|
14
|
+
* Serialize a XailMessage into a TLV byte stream.
|
|
15
|
+
*
|
|
16
|
+
* @param message - Message to serialize
|
|
17
|
+
* @returns TLV-encoded byte array
|
|
18
|
+
*/
|
|
19
|
+
export declare function serializeMessage(message: XailMessage): Uint8Array;
|
|
20
|
+
/**
|
|
21
|
+
* Deserialize a TLV byte stream into a XailMessage.
|
|
22
|
+
*
|
|
23
|
+
* @param data - TLV-encoded byte array
|
|
24
|
+
* @returns Deserialized message, or SerializationError if invalid
|
|
25
|
+
*/
|
|
26
|
+
export declare function deserializeMessage(data: Uint8Array): Result<XailMessage, SerializationError>;
|