@fgv/ts-extras 5.1.0-42 → 5.1.0-43
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/dist/packlets/crypto-utils/index.browser.js +1 -1
- package/dist/packlets/crypto-utils/index.browser.js.map +1 -1
- package/dist/packlets/crypto-utils/index.js +1 -1
- package/dist/packlets/crypto-utils/index.js.map +1 -1
- package/dist/packlets/crypto-utils/keystore/converters.js +8 -4
- package/dist/packlets/crypto-utils/keystore/converters.js.map +1 -1
- package/dist/packlets/crypto-utils/keystore/keyStore.js +101 -2
- package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -1
- package/dist/packlets/crypto-utils/keystore/model.js +9 -4
- package/dist/packlets/crypto-utils/keystore/model.js.map +1 -1
- package/dist/packlets/crypto-utils/model.js.map +1 -1
- package/dist/packlets/crypto-utils/seedDerivedKeyPair.js +51 -38
- package/dist/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -1
- package/dist/packlets/crypto-utils/spkiHelpers.js +44 -0
- package/dist/packlets/crypto-utils/spkiHelpers.js.map +1 -1
- package/dist/ts-extras.d.ts +211 -30
- package/lib/packlets/crypto-utils/index.browser.d.ts +1 -1
- package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -1
- package/lib/packlets/crypto-utils/index.browser.js +3 -1
- package/lib/packlets/crypto-utils/index.browser.js.map +1 -1
- package/lib/packlets/crypto-utils/index.d.ts +1 -1
- package/lib/packlets/crypto-utils/index.d.ts.map +1 -1
- package/lib/packlets/crypto-utils/index.js +3 -1
- package/lib/packlets/crypto-utils/index.js.map +1 -1
- package/lib/packlets/crypto-utils/keystore/converters.d.ts +1 -1
- package/lib/packlets/crypto-utils/keystore/converters.d.ts.map +1 -1
- package/lib/packlets/crypto-utils/keystore/converters.js +8 -4
- package/lib/packlets/crypto-utils/keystore/converters.js.map +1 -1
- package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +45 -1
- package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -1
- package/lib/packlets/crypto-utils/keystore/keyStore.js +101 -2
- package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -1
- package/lib/packlets/crypto-utils/keystore/model.d.ts +57 -3
- package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -1
- package/lib/packlets/crypto-utils/keystore/model.js +9 -4
- package/lib/packlets/crypto-utils/keystore/model.js.map +1 -1
- package/lib/packlets/crypto-utils/model.d.ts +65 -20
- package/lib/packlets/crypto-utils/model.d.ts.map +1 -1
- package/lib/packlets/crypto-utils/model.js.map +1 -1
- package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts +11 -6
- package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts.map +1 -1
- package/lib/packlets/crypto-utils/seedDerivedKeyPair.js +51 -38
- package/lib/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -1
- package/lib/packlets/crypto-utils/spkiHelpers.d.ts +26 -0
- package/lib/packlets/crypto-utils/spkiHelpers.d.ts.map +1 -1
- package/lib/packlets/crypto-utils/spkiHelpers.js +46 -0
- package/lib/packlets/crypto-utils/spkiHelpers.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spkiHelpers.js","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/spkiHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\nimport { Result, fail, succeed } from '@fgv/ts-utils';\nimport { ICryptoProvider, KeyPairAlgorithm, MultibaseSpkiPublicKey } from './model';\n\n/**\n * Shared shape check for a base64url (no-padding) body: only base64url alphabet\n * characters (`A-Z`, `a-z`, `0-9`, `-`, `_`) and a length that is never `% 4 === 1`\n * (an impossible base64 remainder). Factored so the decoder and the\n * {@link isValidMultibaseSpkiPublicKey} guard agree on exactly one rule.\n */\nfunction isBase64UrlNoPadBody(body: string): boolean {\n return /^[A-Za-z0-9_-]*$/.test(body) && body.length % 4 !== 1;\n}\n\n/**\n * Encodes a `Uint8Array` as a base64url (no-padding) string (RFC 4648 §5).\n *\n * The body uses the base64url alphabet (`+` → `-`, `/` → `_`) and trailing `=`\n * padding is stripped. This is the bare primitive with no multibase prefix; use\n * {@link CryptoUtils.multibaseBase64UrlEncode} when a multibase-`'m'`-prefixed value is required.\n *\n * @param data - The binary data to encode.\n * @returns The base64url-no-pad string.\n * @public\n */\nexport function base64UrlNoPadEncode(data: Uint8Array): string {\n let base64: string;\n if (typeof Buffer !== 'undefined') {\n base64 = Buffer.from(data).toString('base64');\n /* c8 ignore start - browser-only: btoa path not available in Node tests */\n } else {\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n base64 = btoa(binary);\n }\n /* c8 ignore stop */\n // Convert to base64url: + → -, / → _, strip = padding\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/**\n * Decodes a base64url (no-padding) string (RFC 4648 §5) back to a `Uint8Array`.\n *\n * This is the bare primitive with no multibase prefix; use\n * {@link CryptoUtils.multibaseBase64UrlDecode} to decode a multibase-`'m'`-prefixed value.\n *\n * @param encoded - The base64url-no-pad body to decode.\n * @returns `Success` with the decoded bytes, or `Failure` with error context.\n * @public\n */\nexport function base64UrlNoPadDecode(encoded: string): Result<Uint8Array> {\n if (!isBase64UrlNoPadBody(encoded)) {\n return fail(`base64UrlNoPadDecode: malformed base64url body`);\n }\n // Convert base64url back to standard base64 and restore padding\n const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n try {\n let bytes: Uint8Array;\n if (typeof Buffer !== 'undefined') {\n bytes = new Uint8Array(Buffer.from(padded, 'base64'));\n /* c8 ignore start - browser-only: atob path not available in Node tests */\n } else {\n const binary = atob(padded);\n bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n }\n /* c8 ignore stop */\n return succeed(bytes);\n /* c8 ignore next 3 - defensive: shape check above prevents invalid chars from reaching here */\n } catch {\n return fail(`base64UrlNoPadDecode: malformed base64url body`);\n }\n}\n\n/**\n * The structural *shape* of a {@link CryptoUtils.MultibaseSpkiPublicKey}: the\n * multibase `'m'` prefix followed by a non-empty base64url-no-pad body\n * (`A-Z`, `a-z`, `0-9`, `-`, `_`).\n *\n * This is a shape prefilter, not full validation: it does not decode the DER\n * SPKI or verify the key material or algorithm (that happens in\n * {@link CryptoUtils.importPublicKeyFromMultibaseSpki}). The authoritative guard\n * is {@link CryptoUtils.isValidMultibaseSpkiPublicKey}, which enforces this\n * pattern **and** additionally rejects a body whose length is an impossible\n * base64 remainder. Exposed for callers that need the pattern directly (e.g. a\n * JSON-schema `pattern` field); prefer the guard/converter for validation.\n *\n * @public\n */\nexport const MultibaseSpkiPublicKeyRegExp: RegExp = /^m[A-Za-z0-9_-]+$/;\n\n/**\n * Type guard for {@link CryptoUtils.MultibaseSpkiPublicKey}: a string matching\n * {@link CryptoUtils.MultibaseSpkiPublicKeyRegExp} (multibase `'m'` prefix + a\n * non-empty base64url-no-pad body) whose body also satisfies the base64url-no-pad\n * length rule shared with {@link CryptoUtils.base64UrlNoPadDecode}. This is a\n * structural *shape* check, not full validation — it does not decode the DER SPKI\n * or verify the key material/algorithm (a malformed-but-well-shaped string fails\n * later, with clear context, in {@link CryptoUtils.importPublicKeyFromMultibaseSpki}).\n *\n * @param value - The value to test.\n * @returns `true` if `value` is a well-formed multibase SPKI public key string.\n * @public\n */\nexport function isValidMultibaseSpkiPublicKey(value: unknown): value is MultibaseSpkiPublicKey {\n return (\n typeof value === 'string' &&\n MultibaseSpkiPublicKeyRegExp.test(value) &&\n isBase64UrlNoPadBody(value.slice(1))\n );\n}\n\n/**\n * Encodes a `Uint8Array` as a multibase base64url (no-padding) string.\n *\n * The multibase prefix `'m'` identifies the encoding as RFC 4648 base64url\n * without padding. The body uses base64url alphabet: `+` → `-`, `/` → `_`,\n * and trailing `=` padding is stripped.\n *\n * @param data - The binary data to encode.\n * @returns A multibase-prefixed base64url string (`'m' + base64url-no-pad`).\n * @public\n */\nexport function multibaseBase64UrlEncode(data: Uint8Array): string {\n return 'm' + base64UrlNoPadEncode(data);\n}\n\n/**\n * Decodes a multibase base64url (no-padding) string back to a `Uint8Array`.\n *\n * Validates that the first character is `'m'` (the multibase prefix for\n * RFC 4648 base64url without padding), then decodes the remaining body.\n *\n * @param encoded - A multibase-prefixed base64url string.\n * @returns `Success` with the decoded bytes, or `Failure` with error context.\n * @public\n */\nexport function multibaseBase64UrlDecode(encoded: string): Result<Uint8Array> {\n if (!encoded.startsWith('m')) {\n return fail(\n `multibaseBase64UrlDecode: invalid multibase prefix '${\n encoded[0] ?? '(empty)'\n }' — expected 'm' (base64url)`\n );\n }\n // Intentionally pin the exact original message (the delegate has a single failure\n // mode) to keep this established public function byte-for-byte behavior-preserving\n // after the extract-and-delegate refactor — do not \"fix\" this into composing the\n // delegate's message without updating the delegation-equivalence tests.\n return base64UrlNoPadDecode(encoded.slice(1)).withErrorFormat(\n () => `multibaseBase64UrlDecode: malformed base64url body`\n );\n}\n\n/**\n * Exports a public `CryptoKey` as a multibase base64url-encoded SPKI blob.\n *\n * The SPKI (SubjectPublicKeyInfo) format is the standard DER-encoded structure\n * for public keys defined in RFC 5280, RFC 5480, and RFC 8410. It is\n * algorithm-agnostic and suitable for storage and transmission.\n *\n * @param key - The `CryptoKey` to export. Must have `key.type === 'public'`.\n * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the export operation.\n * @returns `Success` with the multibase SPKI string, or `Failure` with error context.\n * @public\n */\nexport async function exportPublicKeyAsMultibaseSpki(\n key: CryptoKey,\n provider: ICryptoProvider\n): Promise<Result<MultibaseSpkiPublicKey>> {\n return (await provider.exportPublicKeySpki(key))\n .withErrorFormat((e) => `exportPublicKeyAsMultibaseSpki: ${e}`)\n .onSuccess((buf) =>\n // The output is a freshly-built valid multibase SPKI string (`'m'` prefix +\n // base64url-no-pad body), so brand it at the construction site — no re-validation needed.\n succeed(multibaseBase64UrlEncode(buf) as MultibaseSpkiPublicKey)\n );\n}\n\n/**\n * Imports a public key from a multibase base64url-encoded SPKI blob.\n *\n * Decodes the multibase prefix, decodes the base64url body, then uses\n * the provider to import the key with the algorithm parameters from\n * {@link CryptoUtils.keyPairAlgorithmParams}.\n *\n * Accepts a plain `string` (not only a branded {@link CryptoUtils.MultibaseSpkiPublicKey}),\n * so callers holding an unbranded value read from storage or the wire can import\n * it directly; a malformed value fails with error context rather than throwing.\n *\n * @param encoded - A multibase SPKI string produced by {@link CryptoUtils.exportPublicKeyAsMultibaseSpki}.\n * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm} the key was generated for.\n * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the import operation.\n * @returns `Success` with the imported public `CryptoKey`, or `Failure` with error context.\n * @public\n */\nexport async function importPublicKeyFromMultibaseSpki(\n encoded: string,\n algorithm: KeyPairAlgorithm,\n provider: ICryptoProvider\n): Promise<Result<CryptoKey>> {\n const decodeResult = multibaseBase64UrlDecode(encoded);\n if (decodeResult.isFailure()) {\n return fail(`importPublicKeyFromMultibaseSpki: ${decodeResult.message}`);\n }\n return (await provider.importPublicKeySpki(decodeResult.value, algorithm)).withErrorFormat(\n (e) => `importPublicKeyFromMultibaseSpki: ${e}`\n );\n}\n\n// DER prefix for an X25519 SubjectPublicKeyInfo: SEQUENCE { SEQUENCE { OID id-X25519 }, BIT STRING }.\n// SEQUENCE(42) / SEQUENCE(5) / OID 1.3.101.110 (id-X25519) / BIT STRING(33, 0 unused bits).\nconst _X25519_SPKI_PREFIX: ReadonlyArray<number> = [\n 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x03, 0x21, 0x00\n];\nconst _X25519_SPKI_LENGTH: number = _X25519_SPKI_PREFIX.length + 32;\n\n/**\n * Strips the fixed DER prefix from an X25519 SubjectPublicKeyInfo blob, returning the raw\n * 32-byte public key.\n *\n * An X25519 SPKI is always exactly 44 bytes: a fixed 12-byte prefix (SEQUENCE / AlgorithmIdentifier\n * with OID 1.3.101.110 / BIT STRING) followed by the 32-byte raw key. Use this to convert a\n * SPKI-held recipient public key into the raw form accepted by {@link HpkeProvider.openBase}'s\n * `recipientPublicKey` parameter.\n *\n * @param spki - The DER-encoded X25519 SubjectPublicKeyInfo bytes.\n * @returns `Success` with the raw 32-byte public key, or `Failure` if `spki` is not a\n * well-formed 44-byte X25519 SPKI blob.\n * @public\n */\nexport function spkiToRawX25519(spki: Uint8Array): Result<Uint8Array> {\n if (spki.length !== _X25519_SPKI_LENGTH) {\n return fail(`spkiToRawX25519: expected ${_X25519_SPKI_LENGTH} bytes, got ${spki.length}`);\n }\n for (let i = 0; i < _X25519_SPKI_PREFIX.length; i++) {\n if (spki[i] !== _X25519_SPKI_PREFIX[i]) {\n return fail(`spkiToRawX25519: byte ${i} does not match the expected X25519 SPKI prefix`);\n }\n }\n return succeed(spki.slice(_X25519_SPKI_PREFIX.length));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"spkiHelpers.js","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/spkiHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\nimport { Result, fail, succeed } from '@fgv/ts-utils';\nimport { ICryptoProvider, KeyPairAlgorithm, MultibaseSpkiPublicKey } from './model';\n\n/**\n * Shared shape check for a base64url (no-padding) body: only base64url alphabet\n * characters (`A-Z`, `a-z`, `0-9`, `-`, `_`) and a length that is never `% 4 === 1`\n * (an impossible base64 remainder). Factored so the decoder and the\n * {@link isValidMultibaseSpkiPublicKey} guard agree on exactly one rule.\n */\nfunction isBase64UrlNoPadBody(body: string): boolean {\n return /^[A-Za-z0-9_-]*$/.test(body) && body.length % 4 !== 1;\n}\n\n/**\n * Encodes a `Uint8Array` as a base64url (no-padding) string (RFC 4648 §5).\n *\n * The body uses the base64url alphabet (`+` → `-`, `/` → `_`) and trailing `=`\n * padding is stripped. This is the bare primitive with no multibase prefix; use\n * {@link CryptoUtils.multibaseBase64UrlEncode} when a multibase-`'m'`-prefixed value is required.\n *\n * @param data - The binary data to encode.\n * @returns The base64url-no-pad string.\n * @public\n */\nexport function base64UrlNoPadEncode(data: Uint8Array): string {\n let base64: string;\n if (typeof Buffer !== 'undefined') {\n base64 = Buffer.from(data).toString('base64');\n /* c8 ignore start - browser-only: btoa path not available in Node tests */\n } else {\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n base64 = btoa(binary);\n }\n /* c8 ignore stop */\n // Convert to base64url: + → -, / → _, strip = padding\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/**\n * Decodes a base64url (no-padding) string (RFC 4648 §5) back to a `Uint8Array`.\n *\n * This is the bare primitive with no multibase prefix; use\n * {@link CryptoUtils.multibaseBase64UrlDecode} to decode a multibase-`'m'`-prefixed value.\n *\n * @param encoded - The base64url-no-pad body to decode.\n * @returns `Success` with the decoded bytes, or `Failure` with error context.\n * @public\n */\nexport function base64UrlNoPadDecode(encoded: string): Result<Uint8Array> {\n if (!isBase64UrlNoPadBody(encoded)) {\n return fail(`base64UrlNoPadDecode: malformed base64url body`);\n }\n // Convert base64url back to standard base64 and restore padding\n const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n try {\n let bytes: Uint8Array;\n if (typeof Buffer !== 'undefined') {\n bytes = new Uint8Array(Buffer.from(padded, 'base64'));\n /* c8 ignore start - browser-only: atob path not available in Node tests */\n } else {\n const binary = atob(padded);\n bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n }\n /* c8 ignore stop */\n return succeed(bytes);\n /* c8 ignore next 3 - defensive: shape check above prevents invalid chars from reaching here */\n } catch {\n return fail(`base64UrlNoPadDecode: malformed base64url body`);\n }\n}\n\n/**\n * Encodes a `Uint8Array` as a lowercase hexadecimal string with no `0x` prefix.\n *\n * Each byte becomes exactly two lowercase hex characters (zero-padded), so an\n * `n`-byte input yields a `2n`-character string. An empty input yields the empty\n * string. This is the inverse of {@link CryptoUtils.hexDecode}.\n *\n * @param data - The binary data to encode.\n * @returns The lowercase, unprefixed hex string.\n * @public\n */\nexport function hexEncode(data: Uint8Array): string {\n let hex = '';\n for (let i = 0; i < data.length; i++) {\n hex += data[i].toString(16).padStart(2, '0');\n }\n return hex;\n}\n\n/**\n * Decodes a hexadecimal string (no `0x` prefix) back to a `Uint8Array`.\n *\n * Liberal in what it accepts: both lowercase and uppercase hex digits are\n * allowed (whereas {@link CryptoUtils.hexEncode} always emits lowercase). The\n * input must have even length and contain only hex digits (`0-9`, `a-f`, `A-F`);\n * an empty string decodes to an empty `Uint8Array`. Odd length or any non-hex\n * character fails with error context.\n *\n * @param encoded - The hex string to decode.\n * @returns `Success` with the decoded bytes, or `Failure` with error context.\n * @public\n */\nexport function hexDecode(encoded: string): Result<Uint8Array> {\n if (encoded.length % 2 !== 0) {\n return fail(`hexDecode: odd-length hex string (length ${encoded.length})`);\n }\n if (!/^[0-9a-fA-F]*$/.test(encoded)) {\n return fail(`hexDecode: string contains non-hex characters`);\n }\n const bytes = new Uint8Array(encoded.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(encoded.slice(i * 2, i * 2 + 2), 16);\n }\n return succeed(bytes);\n}\n\n/**\n * The structural *shape* of a {@link CryptoUtils.MultibaseSpkiPublicKey}: the\n * multibase `'m'` prefix followed by a non-empty base64url-no-pad body\n * (`A-Z`, `a-z`, `0-9`, `-`, `_`).\n *\n * This is a shape prefilter, not full validation: it does not decode the DER\n * SPKI or verify the key material or algorithm (that happens in\n * {@link CryptoUtils.importPublicKeyFromMultibaseSpki}). The authoritative guard\n * is {@link CryptoUtils.isValidMultibaseSpkiPublicKey}, which enforces this\n * pattern **and** additionally rejects a body whose length is an impossible\n * base64 remainder. Exposed for callers that need the pattern directly (e.g. a\n * JSON-schema `pattern` field); prefer the guard/converter for validation.\n *\n * @public\n */\nexport const MultibaseSpkiPublicKeyRegExp: RegExp = /^m[A-Za-z0-9_-]+$/;\n\n/**\n * Type guard for {@link CryptoUtils.MultibaseSpkiPublicKey}: a string matching\n * {@link CryptoUtils.MultibaseSpkiPublicKeyRegExp} (multibase `'m'` prefix + a\n * non-empty base64url-no-pad body) whose body also satisfies the base64url-no-pad\n * length rule shared with {@link CryptoUtils.base64UrlNoPadDecode}. This is a\n * structural *shape* check, not full validation — it does not decode the DER SPKI\n * or verify the key material/algorithm (a malformed-but-well-shaped string fails\n * later, with clear context, in {@link CryptoUtils.importPublicKeyFromMultibaseSpki}).\n *\n * @param value - The value to test.\n * @returns `true` if `value` is a well-formed multibase SPKI public key string.\n * @public\n */\nexport function isValidMultibaseSpkiPublicKey(value: unknown): value is MultibaseSpkiPublicKey {\n return (\n typeof value === 'string' &&\n MultibaseSpkiPublicKeyRegExp.test(value) &&\n isBase64UrlNoPadBody(value.slice(1))\n );\n}\n\n/**\n * Encodes a `Uint8Array` as a multibase base64url (no-padding) string.\n *\n * The multibase prefix `'m'` identifies the encoding as RFC 4648 base64url\n * without padding. The body uses base64url alphabet: `+` → `-`, `/` → `_`,\n * and trailing `=` padding is stripped.\n *\n * @param data - The binary data to encode.\n * @returns A multibase-prefixed base64url string (`'m' + base64url-no-pad`).\n * @public\n */\nexport function multibaseBase64UrlEncode(data: Uint8Array): string {\n return 'm' + base64UrlNoPadEncode(data);\n}\n\n/**\n * Decodes a multibase base64url (no-padding) string back to a `Uint8Array`.\n *\n * Validates that the first character is `'m'` (the multibase prefix for\n * RFC 4648 base64url without padding), then decodes the remaining body.\n *\n * @param encoded - A multibase-prefixed base64url string.\n * @returns `Success` with the decoded bytes, or `Failure` with error context.\n * @public\n */\nexport function multibaseBase64UrlDecode(encoded: string): Result<Uint8Array> {\n if (!encoded.startsWith('m')) {\n return fail(\n `multibaseBase64UrlDecode: invalid multibase prefix '${\n encoded[0] ?? '(empty)'\n }' — expected 'm' (base64url)`\n );\n }\n // Intentionally pin the exact original message (the delegate has a single failure\n // mode) to keep this established public function byte-for-byte behavior-preserving\n // after the extract-and-delegate refactor — do not \"fix\" this into composing the\n // delegate's message without updating the delegation-equivalence tests.\n return base64UrlNoPadDecode(encoded.slice(1)).withErrorFormat(\n () => `multibaseBase64UrlDecode: malformed base64url body`\n );\n}\n\n/**\n * Exports a public `CryptoKey` as a multibase base64url-encoded SPKI blob.\n *\n * The SPKI (SubjectPublicKeyInfo) format is the standard DER-encoded structure\n * for public keys defined in RFC 5280, RFC 5480, and RFC 8410. It is\n * algorithm-agnostic and suitable for storage and transmission.\n *\n * @param key - The `CryptoKey` to export. Must have `key.type === 'public'`.\n * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the export operation.\n * @returns `Success` with the multibase SPKI string, or `Failure` with error context.\n * @public\n */\nexport async function exportPublicKeyAsMultibaseSpki(\n key: CryptoKey,\n provider: ICryptoProvider\n): Promise<Result<MultibaseSpkiPublicKey>> {\n return (await provider.exportPublicKeySpki(key))\n .withErrorFormat((e) => `exportPublicKeyAsMultibaseSpki: ${e}`)\n .onSuccess((buf) =>\n // The output is a freshly-built valid multibase SPKI string (`'m'` prefix +\n // base64url-no-pad body), so brand it at the construction site — no re-validation needed.\n succeed(multibaseBase64UrlEncode(buf) as MultibaseSpkiPublicKey)\n );\n}\n\n/**\n * Imports a public key from a multibase base64url-encoded SPKI blob.\n *\n * Decodes the multibase prefix, decodes the base64url body, then uses\n * the provider to import the key with the algorithm parameters from\n * {@link CryptoUtils.keyPairAlgorithmParams}.\n *\n * Accepts a plain `string` (not only a branded {@link CryptoUtils.MultibaseSpkiPublicKey}),\n * so callers holding an unbranded value read from storage or the wire can import\n * it directly; a malformed value fails with error context rather than throwing.\n *\n * @param encoded - A multibase SPKI string produced by {@link CryptoUtils.exportPublicKeyAsMultibaseSpki}.\n * @param algorithm - The {@link CryptoUtils.KeyPairAlgorithm} the key was generated for.\n * @param provider - The {@link CryptoUtils.ICryptoProvider} to use for the import operation.\n * @returns `Success` with the imported public `CryptoKey`, or `Failure` with error context.\n * @public\n */\nexport async function importPublicKeyFromMultibaseSpki(\n encoded: string,\n algorithm: KeyPairAlgorithm,\n provider: ICryptoProvider\n): Promise<Result<CryptoKey>> {\n const decodeResult = multibaseBase64UrlDecode(encoded);\n if (decodeResult.isFailure()) {\n return fail(`importPublicKeyFromMultibaseSpki: ${decodeResult.message}`);\n }\n return (await provider.importPublicKeySpki(decodeResult.value, algorithm)).withErrorFormat(\n (e) => `importPublicKeyFromMultibaseSpki: ${e}`\n );\n}\n\n// DER prefix for an X25519 SubjectPublicKeyInfo: SEQUENCE { SEQUENCE { OID id-X25519 }, BIT STRING }.\n// SEQUENCE(42) / SEQUENCE(5) / OID 1.3.101.110 (id-X25519) / BIT STRING(33, 0 unused bits).\nconst _X25519_SPKI_PREFIX: ReadonlyArray<number> = [\n 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x03, 0x21, 0x00\n];\nconst _X25519_SPKI_LENGTH: number = _X25519_SPKI_PREFIX.length + 32;\n\n/**\n * Strips the fixed DER prefix from an X25519 SubjectPublicKeyInfo blob, returning the raw\n * 32-byte public key.\n *\n * An X25519 SPKI is always exactly 44 bytes: a fixed 12-byte prefix (SEQUENCE / AlgorithmIdentifier\n * with OID 1.3.101.110 / BIT STRING) followed by the 32-byte raw key. Use this to convert a\n * SPKI-held recipient public key into the raw form accepted by {@link HpkeProvider.openBase}'s\n * `recipientPublicKey` parameter.\n *\n * @param spki - The DER-encoded X25519 SubjectPublicKeyInfo bytes.\n * @returns `Success` with the raw 32-byte public key, or `Failure` if `spki` is not a\n * well-formed 44-byte X25519 SPKI blob.\n * @public\n */\nexport function spkiToRawX25519(spki: Uint8Array): Result<Uint8Array> {\n if (spki.length !== _X25519_SPKI_LENGTH) {\n return fail(`spkiToRawX25519: expected ${_X25519_SPKI_LENGTH} bytes, got ${spki.length}`);\n }\n for (let i = 0; i < _X25519_SPKI_PREFIX.length; i++) {\n if (spki[i] !== _X25519_SPKI_PREFIX[i]) {\n return fail(`spkiToRawX25519: byte ${i} does not match the expected X25519 SPKI prefix`);\n }\n }\n return succeed(spki.slice(_X25519_SPKI_PREFIX.length));\n}\n"]}
|
package/dist/ts-extras.d.ts
CHANGED
|
@@ -732,6 +732,8 @@ declare namespace CryptoUtils {
|
|
|
732
732
|
base64UrlNoPadDecode,
|
|
733
733
|
base64UrlNoPadEncode,
|
|
734
734
|
exportPublicKeyAsMultibaseSpki,
|
|
735
|
+
hexDecode,
|
|
736
|
+
hexEncode,
|
|
735
737
|
importPublicKeyFromMultibaseSpki,
|
|
736
738
|
isValidMultibaseSpkiPublicKey,
|
|
737
739
|
MultibaseSpkiPublicKeyRegExp,
|
|
@@ -759,6 +761,7 @@ declare namespace CryptoUtils {
|
|
|
759
761
|
IArgon2idParams,
|
|
760
762
|
ARGON2ID_OWASP_MIN,
|
|
761
763
|
ARGON2ID_PASSPHRASE,
|
|
764
|
+
IArgon2idKeyingOptions,
|
|
762
765
|
IArgon2idProvider,
|
|
763
766
|
IEncryptedFile,
|
|
764
767
|
ICryptoProvider,
|
|
@@ -851,25 +854,30 @@ declare const DEFAULT_SECRET_ITERATIONS: number;
|
|
|
851
854
|
* {@link CryptoUtils.ICryptoProvider.importKeyPairFromSeed | importKeyPairFromSeed}
|
|
852
855
|
* for the public contract.
|
|
853
856
|
*
|
|
854
|
-
* For
|
|
855
|
-
* runs a transient-extractable-then-derive dance so the public
|
|
856
|
-
* recoverable even when the caller requests a non-extractable private key:
|
|
857
|
+
* For each supported algorithm: wraps the 32-byte seed in the RFC 8410 PKCS#8
|
|
858
|
+
* envelope, then runs a transient-extractable-then-derive dance so the public
|
|
859
|
+
* key is recoverable even when the caller requests a non-extractable private key:
|
|
857
860
|
*
|
|
858
861
|
* 1. Import the PKCS#8 as a *transient* extractable private key.
|
|
859
862
|
* 2. Export it to JWK to read the deterministic public coordinate `x`.
|
|
860
|
-
* 3. Import `{ kty: 'OKP', crv
|
|
863
|
+
* 3. Import `{ kty: 'OKP', crv, x }` as the returned public key.
|
|
861
864
|
* 4. For the returned private key: reuse the transient key when `extractable`
|
|
862
865
|
* is `true`; otherwise re-import the same PKCS#8 as a non-extractable key.
|
|
863
866
|
* The transient extractable key is never returned when `extractable` is
|
|
864
867
|
* `false`, so seed material cannot escape through it.
|
|
865
868
|
*
|
|
869
|
+
* The two algorithms differ only in the OID/name/curve/usages (see
|
|
870
|
+
* {@link ISeedAlgorithmParams}); `'x25519'` yields the DH key-agreement keypair
|
|
871
|
+
* (private `'deriveBits'`, public no-usage) that {@link CryptoUtils.HpkeProvider}
|
|
872
|
+
* consumes as its recipient key.
|
|
873
|
+
*
|
|
866
874
|
* The seed bytes are copied into a freshly allocated PKCS#8 buffer, so the
|
|
867
875
|
* `BufferSource` handed to WebCrypto is always backed by a plain `ArrayBuffer`
|
|
868
876
|
* (side-stepping the Node-20 `SharedArrayBuffer`-view rejection) and the
|
|
869
877
|
* caller's `seed` is never mutated.
|
|
870
878
|
*
|
|
871
|
-
* @param algorithm - The seed-derivable algorithm
|
|
872
|
-
*
|
|
879
|
+
* @param algorithm - The seed-derivable algorithm (`'ed25519'` or `'x25519'`).
|
|
880
|
+
* Any other value fails loudly rather than being mis-handled.
|
|
873
881
|
* @param seed - The 32-byte secret seed. Any other length fails loudly, before
|
|
874
882
|
* any WebCrypto call.
|
|
875
883
|
* @param extractable - Whether the returned private key may be exported.
|
|
@@ -1405,6 +1413,34 @@ declare namespace Hash {
|
|
|
1405
1413
|
}
|
|
1406
1414
|
export { Hash }
|
|
1407
1415
|
|
|
1416
|
+
/**
|
|
1417
|
+
* Decodes a hexadecimal string (no `0x` prefix) back to a `Uint8Array`.
|
|
1418
|
+
*
|
|
1419
|
+
* Liberal in what it accepts: both lowercase and uppercase hex digits are
|
|
1420
|
+
* allowed (whereas {@link CryptoUtils.hexEncode} always emits lowercase). The
|
|
1421
|
+
* input must have even length and contain only hex digits (`0-9`, `a-f`, `A-F`);
|
|
1422
|
+
* an empty string decodes to an empty `Uint8Array`. Odd length or any non-hex
|
|
1423
|
+
* character fails with error context.
|
|
1424
|
+
*
|
|
1425
|
+
* @param encoded - The hex string to decode.
|
|
1426
|
+
* @returns `Success` with the decoded bytes, or `Failure` with error context.
|
|
1427
|
+
* @public
|
|
1428
|
+
*/
|
|
1429
|
+
declare function hexDecode(encoded: string): Result<Uint8Array>;
|
|
1430
|
+
|
|
1431
|
+
/**
|
|
1432
|
+
* Encodes a `Uint8Array` as a lowercase hexadecimal string with no `0x` prefix.
|
|
1433
|
+
*
|
|
1434
|
+
* Each byte becomes exactly two lowercase hex characters (zero-padded), so an
|
|
1435
|
+
* `n`-byte input yields a `2n`-character string. An empty input yields the empty
|
|
1436
|
+
* string. This is the inverse of {@link CryptoUtils.hexDecode}.
|
|
1437
|
+
*
|
|
1438
|
+
* @param data - The binary data to encode.
|
|
1439
|
+
* @returns The lowercase, unprefixed hex string.
|
|
1440
|
+
* @public
|
|
1441
|
+
*/
|
|
1442
|
+
declare function hexEncode(data: Uint8Array): string;
|
|
1443
|
+
|
|
1408
1444
|
/**
|
|
1409
1445
|
* HPKE base mode (RFC 9180) — `DHKEM(X25519, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM`.
|
|
1410
1446
|
*
|
|
@@ -2560,6 +2596,33 @@ declare interface IArgon2idKeyDerivationParams {
|
|
|
2560
2596
|
readonly parallelism: number;
|
|
2561
2597
|
}
|
|
2562
2598
|
|
|
2599
|
+
/**
|
|
2600
|
+
* Optional keyed-hashing inputs for {@link CryptoUtils.IArgon2idProvider.argon2id | argon2id}
|
|
2601
|
+
* (RFC 9106 §3.1). These are distinct from the cost parameters in
|
|
2602
|
+
* {@link CryptoUtils.IArgon2idParams} — they change the derived output but are
|
|
2603
|
+
* not tuning knobs. Both fields are optional; omitting a field (or passing an
|
|
2604
|
+
* empty `Uint8Array`) is a no-op that leaves the output byte-identical to a call
|
|
2605
|
+
* with no options at all.
|
|
2606
|
+
* @public
|
|
2607
|
+
*/
|
|
2608
|
+
declare interface IArgon2idKeyingOptions {
|
|
2609
|
+
/**
|
|
2610
|
+
* Optional secret key K (RFC 9106 keyed hashing, sometimes called a "pepper").
|
|
2611
|
+
* When present and non-empty it is mixed into the hash so that the derived
|
|
2612
|
+
* output cannot be reproduced without also knowing K. Empty or omitted means
|
|
2613
|
+
* no secret. Honored by both the Node and browser backends.
|
|
2614
|
+
*/
|
|
2615
|
+
readonly secret?: Uint8Array;
|
|
2616
|
+
/**
|
|
2617
|
+
* Optional associated data X (RFC 9106 §3.1). When present and non-empty it is
|
|
2618
|
+
* mixed into the hash. **Node-only:** the WASM (`hash-wasm`) browser backend
|
|
2619
|
+
* has no associated-data input, so `BrowserArgon2Provider` fails loudly rather
|
|
2620
|
+
* than silently dropping it (which would produce wrong bytes). Empty or omitted
|
|
2621
|
+
* means no associated data and is accepted by both backends.
|
|
2622
|
+
*/
|
|
2623
|
+
readonly associatedData?: Uint8Array;
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2563
2626
|
/**
|
|
2564
2627
|
* Parameters for Argon2id key derivation (RFC 9106).
|
|
2565
2628
|
* All fields are required; fgv does not pick defaults silently.
|
|
@@ -2607,15 +2670,24 @@ declare interface IArgon2idProvider {
|
|
|
2607
2670
|
/**
|
|
2608
2671
|
* Derives key material from a password using Argon2id (RFC 9106 §3.1).
|
|
2609
2672
|
*
|
|
2610
|
-
* Returns the raw derived bytes as a `Uint8Array`.
|
|
2611
|
-
*
|
|
2673
|
+
* Returns the raw derived bytes as a `Uint8Array`. For the same inputs that
|
|
2674
|
+
* both backends support, the Node and browser implementations produce
|
|
2675
|
+
* byte-identical output. The optional `associatedData` in
|
|
2676
|
+
* {@link CryptoUtils.IArgon2idKeyingOptions} is the one exception: it is
|
|
2677
|
+
* Node-only (the browser WASM backend has no associated-data input), so a call
|
|
2678
|
+
* that supplies non-empty `associatedData` is not portable to the browser
|
|
2679
|
+
* backend. Every input the browser backend *does* support (including the
|
|
2680
|
+
* optional `secret`) is byte-identical across the two.
|
|
2612
2681
|
*
|
|
2613
2682
|
* @param password - Password or passphrase. Accepts string (UTF-8) or raw bytes.
|
|
2614
2683
|
* @param salt - Salt bytes. Must be random and unique per credential (\>= 16 bytes recommended).
|
|
2615
2684
|
* @param params - Argon2id parameters. Use `ARGON2ID_OWASP_MIN` as a starting point.
|
|
2685
|
+
* @param options - Optional {@link CryptoUtils.IArgon2idKeyingOptions | keyed-hashing inputs}
|
|
2686
|
+
* (secret K and/or associated data X). Omitting them (the default) leaves the
|
|
2687
|
+
* output byte-identical to prior behavior.
|
|
2616
2688
|
* @returns Success with derived bytes, Failure with error context.
|
|
2617
2689
|
*/
|
|
2618
|
-
argon2id(password: Uint8Array | string, salt: Uint8Array, params: IArgon2idParams): Promise<Result<Uint8Array>>;
|
|
2690
|
+
argon2id(password: Uint8Array | string, salt: Uint8Array, params: IArgon2idParams, options?: IArgon2idKeyingOptions): Promise<Result<Uint8Array>>;
|
|
2619
2691
|
}
|
|
2620
2692
|
|
|
2621
2693
|
/**
|
|
@@ -2881,16 +2953,19 @@ declare interface ICryptoProvider {
|
|
|
2881
2953
|
* material (key escrow, HD-style derivation, deterministic test vectors) rather
|
|
2882
2954
|
* than freshly sampled by {@link CryptoUtils.ICryptoProvider.generateKeyPair | generateKeyPair}.
|
|
2883
2955
|
*
|
|
2884
|
-
* For `'ed25519'` the private key *is* its 32-byte seed and
|
|
2885
|
-
* deterministic function of that seed (RFC 8032
|
|
2886
|
-
* recovered even when the caller requests a
|
|
2887
|
-
* transient extractable key used internally to
|
|
2888
|
-
* returned or logged when `extractable` is
|
|
2889
|
-
*
|
|
2890
|
-
*
|
|
2891
|
-
*
|
|
2892
|
-
*
|
|
2893
|
-
*
|
|
2956
|
+
* For both `'ed25519'` and `'x25519'` the private key *is* its 32-byte seed and
|
|
2957
|
+
* the public key is a deterministic function of that seed (RFC 8032 / RFC 7748),
|
|
2958
|
+
* so the returned public key is recovered even when the caller requests a
|
|
2959
|
+
* non-extractable private key. The transient extractable key used internally to
|
|
2960
|
+
* recover the public half is never returned or logged when `extractable` is
|
|
2961
|
+
* `false`. The returned keys carry the algorithm's usages: `'ed25519'` →
|
|
2962
|
+
* private `'sign'` / public `'verify'`; `'x25519'` → private `'deriveBits'` /
|
|
2963
|
+
* public no-usage (ready to hand to {@link CryptoUtils.HpkeProvider}).
|
|
2964
|
+
* @param algorithm - The {@link CryptoUtils.SeedDerivableAlgorithm | seed-derivable algorithm}
|
|
2965
|
+
* (`'ed25519'` or `'x25519'`); any other value fails loudly with context.
|
|
2966
|
+
* @param seed - The secret seed. It must be exactly 32 bytes for both supported
|
|
2967
|
+
* algorithms; any other length fails loudly, before any WebCrypto call. The
|
|
2968
|
+
* bytes are copied, not retained or mutated.
|
|
2894
2969
|
* @param extractable - Whether the returned private key may be exported. The
|
|
2895
2970
|
* returned public key is identical for a given seed regardless of this flag.
|
|
2896
2971
|
* @returns Success with the derived `CryptoKeyPair`, or Failure with error context.
|
|
@@ -3570,6 +3645,19 @@ declare interface IImportKeyOptions extends IImportSecretOptions {
|
|
|
3570
3645
|
readonly type?: KeyStoreSymmetricSecretType;
|
|
3571
3646
|
}
|
|
3572
3647
|
|
|
3648
|
+
/**
|
|
3649
|
+
* Options for importing raw opaque bytes via {@link KeyStore.importSecretBytes}.
|
|
3650
|
+
* Extends {@link IImportSecretOptions} with optional initial metadata.
|
|
3651
|
+
* @public
|
|
3652
|
+
*/
|
|
3653
|
+
declare interface IImportSecretBytesOptions extends IImportSecretOptions {
|
|
3654
|
+
/**
|
|
3655
|
+
* Optional initial mutable metadata to store with the entry. Can also be set
|
|
3656
|
+
* or replaced later via {@link KeyStore.setSecretMetadata}.
|
|
3657
|
+
*/
|
|
3658
|
+
readonly metadata?: JsonValue;
|
|
3659
|
+
}
|
|
3660
|
+
|
|
3573
3661
|
/**
|
|
3574
3662
|
* Options for importing a secret.
|
|
3575
3663
|
* @public
|
|
@@ -3850,16 +3938,36 @@ declare interface IKeyStoreSymmetricEntry {
|
|
|
3850
3938
|
* The secret data.
|
|
3851
3939
|
* - For `'encryption-key'`: 32-byte AES-256 key.
|
|
3852
3940
|
* - For `'api-key'`: UTF-8 encoded API key string (arbitrary length).
|
|
3941
|
+
* - For `'opaque'`: arbitrary raw bytes, stored and returned verbatim.
|
|
3853
3942
|
*/
|
|
3854
3943
|
readonly key: Uint8Array;
|
|
3855
3944
|
/**
|
|
3856
3945
|
* Optional description for this secret.
|
|
3857
3946
|
*/
|
|
3858
3947
|
readonly description?: string;
|
|
3948
|
+
/**
|
|
3949
|
+
* Optional mutable, non-secret-by-contract metadata for this entry. Set via
|
|
3950
|
+
* {@link CryptoUtils.KeyStore.KeyStore.setSecretMetadata} without touching the
|
|
3951
|
+
* secret `key` bytes.
|
|
3952
|
+
*
|
|
3953
|
+
* "Non-secret by contract" means the field is intended for lifecycle metadata
|
|
3954
|
+
* (rotation timestamps, labels, provenance) rather than secret material.
|
|
3955
|
+
* PHYSICALLY it lives inside the vault's AES-GCM ciphertext alongside the key
|
|
3956
|
+
* bytes — the vault has no plaintext index — so it is protected at rest by the
|
|
3957
|
+
* master password; the "non-secret" designation is a usage contract, not a
|
|
3958
|
+
* weaker custody class.
|
|
3959
|
+
*/
|
|
3960
|
+
readonly metadata?: JsonValue;
|
|
3859
3961
|
/**
|
|
3860
3962
|
* When this secret was added (ISO 8601).
|
|
3861
3963
|
*/
|
|
3862
3964
|
readonly createdAt: string;
|
|
3965
|
+
/**
|
|
3966
|
+
* When this entry was last mutated (ISO 8601). Stamped on any metadata
|
|
3967
|
+
* mutation (see {@link CryptoUtils.KeyStore.KeyStore.setSecretMetadata}).
|
|
3968
|
+
* Absent on entries that have never been mutated since creation.
|
|
3969
|
+
*/
|
|
3970
|
+
readonly updatedAt?: string;
|
|
3863
3971
|
}
|
|
3864
3972
|
|
|
3865
3973
|
/**
|
|
@@ -3899,10 +4007,22 @@ declare interface IKeyStoreSymmetricEntryJson {
|
|
|
3899
4007
|
* Optional description.
|
|
3900
4008
|
*/
|
|
3901
4009
|
readonly description?: string;
|
|
4010
|
+
/**
|
|
4011
|
+
* Optional mutable, non-secret-by-contract metadata for this entry. Present
|
|
4012
|
+
* only on `'keystore-v3'` vaults whose entry carried metadata; a v1/v2 vault
|
|
4013
|
+
* omits the field. Physically carried inside the vault ciphertext (the vault
|
|
4014
|
+
* has no plaintext index).
|
|
4015
|
+
*/
|
|
4016
|
+
readonly metadata?: JsonValue;
|
|
3902
4017
|
/**
|
|
3903
4018
|
* When this secret was added (ISO 8601).
|
|
3904
4019
|
*/
|
|
3905
4020
|
readonly createdAt: string;
|
|
4021
|
+
/**
|
|
4022
|
+
* When this entry was last mutated (ISO 8601). Present only on `'keystore-v3'`
|
|
4023
|
+
* vaults whose entry has been mutated since creation.
|
|
4024
|
+
*/
|
|
4025
|
+
readonly updatedAt?: string;
|
|
3906
4026
|
}
|
|
3907
4027
|
|
|
3908
4028
|
/**
|
|
@@ -4859,6 +4979,7 @@ declare namespace KeyStore {
|
|
|
4859
4979
|
IAddSecretOptions,
|
|
4860
4980
|
IImportSecretOptions,
|
|
4861
4981
|
IImportKeyOptions,
|
|
4982
|
+
IImportSecretBytesOptions,
|
|
4862
4983
|
IAddSecretFromPasswordOptions,
|
|
4863
4984
|
DEFAULT_SECRET_ITERATIONS,
|
|
4864
4985
|
IAddSecretFromPasswordResult,
|
|
@@ -5179,6 +5300,50 @@ declare class KeyStore_2 implements IEncryptionProvider {
|
|
|
5179
5300
|
* @public
|
|
5180
5301
|
*/
|
|
5181
5302
|
getApiKey(name: string): Result<string>;
|
|
5303
|
+
/**
|
|
5304
|
+
* Imports arbitrary raw bytes into the vault with type `'opaque'`.
|
|
5305
|
+
*
|
|
5306
|
+
* Unlike {@link KeyStore.importSecret} (which enforces a 32-byte AES-256 key)
|
|
5307
|
+
* and {@link KeyStore.importApiKey} (which UTF-8 encodes a string), this
|
|
5308
|
+
* accepts a byte buffer of any length and stores it verbatim — including
|
|
5309
|
+
* embedded NUL bytes. Use it for byte blobs that are neither a fixed-size key
|
|
5310
|
+
* nor a UTF-8 string (e.g. a serialized credential bundle), so they are not
|
|
5311
|
+
* mistyped as `'api-key'`.
|
|
5312
|
+
*
|
|
5313
|
+
* @param name - Unique name for the secret
|
|
5314
|
+
* @param bytes - The raw bytes to store
|
|
5315
|
+
* @param options - Optional description, initial metadata, whether to replace existing
|
|
5316
|
+
* @returns Success with entry, Failure if locked, empty, or exists and !replace
|
|
5317
|
+
* @public
|
|
5318
|
+
*/
|
|
5319
|
+
importSecretBytes(name: string, bytes: Uint8Array, options?: IImportSecretBytesOptions): Promise<Result<IAddSecretResult>>;
|
|
5320
|
+
/**
|
|
5321
|
+
* Retrieves the raw stored bytes for a symmetric entry, returned verbatim
|
|
5322
|
+
* (never UTF-8 decoded). Intended for `'opaque'` entries but works for any
|
|
5323
|
+
* symmetric type; asymmetric-keypair entries carry no raw key material and
|
|
5324
|
+
* are rejected.
|
|
5325
|
+
*
|
|
5326
|
+
* @param name - Name of the secret
|
|
5327
|
+
* @returns Success with a copy of the stored bytes, Failure if not found,
|
|
5328
|
+
* locked, or the entry is asymmetric
|
|
5329
|
+
* @public
|
|
5330
|
+
*/
|
|
5331
|
+
getSecretBytes(name: string): Result<Uint8Array>;
|
|
5332
|
+
/**
|
|
5333
|
+
* Replaces the mutable metadata on a symmetric entry and stamps `updatedAt`
|
|
5334
|
+
* with the current timestamp. Does NOT touch the secret `key` bytes — the
|
|
5335
|
+
* material reads back identically afterward.
|
|
5336
|
+
*
|
|
5337
|
+
* Metadata is non-secret by contract but physically lives inside the vault
|
|
5338
|
+
* ciphertext (see {@link CryptoUtils.KeyStore.IKeyStoreSymmetricEntry.metadata}).
|
|
5339
|
+
*
|
|
5340
|
+
* @param name - Name of the secret to update
|
|
5341
|
+
* @param value - New metadata value (replaces any prior metadata)
|
|
5342
|
+
* @returns Success with the updated entry, Failure if not found, locked, or
|
|
5343
|
+
* the entry is asymmetric
|
|
5344
|
+
* @public
|
|
5345
|
+
*/
|
|
5346
|
+
setSecretMetadata(name: string, value: JsonValue): Result<IKeyStoreSymmetricEntry>;
|
|
5182
5347
|
/**
|
|
5183
5348
|
* Adds a new asymmetric keypair to the vault. Storage-first: the private key
|
|
5184
5349
|
* is stored under a freshly-minted `id` before the public-key vault entry is
|
|
@@ -5364,7 +5529,7 @@ declare class KeyStore_2 implements IEncryptionProvider {
|
|
|
5364
5529
|
}
|
|
5365
5530
|
|
|
5366
5531
|
/**
|
|
5367
|
-
* Current format version constant. New vaults are written as `'keystore-
|
|
5532
|
+
* Current format version constant. New vaults are written as `'keystore-v3'`.
|
|
5368
5533
|
* @public
|
|
5369
5534
|
*/
|
|
5370
5535
|
declare const KEYSTORE_FORMAT: KeyStoreFormat;
|
|
@@ -5408,9 +5573,14 @@ declare const keystoreFile: Converter<IKeyStoreFile>;
|
|
|
5408
5573
|
* asymmetric-keypair entries. A strict superset of v1 — the field is
|
|
5409
5574
|
* optional, so a v2 reader opens a v1 vault with no special-casing, and a
|
|
5410
5575
|
* v1 vault opened and re-saved is silently upgraded to v2.
|
|
5576
|
+
* - `'keystore-v3'`: adds the `'opaque'` symmetric secret type and the optional
|
|
5577
|
+
* `metadata` / `updatedAt` fields on symmetric entries. A strict superset of
|
|
5578
|
+
* v1/v2 — the additions are optional (and `'opaque'` is simply a new enum
|
|
5579
|
+
* value), so a v3 reader opens a v1/v2 vault with no special-casing, and a
|
|
5580
|
+
* v1/v2 vault opened and re-saved is silently upgraded to v3.
|
|
5411
5581
|
* @public
|
|
5412
5582
|
*/
|
|
5413
|
-
declare type KeyStoreFormat = 'keystore-v1' | 'keystore-v2';
|
|
5583
|
+
declare type KeyStoreFormat = 'keystore-v1' | 'keystore-v2' | 'keystore-v3';
|
|
5414
5584
|
|
|
5415
5585
|
/**
|
|
5416
5586
|
* Converter for {@link CryptoUtils.KeyStore.KeyStoreFormat | key store format} version.
|
|
@@ -5468,13 +5638,17 @@ declare const keystoreSymmetricEntryJson: Converter<IKeyStoreSymmetricEntryJson>
|
|
|
5468
5638
|
* Discriminator for symmetric secret types stored in the vault.
|
|
5469
5639
|
* - `'encryption-key'`: A 32-byte AES-256 encryption key.
|
|
5470
5640
|
* - `'api-key'`: An arbitrary-length API key string (UTF-8 encoded).
|
|
5641
|
+
* - `'opaque'`: Arbitrary raw bytes with no encoding contract — stored and
|
|
5642
|
+
* returned verbatim (never UTF-8 decoded). Use for byte blobs that are
|
|
5643
|
+
* neither a fixed-size AES key nor a UTF-8 string (e.g. a serialized
|
|
5644
|
+
* credential bundle), so they are not mistyped as `'api-key'`.
|
|
5471
5645
|
* @public
|
|
5472
5646
|
*/
|
|
5473
|
-
declare type KeyStoreSymmetricSecretType = 'encryption-key' | 'api-key';
|
|
5647
|
+
declare type KeyStoreSymmetricSecretType = 'encryption-key' | 'api-key' | 'opaque';
|
|
5474
5648
|
|
|
5475
5649
|
/**
|
|
5476
5650
|
* Converter for {@link CryptoUtils.KeyStore.KeyStoreSymmetricSecretType | symmetric secret type} discriminator.
|
|
5477
|
-
* Accepts
|
|
5651
|
+
* Accepts `'encryption-key'`, `'api-key'`, and `'opaque'`.
|
|
5478
5652
|
* @public
|
|
5479
5653
|
*/
|
|
5480
5654
|
declare const keystoreSymmetricSecretType: Converter<KeyStoreSymmetricSecretType>;
|
|
@@ -6286,15 +6460,22 @@ declare type SecretProvider = (secretName: string) => Promise<Result<Uint8Array>
|
|
|
6286
6460
|
* derived *deterministically* from a fixed secret seed, for use with
|
|
6287
6461
|
* {@link CryptoUtils.ICryptoProvider.importKeyPairFromSeed | importKeyPairFromSeed}.
|
|
6288
6462
|
*
|
|
6289
|
-
*
|
|
6290
|
-
* seed and
|
|
6291
|
-
*
|
|
6292
|
-
*
|
|
6293
|
-
*
|
|
6294
|
-
* `'x25519'`
|
|
6463
|
+
* Two algorithms are supported, both of whose 32-byte private scalar *is* the
|
|
6464
|
+
* seed and whose public key is a deterministic function of it, so the same seed
|
|
6465
|
+
* always yields the same keypair on every runtime:
|
|
6466
|
+
* - `'ed25519'` — signing keypair (RFC 8032). Private usage `'sign'`, public
|
|
6467
|
+
* usage `'verify'`.
|
|
6468
|
+
* - `'x25519'` — Diffie-Hellman key-agreement keypair (RFC 7748), the recipient
|
|
6469
|
+
* keypair consumed by {@link CryptoUtils.HpkeProvider}. Private usage
|
|
6470
|
+
* `'deriveBits'`, public key imported with no usages. Deriving a fixed X25519
|
|
6471
|
+
* recipient keypair from a checked-in seed is what makes a deterministic HPKE
|
|
6472
|
+
* seal/open round-trip vector possible.
|
|
6473
|
+
*
|
|
6474
|
+
* The type is a proper subset of {@link CryptoUtils.KeyPairAlgorithm} because
|
|
6475
|
+
* algorithms like RSA or the NIST curves are not recoverable from a bare seed.
|
|
6295
6476
|
* @public
|
|
6296
6477
|
*/
|
|
6297
|
-
declare type SeedDerivableAlgorithm = 'ed25519';
|
|
6478
|
+
declare type SeedDerivableAlgorithm = 'ed25519' | 'x25519';
|
|
6298
6479
|
|
|
6299
6480
|
/**
|
|
6300
6481
|
* Default system-prompt suffix appended when {@link AiAssist.IGenerateJsonCompletionParams.promptHint}
|
|
@@ -13,6 +13,6 @@ export { DirectEncryptionProvider, IDirectEncryptionProviderParams } from './dir
|
|
|
13
13
|
export { IKeyPairAlgorithmParams, keyPairAlgorithmParams } from './keyPairAlgorithmParams';
|
|
14
14
|
export { deriveKeyPairFromSeed } from './seedDerivedKeyPair';
|
|
15
15
|
export { createEncryptedFile, decryptFile, fromBase64, ICreateEncryptedFileParams, toBase64, tryDecryptFile } from './encryptedFile';
|
|
16
|
-
export { base64UrlNoPadDecode, base64UrlNoPadEncode, exportPublicKeyAsMultibaseSpki, importPublicKeyFromMultibaseSpki, isValidMultibaseSpkiPublicKey, MultibaseSpkiPublicKeyRegExp, multibaseBase64UrlDecode, multibaseBase64UrlEncode, spkiToRawX25519 } from './spkiHelpers';
|
|
16
|
+
export { base64UrlNoPadDecode, base64UrlNoPadEncode, exportPublicKeyAsMultibaseSpki, hexDecode, hexEncode, importPublicKeyFromMultibaseSpki, isValidMultibaseSpkiPublicKey, MultibaseSpkiPublicKeyRegExp, multibaseBase64UrlDecode, multibaseBase64UrlEncode, spkiToRawX25519 } from './spkiHelpers';
|
|
17
17
|
export { HpkeProvider, IHpkeSealResult } from './hpkeProvider';
|
|
18
18
|
//# sourceMappingURL=index.browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/index.browser.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,WAAW,EACZ,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,QAAQ,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,CAAC;AAGpB,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,CAAC;AAGtB,OAAO,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAGvG,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAI3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAM7D,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,0BAA0B,EAC1B,QAAQ,EACR,cAAc,EACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,8BAA8B,EAC9B,gCAAgC,EAChC,6BAA6B,EAC7B,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EAChB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/index.browser.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,WAAW,EACZ,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,QAAQ,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,CAAC;AAGpB,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,CAAC;AAGtB,OAAO,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAGvG,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAI3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAM7D,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,0BAA0B,EAC1B,QAAQ,EACR,cAAc,EACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,8BAA8B,EAC9B,SAAS,EACT,SAAS,EACT,gCAAgC,EAChC,6BAA6B,EAC7B,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EAChB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -55,7 +55,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
55
55
|
};
|
|
56
56
|
})();
|
|
57
57
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
|
-
exports.HpkeProvider = exports.spkiToRawX25519 = exports.multibaseBase64UrlEncode = exports.multibaseBase64UrlDecode = exports.MultibaseSpkiPublicKeyRegExp = exports.isValidMultibaseSpkiPublicKey = exports.importPublicKeyFromMultibaseSpki = exports.exportPublicKeyAsMultibaseSpki = exports.base64UrlNoPadEncode = exports.base64UrlNoPadDecode = exports.tryDecryptFile = exports.toBase64 = exports.fromBase64 = exports.decryptFile = exports.createEncryptedFile = exports.deriveKeyPairFromSeed = exports.keyPairAlgorithmParams = exports.DirectEncryptionProvider = exports.Converters = exports.KeyStore = exports.GCM_IV_SIZE = exports.GCM_AUTH_TAG_SIZE = exports.ENCRYPTED_FILE_FORMAT = exports.DEFAULT_ALGORITHM = exports.AES_256_KEY_SIZE = void 0;
|
|
58
|
+
exports.HpkeProvider = exports.spkiToRawX25519 = exports.multibaseBase64UrlEncode = exports.multibaseBase64UrlDecode = exports.MultibaseSpkiPublicKeyRegExp = exports.isValidMultibaseSpkiPublicKey = exports.importPublicKeyFromMultibaseSpki = exports.hexEncode = exports.hexDecode = exports.exportPublicKeyAsMultibaseSpki = exports.base64UrlNoPadEncode = exports.base64UrlNoPadDecode = exports.tryDecryptFile = exports.toBase64 = exports.fromBase64 = exports.decryptFile = exports.createEncryptedFile = exports.deriveKeyPairFromSeed = exports.keyPairAlgorithmParams = exports.DirectEncryptionProvider = exports.Converters = exports.KeyStore = exports.GCM_IV_SIZE = exports.GCM_AUTH_TAG_SIZE = exports.ENCRYPTED_FILE_FORMAT = exports.DEFAULT_ALGORITHM = exports.AES_256_KEY_SIZE = void 0;
|
|
59
59
|
/**
|
|
60
60
|
* Crypto utilities for encrypted file handling and key management (browser version).
|
|
61
61
|
* Note: For browser crypto provider, use \@fgv/ts-web-extras.
|
|
@@ -101,6 +101,8 @@ var spkiHelpers_1 = require("./spkiHelpers");
|
|
|
101
101
|
Object.defineProperty(exports, "base64UrlNoPadDecode", { enumerable: true, get: function () { return spkiHelpers_1.base64UrlNoPadDecode; } });
|
|
102
102
|
Object.defineProperty(exports, "base64UrlNoPadEncode", { enumerable: true, get: function () { return spkiHelpers_1.base64UrlNoPadEncode; } });
|
|
103
103
|
Object.defineProperty(exports, "exportPublicKeyAsMultibaseSpki", { enumerable: true, get: function () { return spkiHelpers_1.exportPublicKeyAsMultibaseSpki; } });
|
|
104
|
+
Object.defineProperty(exports, "hexDecode", { enumerable: true, get: function () { return spkiHelpers_1.hexDecode; } });
|
|
105
|
+
Object.defineProperty(exports, "hexEncode", { enumerable: true, get: function () { return spkiHelpers_1.hexEncode; } });
|
|
104
106
|
Object.defineProperty(exports, "importPublicKeyFromMultibaseSpki", { enumerable: true, get: function () { return spkiHelpers_1.importPublicKeyFromMultibaseSpki; } });
|
|
105
107
|
Object.defineProperty(exports, "isValidMultibaseSpkiPublicKey", { enumerable: true, get: function () { return spkiHelpers_1.isValidMultibaseSpkiPublicKey; } });
|
|
106
108
|
Object.defineProperty(exports, "MultibaseSpkiPublicKeyRegExp", { enumerable: true, get: function () { return spkiHelpers_1.MultibaseSpkiPublicKeyRegExp; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/index.browser.ts"],"names":[],"mappings":";AAAA,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AACxE,2DAA2D;AAC3D,EAAE;AACF,iFAAiF;AACjF,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,gFAAgF;AAChF,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEZ;;;;GAIG;AAEH,iCAAiC;AACjC,0CAAwB;AAExB,YAAY;AACZ,yCAMqB;AALnB,6GAAA,gBAAgB,OAAA;AAChB,8GAAA,iBAAiB,OAAA;AACjB,kHAAA,qBAAqB,OAAA;AACrB,8GAAA,iBAAiB,OAAA;AACjB,wGAAA,WAAW,OAAA;AAGb,gEAAgE;AAChE,iFAAiF;AACjF,mEAAqD;AAC5C,4BAAQ;AAEjB,uBAAuB;AACvB,yDAA2C;AAClC,gCAAU;AAEnB,6BAA6B;AAC7B,uEAAuG;AAA9F,oIAAA,wBAAwB,OAAA;AAEjC,8DAA8D;AAC9D,mEAA2F;AAAzD,gIAAA,sBAAsB,OAAA;AAExD,+EAA+E;AAC/E,oFAAoF;AACpF,2DAA6D;AAApD,2HAAA,qBAAqB,OAAA;AAE9B,8DAA8D;AAC9D,4DAA4D;AAE5D,yBAAyB;AACzB,iDAOyB;AANvB,oHAAA,mBAAmB,OAAA;AACnB,4GAAA,WAAW,OAAA;AACX,2GAAA,UAAU,OAAA;AAEV,yGAAA,QAAQ,OAAA;AACR,+GAAA,cAAc,OAAA;AAGhB,qCAAqC;AACrC,
|
|
1
|
+
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/index.browser.ts"],"names":[],"mappings":";AAAA,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AACxE,2DAA2D;AAC3D,EAAE;AACF,iFAAiF;AACjF,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,gFAAgF;AAChF,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEZ;;;;GAIG;AAEH,iCAAiC;AACjC,0CAAwB;AAExB,YAAY;AACZ,yCAMqB;AALnB,6GAAA,gBAAgB,OAAA;AAChB,8GAAA,iBAAiB,OAAA;AACjB,kHAAA,qBAAqB,OAAA;AACrB,8GAAA,iBAAiB,OAAA;AACjB,wGAAA,WAAW,OAAA;AAGb,gEAAgE;AAChE,iFAAiF;AACjF,mEAAqD;AAC5C,4BAAQ;AAEjB,uBAAuB;AACvB,yDAA2C;AAClC,gCAAU;AAEnB,6BAA6B;AAC7B,uEAAuG;AAA9F,oIAAA,wBAAwB,OAAA;AAEjC,8DAA8D;AAC9D,mEAA2F;AAAzD,gIAAA,sBAAsB,OAAA;AAExD,+EAA+E;AAC/E,oFAAoF;AACpF,2DAA6D;AAApD,2HAAA,qBAAqB,OAAA;AAE9B,8DAA8D;AAC9D,4DAA4D;AAE5D,yBAAyB;AACzB,iDAOyB;AANvB,oHAAA,mBAAmB,OAAA;AACnB,4GAAA,WAAW,OAAA;AACX,2GAAA,UAAU,OAAA;AAEV,yGAAA,QAAQ,OAAA;AACR,+GAAA,cAAc,OAAA;AAGhB,qCAAqC;AACrC,6CAYuB;AAXrB,mHAAA,oBAAoB,OAAA;AACpB,mHAAA,oBAAoB,OAAA;AACpB,6HAAA,8BAA8B,OAAA;AAC9B,wGAAA,SAAS,OAAA;AACT,wGAAA,SAAS,OAAA;AACT,+HAAA,gCAAgC,OAAA;AAChC,4HAAA,6BAA6B,OAAA;AAC7B,2HAAA,4BAA4B,OAAA;AAC5B,uHAAA,wBAAwB,OAAA;AACxB,uHAAA,wBAAwB,OAAA;AACxB,8GAAA,eAAe,OAAA;AAGjB,qFAAqF;AACrF,uFAAuF;AACvF,+CAA+D;AAAtD,4GAAA,YAAY,OAAA","sourcesContent":["// Copyright (c) 2024 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Crypto utilities for encrypted file handling and key management (browser version).\n * Note: For browser crypto provider, use \\@fgv/ts-web-extras.\n * @packageDocumentation\n */\n\n// Re-export all types from model\nexport * from './model';\n\n// Constants\nexport {\n AES_256_KEY_SIZE,\n DEFAULT_ALGORITHM,\n ENCRYPTED_FILE_FORMAT,\n GCM_AUTH_TAG_SIZE,\n GCM_IV_SIZE\n} from './constants';\n\n// KeyStore namespace (browser-safe barrel — omits the Node-only\n// EncryptedFilePrivateKeyStorage so the browser entry stays free of node:crypto)\nimport * as KeyStore from './keystore/index.browser';\nexport { KeyStore };\n\n// Converters namespace\nimport * as Converters from './converters';\nexport { Converters };\n\n// Direct encryption provider\nexport { DirectEncryptionProvider, IDirectEncryptionProviderParams } from './directEncryptionProvider';\n\n// WebCrypto parameter table for asymmetric keypair algorithms\nexport { IKeyPairAlgorithmParams, keyPairAlgorithmParams } from './keyPairAlgorithmParams';\n\n// Deterministic seed → keypair derivation shared by the Node/browser providers\n// (globalThis.crypto.subtle only — no node:crypto, safe in the browser entry point)\nexport { deriveKeyPairFromSeed } from './seedDerivedKeyPair';\n\n// Note: NodeCryptoProvider is NOT exported in browser version\n// Use BrowserCryptoProvider from @fgv/ts-web-extras instead\n\n// Encrypted file helpers\nexport {\n createEncryptedFile,\n decryptFile,\n fromBase64,\n ICreateEncryptedFileParams,\n toBase64,\n tryDecryptFile\n} from './encryptedFile';\n\n// Multibase/SPKI + base64url helpers\nexport {\n base64UrlNoPadDecode,\n base64UrlNoPadEncode,\n exportPublicKeyAsMultibaseSpki,\n hexDecode,\n hexEncode,\n importPublicKeyFromMultibaseSpki,\n isValidMultibaseSpkiPublicKey,\n MultibaseSpkiPublicKeyRegExp,\n multibaseBase64UrlDecode,\n multibaseBase64UrlEncode,\n spkiToRawX25519\n} from './spkiHelpers';\n\n// HPKE base mode (RFC 9180) — DHKEM(X25519, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM\n// hpkeProvider.ts has no Node-specific imports and is safe in the browser entry point.\nexport { HpkeProvider, IHpkeSealResult } from './hpkeProvider';\n"]}
|
|
@@ -14,6 +14,6 @@ export { IKeyPairAlgorithmParams, keyPairAlgorithmParams } from './keyPairAlgori
|
|
|
14
14
|
export { deriveKeyPairFromSeed } from './seedDerivedKeyPair';
|
|
15
15
|
export { NodeCryptoProvider, nodeCryptoProvider } from './nodeCryptoProvider';
|
|
16
16
|
export { createEncryptedFile, decryptFile, fromBase64, ICreateEncryptedFileParams, toBase64, tryDecryptFile } from './encryptedFile';
|
|
17
|
-
export { base64UrlNoPadDecode, base64UrlNoPadEncode, exportPublicKeyAsMultibaseSpki, importPublicKeyFromMultibaseSpki, isValidMultibaseSpkiPublicKey, MultibaseSpkiPublicKeyRegExp, multibaseBase64UrlDecode, multibaseBase64UrlEncode, spkiToRawX25519 } from './spkiHelpers';
|
|
17
|
+
export { base64UrlNoPadDecode, base64UrlNoPadEncode, exportPublicKeyAsMultibaseSpki, hexDecode, hexEncode, importPublicKeyFromMultibaseSpki, isValidMultibaseSpkiPublicKey, MultibaseSpkiPublicKeyRegExp, multibaseBase64UrlDecode, multibaseBase64UrlEncode, spkiToRawX25519 } from './spkiHelpers';
|
|
18
18
|
export { HpkeProvider, IHpkeSealResult } from './hpkeProvider';
|
|
19
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/index.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,KAAK,SAAS,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,CAAC;AAGrB,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,CAAC;AAGpB,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,CAAC;AAGtB,OAAO,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAGvG,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAG3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,0BAA0B,EAC1B,QAAQ,EACR,cAAc,EACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,8BAA8B,EAC9B,gCAAgC,EAChC,6BAA6B,EAC7B,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/index.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,KAAK,SAAS,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,CAAC;AAGrB,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,CAAC;AAGpB,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,CAAC;AAGtB,OAAO,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAGvG,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAG3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,0BAA0B,EAC1B,QAAQ,EACR,cAAc,EACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,8BAA8B,EAC9B,SAAS,EACT,SAAS,EACT,gCAAgC,EAChC,6BAA6B,EAC7B,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -55,7 +55,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
55
55
|
};
|
|
56
56
|
})();
|
|
57
57
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
|
-
exports.HpkeProvider = exports.spkiToRawX25519 = exports.multibaseBase64UrlEncode = exports.multibaseBase64UrlDecode = exports.MultibaseSpkiPublicKeyRegExp = exports.isValidMultibaseSpkiPublicKey = exports.importPublicKeyFromMultibaseSpki = exports.exportPublicKeyAsMultibaseSpki = exports.base64UrlNoPadEncode = exports.base64UrlNoPadDecode = exports.tryDecryptFile = exports.toBase64 = exports.fromBase64 = exports.decryptFile = exports.createEncryptedFile = exports.nodeCryptoProvider = exports.NodeCryptoProvider = exports.deriveKeyPairFromSeed = exports.keyPairAlgorithmParams = exports.DirectEncryptionProvider = exports.Converters = exports.KeyStore = exports.Constants = void 0;
|
|
58
|
+
exports.HpkeProvider = exports.spkiToRawX25519 = exports.multibaseBase64UrlEncode = exports.multibaseBase64UrlDecode = exports.MultibaseSpkiPublicKeyRegExp = exports.isValidMultibaseSpkiPublicKey = exports.importPublicKeyFromMultibaseSpki = exports.hexEncode = exports.hexDecode = exports.exportPublicKeyAsMultibaseSpki = exports.base64UrlNoPadEncode = exports.base64UrlNoPadDecode = exports.tryDecryptFile = exports.toBase64 = exports.fromBase64 = exports.decryptFile = exports.createEncryptedFile = exports.nodeCryptoProvider = exports.NodeCryptoProvider = exports.deriveKeyPairFromSeed = exports.keyPairAlgorithmParams = exports.DirectEncryptionProvider = exports.Converters = exports.KeyStore = exports.Constants = void 0;
|
|
59
59
|
/**
|
|
60
60
|
* Crypto utilities for encrypted file handling and key management.
|
|
61
61
|
* @packageDocumentation
|
|
@@ -96,6 +96,8 @@ var spkiHelpers_1 = require("./spkiHelpers");
|
|
|
96
96
|
Object.defineProperty(exports, "base64UrlNoPadDecode", { enumerable: true, get: function () { return spkiHelpers_1.base64UrlNoPadDecode; } });
|
|
97
97
|
Object.defineProperty(exports, "base64UrlNoPadEncode", { enumerable: true, get: function () { return spkiHelpers_1.base64UrlNoPadEncode; } });
|
|
98
98
|
Object.defineProperty(exports, "exportPublicKeyAsMultibaseSpki", { enumerable: true, get: function () { return spkiHelpers_1.exportPublicKeyAsMultibaseSpki; } });
|
|
99
|
+
Object.defineProperty(exports, "hexDecode", { enumerable: true, get: function () { return spkiHelpers_1.hexDecode; } });
|
|
100
|
+
Object.defineProperty(exports, "hexEncode", { enumerable: true, get: function () { return spkiHelpers_1.hexEncode; } });
|
|
99
101
|
Object.defineProperty(exports, "importPublicKeyFromMultibaseSpki", { enumerable: true, get: function () { return spkiHelpers_1.importPublicKeyFromMultibaseSpki; } });
|
|
100
102
|
Object.defineProperty(exports, "isValidMultibaseSpkiPublicKey", { enumerable: true, get: function () { return spkiHelpers_1.isValidMultibaseSpkiPublicKey; } });
|
|
101
103
|
Object.defineProperty(exports, "MultibaseSpkiPublicKeyRegExp", { enumerable: true, get: function () { return spkiHelpers_1.MultibaseSpkiPublicKeyRegExp; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/index.ts"],"names":[],"mappings":";AAAA,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AACxE,2DAA2D;AAC3D,EAAE;AACF,iFAAiF;AACjF,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,gFAAgF;AAChF,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEZ;;;GAGG;AAEH,iCAAiC;AACjC,0CAAwB;AAExB,YAAY;AACZ,uDAAyC;AAChC,8BAAS;AAElB,qBAAqB;AACrB,qDAAuC;AAC9B,4BAAQ;AAEjB,uBAAuB;AACvB,yDAA2C;AAClC,gCAAU;AAEnB,6BAA6B;AAC7B,uEAAuG;AAA9F,oIAAA,wBAAwB,OAAA;AAEjC,8DAA8D;AAC9D,mEAA2F;AAAzD,gIAAA,sBAAsB,OAAA;AAExD,+EAA+E;AAC/E,2DAA6D;AAApD,2HAAA,qBAAqB,OAAA;AAE9B,qDAAqD;AACrD,2DAA8E;AAArE,wHAAA,kBAAkB,OAAA;AAAE,wHAAA,kBAAkB,OAAA;AAE/C,yBAAyB;AACzB,iDAOyB;AANvB,oHAAA,mBAAmB,OAAA;AACnB,4GAAA,WAAW,OAAA;AACX,2GAAA,UAAU,OAAA;AAEV,yGAAA,QAAQ,OAAA;AACR,+GAAA,cAAc,OAAA;AAGhB,qCAAqC;AACrC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/crypto-utils/index.ts"],"names":[],"mappings":";AAAA,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AACxE,2DAA2D;AAC3D,EAAE;AACF,iFAAiF;AACjF,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,gFAAgF;AAChF,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEZ;;;GAGG;AAEH,iCAAiC;AACjC,0CAAwB;AAExB,YAAY;AACZ,uDAAyC;AAChC,8BAAS;AAElB,qBAAqB;AACrB,qDAAuC;AAC9B,4BAAQ;AAEjB,uBAAuB;AACvB,yDAA2C;AAClC,gCAAU;AAEnB,6BAA6B;AAC7B,uEAAuG;AAA9F,oIAAA,wBAAwB,OAAA;AAEjC,8DAA8D;AAC9D,mEAA2F;AAAzD,gIAAA,sBAAsB,OAAA;AAExD,+EAA+E;AAC/E,2DAA6D;AAApD,2HAAA,qBAAqB,OAAA;AAE9B,qDAAqD;AACrD,2DAA8E;AAArE,wHAAA,kBAAkB,OAAA;AAAE,wHAAA,kBAAkB,OAAA;AAE/C,yBAAyB;AACzB,iDAOyB;AANvB,oHAAA,mBAAmB,OAAA;AACnB,4GAAA,WAAW,OAAA;AACX,2GAAA,UAAU,OAAA;AAEV,yGAAA,QAAQ,OAAA;AACR,+GAAA,cAAc,OAAA;AAGhB,qCAAqC;AACrC,6CAYuB;AAXrB,mHAAA,oBAAoB,OAAA;AACpB,mHAAA,oBAAoB,OAAA;AACpB,6HAAA,8BAA8B,OAAA;AAC9B,wGAAA,SAAS,OAAA;AACT,wGAAA,SAAS,OAAA;AACT,+HAAA,gCAAgC,OAAA;AAChC,4HAAA,6BAA6B,OAAA;AAC7B,2HAAA,4BAA4B,OAAA;AAC5B,uHAAA,wBAAwB,OAAA;AACxB,uHAAA,wBAAwB,OAAA;AACxB,8GAAA,eAAe,OAAA;AAGjB,qFAAqF;AACrF,+CAA+D;AAAtD,4GAAA,YAAY,OAAA","sourcesContent":["// Copyright (c) 2024 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Crypto utilities for encrypted file handling and key management.\n * @packageDocumentation\n */\n\n// Re-export all types from model\nexport * from './model';\n\n// Constants\nimport * as Constants from './constants';\nexport { Constants };\n\n// KeyStore namespace\nimport * as KeyStore from './keystore';\nexport { KeyStore };\n\n// Converters namespace\nimport * as Converters from './converters';\nexport { Converters };\n\n// Direct encryption provider\nexport { DirectEncryptionProvider, IDirectEncryptionProviderParams } from './directEncryptionProvider';\n\n// WebCrypto parameter table for asymmetric keypair algorithms\nexport { IKeyPairAlgorithmParams, keyPairAlgorithmParams } from './keyPairAlgorithmParams';\n\n// Deterministic seed → keypair derivation shared by the Node/browser providers\nexport { deriveKeyPairFromSeed } from './seedDerivedKeyPair';\n\n// Node.js crypto provider (Node.js environment only)\nexport { NodeCryptoProvider, nodeCryptoProvider } from './nodeCryptoProvider';\n\n// Encrypted file helpers\nexport {\n createEncryptedFile,\n decryptFile,\n fromBase64,\n ICreateEncryptedFileParams,\n toBase64,\n tryDecryptFile\n} from './encryptedFile';\n\n// Multibase/SPKI + base64url helpers\nexport {\n base64UrlNoPadDecode,\n base64UrlNoPadEncode,\n exportPublicKeyAsMultibaseSpki,\n hexDecode,\n hexEncode,\n importPublicKeyFromMultibaseSpki,\n isValidMultibaseSpkiPublicKey,\n MultibaseSpkiPublicKeyRegExp,\n multibaseBase64UrlDecode,\n multibaseBase64UrlEncode,\n spkiToRawX25519\n} from './spkiHelpers';\n\n// HPKE base mode (RFC 9180) — DHKEM(X25519, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM\nexport { HpkeProvider, IHpkeSealResult } from './hpkeProvider';\n"]}
|
|
@@ -13,7 +13,7 @@ export declare const keystoreFormat: Converter<KeyStoreFormat>;
|
|
|
13
13
|
export declare const keystoreSecretType: Converter<KeyStoreSecretType>;
|
|
14
14
|
/**
|
|
15
15
|
* Converter for {@link CryptoUtils.KeyStore.KeyStoreSymmetricSecretType | symmetric secret type} discriminator.
|
|
16
|
-
* Accepts
|
|
16
|
+
* Accepts `'encryption-key'`, `'api-key'`, and `'opaque'`.
|
|
17
17
|
* @public
|
|
18
18
|
*/
|
|
19
19
|
export declare const keystoreSymmetricSecretType: Converter<KeyStoreSymmetricSecretType>;
|