@msdis/shield 0.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/LICENSE +140 -0
- package/README.md +106 -0
- package/dist/aead/index.d.ts +37 -0
- package/dist/aead/index.js +7 -0
- package/dist/aead/index.js.map +1 -0
- package/dist/asymmetric/index.d.ts +32 -0
- package/dist/asymmetric/index.js +6 -0
- package/dist/asymmetric/index.js.map +1 -0
- package/dist/chunk-3DQPQCAR.js +114 -0
- package/dist/chunk-3DQPQCAR.js.map +1 -0
- package/dist/chunk-3HCT6A2P.js +55 -0
- package/dist/chunk-3HCT6A2P.js.map +1 -0
- package/dist/chunk-AB2WZ7Y2.js +57 -0
- package/dist/chunk-AB2WZ7Y2.js.map +1 -0
- package/dist/chunk-BUFRR5PB.js +9 -0
- package/dist/chunk-BUFRR5PB.js.map +1 -0
- package/dist/chunk-CYIGDF63.js +30 -0
- package/dist/chunk-CYIGDF63.js.map +1 -0
- package/dist/chunk-EOXWR7DS.js +153 -0
- package/dist/chunk-EOXWR7DS.js.map +1 -0
- package/dist/chunk-FUDDBD2G.js +43 -0
- package/dist/chunk-FUDDBD2G.js.map +1 -0
- package/dist/chunk-JSKIWIEC.js +56 -0
- package/dist/chunk-JSKIWIEC.js.map +1 -0
- package/dist/chunk-JVFP2GAO.js +66 -0
- package/dist/chunk-JVFP2GAO.js.map +1 -0
- package/dist/chunk-KNCZMIZA.js +55 -0
- package/dist/chunk-KNCZMIZA.js.map +1 -0
- package/dist/chunk-MJO7IJZC.js +44 -0
- package/dist/chunk-MJO7IJZC.js.map +1 -0
- package/dist/chunk-MPWYZXW7.js +66 -0
- package/dist/chunk-MPWYZXW7.js.map +1 -0
- package/dist/chunk-OA5ARYJM.js +73 -0
- package/dist/chunk-OA5ARYJM.js.map +1 -0
- package/dist/chunk-OPHN2B3N.js +147 -0
- package/dist/chunk-OPHN2B3N.js.map +1 -0
- package/dist/chunk-RTAJJZKO.js +116 -0
- package/dist/chunk-RTAJJZKO.js.map +1 -0
- package/dist/chunk-SCHZI6YY.js +35 -0
- package/dist/chunk-SCHZI6YY.js.map +1 -0
- package/dist/chunk-T3IV7SHD.js +388 -0
- package/dist/chunk-T3IV7SHD.js.map +1 -0
- package/dist/chunk-U65A4HIY.js +133 -0
- package/dist/chunk-U65A4HIY.js.map +1 -0
- package/dist/core/index.d.ts +20 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/encoding-B-cb7Duu.d.ts +37 -0
- package/dist/errors-C79jA9vX.d.ts +65 -0
- package/dist/file-encryption/index.d.ts +135 -0
- package/dist/file-encryption/index.js +11 -0
- package/dist/file-encryption/index.js.map +1 -0
- package/dist/format-versioning/index.d.ts +37 -0
- package/dist/format-versioning/index.js +4 -0
- package/dist/format-versioning/index.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/integrity/index.d.ts +46 -0
- package/dist/integrity/index.js +6 -0
- package/dist/integrity/index.js.map +1 -0
- package/dist/kdf/index.d.ts +104 -0
- package/dist/kdf/index.js +7 -0
- package/dist/kdf/index.js.map +1 -0
- package/dist/key-management/index.d.ts +69 -0
- package/dist/key-management/index.js +10 -0
- package/dist/key-management/index.js.map +1 -0
- package/dist/migrations/index.d.ts +41 -0
- package/dist/migrations/index.js +4 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/post-quantum/index.d.ts +153 -0
- package/dist/post-quantum/index.js +3 -0
- package/dist/post-quantum/index.js.map +1 -0
- package/dist/random/index.d.ts +28 -0
- package/dist/random/index.js +5 -0
- package/dist/random/index.js.map +1 -0
- package/dist/secure-memory/index.d.ts +40 -0
- package/dist/secure-memory/index.js +5 -0
- package/dist/secure-memory/index.js.map +1 -0
- package/dist/signing/index.d.ts +41 -0
- package/dist/signing/index.js +5 -0
- package/dist/signing/index.js.map +1 -0
- package/dist/totp/index.d.ts +69 -0
- package/dist/totp/index.js +4 -0
- package/dist/totp/index.js.map +1 -0
- package/dist/vault-crypto/index.d.ts +225 -0
- package/dist/vault-crypto/index.js +465 -0
- package/dist/vault-crypto/index.js.map +1 -0
- package/dist/vault-encryption/index.d.ts +40 -0
- package/dist/vault-encryption/index.js +9 -0
- package/dist/vault-encryption/index.js.map +1 -0
- package/package.json +137 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dis-migrations — explicit, ordered transformation of encrypted payloads.
|
|
3
|
+
*
|
|
4
|
+
* Migrations are registered against a (subject, fromVersion) key and run in a
|
|
5
|
+
* deterministic order. This gives applications a single, testable place to
|
|
6
|
+
* evolve formats (e.g. re-wrap legacy no-AAD vault items, bump KDF parameters,
|
|
7
|
+
* re-encrypt under a new cipher) without scattering ad-hoc upgrade code.
|
|
8
|
+
*
|
|
9
|
+
* DIS provides the framework and the crypto; the application decides which
|
|
10
|
+
* migrations to register and how persistence happens.
|
|
11
|
+
*/
|
|
12
|
+
/** Context passed to a migration step. `key` material is caller-supplied. */
|
|
13
|
+
interface MigrationContext {
|
|
14
|
+
readonly key: CryptoKey;
|
|
15
|
+
/** Stable identifier the payload is bound to (e.g. entry id). */
|
|
16
|
+
readonly bindingId?: string;
|
|
17
|
+
}
|
|
18
|
+
/** A single migration: transforms a payload from `fromVersion` to `toVersion`. */
|
|
19
|
+
interface Migration {
|
|
20
|
+
readonly subject: string;
|
|
21
|
+
readonly fromVersion: number | 'legacy';
|
|
22
|
+
readonly toVersion: number;
|
|
23
|
+
/** Returns the migrated payload string. Must be idempotent on its output. */
|
|
24
|
+
migrate(payload: string, context: MigrationContext): Promise<string>;
|
|
25
|
+
}
|
|
26
|
+
/** Detects the current version of a payload for a subject. */
|
|
27
|
+
type VersionDetector = (payload: string) => number | 'legacy';
|
|
28
|
+
/** An ordered registry of migrations for one or more subjects. */
|
|
29
|
+
declare class MigrationRegistry {
|
|
30
|
+
private readonly migrations;
|
|
31
|
+
private keyOf;
|
|
32
|
+
/** Registers a migration. Throws if one already exists for the same step. */
|
|
33
|
+
register(migration: Migration): this;
|
|
34
|
+
/**
|
|
35
|
+
* Applies all applicable migrations in sequence until no further migration
|
|
36
|
+
* exists for the payload's detected version. Guards against cycles.
|
|
37
|
+
*/
|
|
38
|
+
migrateToLatest(subject: string, payload: string, detect: VersionDetector, context: MigrationContext): Promise<string>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { type Migration, type MigrationContext, MigrationRegistry, type VersionDetector };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DIS — Defensive Integration Shield · post-quantum hybrid key wrapping.
|
|
3
|
+
* Powered by DIS — Defensive Integration Shield.
|
|
4
|
+
*
|
|
5
|
+
* Hybrid key wrapping combining:
|
|
6
|
+
* - ML-KEM-768 (FIPS 203) for post-quantum key encapsulation
|
|
7
|
+
* - RSA-4096-OAEP for classical encryption
|
|
8
|
+
*
|
|
9
|
+
* In the product threat model this protects sharing and emergency-access
|
|
10
|
+
* keys against "harvest now, decrypt later" attacks. It is NOT the encryption
|
|
11
|
+
* layer for vault item payloads, which remain AES-256-GCM encrypted with
|
|
12
|
+
* user-derived symmetric keys (see `@dis/shield/vault-encryption`).
|
|
13
|
+
*
|
|
14
|
+
* Wire format is preserved byte-for-byte from the legacy Singra implementation:
|
|
15
|
+
* version(1) || pq_ct(1088) || rsa_ct(512) || iv(12) || aes_ct(variable)
|
|
16
|
+
* with version bytes 0x01 (RSA-only), 0x02 (legacy hybrid), 0x03 (HKDF-v1),
|
|
17
|
+
* 0x04 (HKDF-v2, current). Changing any constant below breaks decryption of
|
|
18
|
+
* already-stored sharing/emergency keys — treat as a hard compatibility gate.
|
|
19
|
+
*
|
|
20
|
+
* @see https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Product-wide security standard version. Centralized so all hybrid/PQ
|
|
24
|
+
* sharing-key provisioning and runtime enforcement paths stay in sync.
|
|
25
|
+
*/
|
|
26
|
+
declare const SECURITY_STANDARD_VERSION = 1;
|
|
27
|
+
/** Current hybrid ciphertext version (v2 HKDF construction) */
|
|
28
|
+
declare const HYBRID_VERSION = 4;
|
|
29
|
+
interface SharedKeyWrapAadInput {
|
|
30
|
+
collectionId: string;
|
|
31
|
+
senderUserId: string;
|
|
32
|
+
recipientUserId: string;
|
|
33
|
+
keyVersion: string | number;
|
|
34
|
+
}
|
|
35
|
+
declare function buildSharedKeyWrapAad(input: SharedKeyWrapAadInput): string;
|
|
36
|
+
/**
|
|
37
|
+
* Generates a new ML-KEM-768 key pair.
|
|
38
|
+
*
|
|
39
|
+
* @returns Object with base64-encoded public and secret keys
|
|
40
|
+
*/
|
|
41
|
+
declare function generatePQKeyPair(): PQKeyPair;
|
|
42
|
+
/**
|
|
43
|
+
* Generates a hybrid key pair combining ML-KEM-768 and RSA-4096.
|
|
44
|
+
*
|
|
45
|
+
* @returns Object with both PQ and RSA keys
|
|
46
|
+
*/
|
|
47
|
+
declare function generateHybridKeyPair(): Promise<HybridKeyPair>;
|
|
48
|
+
/**
|
|
49
|
+
* Encrypts key material using hybrid ML-KEM-768 + RSA-4096-OAEP encryption.
|
|
50
|
+
*
|
|
51
|
+
* The supplied key material is encrypted with a randomly generated AES-256 key.
|
|
52
|
+
* This AES key is then encapsulated/encrypted with both:
|
|
53
|
+
* 1. ML-KEM-768 (post-quantum KEM)
|
|
54
|
+
* 2. RSA-4096-OAEP (classically secure)
|
|
55
|
+
*
|
|
56
|
+
* Format: version(1) || pq_ciphertext(1088) || rsa_ciphertext(512) || iv(12) || aes_ciphertext(variable)
|
|
57
|
+
*
|
|
58
|
+
* @param plaintext - Serialized key material to wrap
|
|
59
|
+
* @param pqPublicKey - Base64-encoded ML-KEM-768 public key
|
|
60
|
+
* @param rsaPublicKey - JWK string of RSA-4096 public key
|
|
61
|
+
* @param aad - Optional additional authenticated data for AES-GCM context binding
|
|
62
|
+
* @returns Base64-encoded hybrid ciphertext
|
|
63
|
+
*/
|
|
64
|
+
declare function hybridEncrypt(plaintext: string, pqPublicKey: string, rsaPublicKey: string, aad?: string): Promise<string>;
|
|
65
|
+
/**
|
|
66
|
+
* Decrypts hybrid ML-KEM-768 + RSA-4096-OAEP wrapped key material.
|
|
67
|
+
*
|
|
68
|
+
* @param ciphertextBase64 - Base64-encoded hybrid ciphertext
|
|
69
|
+
* @param pqSecretKey - Base64-encoded ML-KEM-768 secret key
|
|
70
|
+
* @param rsaPrivateKey - JWK string of RSA-4096 private key
|
|
71
|
+
* @param aad - Optional additional authenticated data (must match encrypt-time AAD)
|
|
72
|
+
* @returns Decrypted plaintext
|
|
73
|
+
* @throws Error if decryption fails or version is unsupported
|
|
74
|
+
*/
|
|
75
|
+
declare function hybridDecrypt(ciphertextBase64: string, pqSecretKey: string, rsaPrivateKey: string, aad?: string): Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* Wraps a shared AES key using hybrid encryption.
|
|
78
|
+
* Used for shared collections where each member gets a wrapped copy.
|
|
79
|
+
*
|
|
80
|
+
* @param sharedKeyJwk - JWK string of the shared AES-256 key
|
|
81
|
+
* @param pqPublicKey - Base64-encoded ML-KEM-768 public key
|
|
82
|
+
* @param rsaPublicKey - JWK string of RSA-4096 public key
|
|
83
|
+
* @param aad - Optional additional authenticated data (e.g. collection ID)
|
|
84
|
+
* @returns Base64-encoded wrapped key
|
|
85
|
+
*/
|
|
86
|
+
declare function hybridWrapKey(sharedKeyJwk: string, pqPublicKey: string, rsaPublicKey: string, aad: string): Promise<string>;
|
|
87
|
+
/**
|
|
88
|
+
* Unwraps a shared AES key using hybrid decryption.
|
|
89
|
+
*
|
|
90
|
+
* @param wrappedKey - Base64-encoded wrapped key
|
|
91
|
+
* @param pqSecretKey - Base64-encoded ML-KEM-768 secret key
|
|
92
|
+
* @param rsaPrivateKey - JWK string of RSA-4096 private key
|
|
93
|
+
* @param aad - Optional additional authenticated data (must match wrap-time AAD)
|
|
94
|
+
* @returns JWK string of the shared AES-256 key
|
|
95
|
+
*/
|
|
96
|
+
declare function hybridUnwrapKey(wrappedKey: string, pqSecretKey: string, rsaPrivateKey: string, aad: string): Promise<string>;
|
|
97
|
+
/**
|
|
98
|
+
* Checks if wrapped key material uses any hybrid (post-quantum) encryption version.
|
|
99
|
+
* Recognizes legacy hybrid (0x02), standard v1 (0x03), and standard v2 (0x04).
|
|
100
|
+
*
|
|
101
|
+
* @param ciphertextBase64 - Base64-encoded ciphertext
|
|
102
|
+
* @returns true if any hybrid wrapped-key version, false if legacy RSA-only or unknown
|
|
103
|
+
*/
|
|
104
|
+
declare function isHybridEncrypted(ciphertextBase64: string): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Checks if a ciphertext uses the current standard encryption (v2 HKDF, version 0x04).
|
|
107
|
+
* Use this for security enforcement checks where only the latest format is acceptable.
|
|
108
|
+
*
|
|
109
|
+
* @param ciphertextBase64 - Base64-encoded ciphertext
|
|
110
|
+
* @returns true if current standard (0x04), false otherwise
|
|
111
|
+
*/
|
|
112
|
+
declare function isCurrentStandardEncrypted(ciphertextBase64: string): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Re-wraps legacy RSA-only or older hybrid key material with current hybrid key wrapping (v2).
|
|
115
|
+
* Used during migration to post-quantum protection for sharing and emergency keys.
|
|
116
|
+
*
|
|
117
|
+
* - Version 0x04: already current, returned unchanged.
|
|
118
|
+
* - Version 0x03: decrypted with legacy HKDF-v1, re-encrypted with HKDF-v2.
|
|
119
|
+
* - Version 0x02: decrypted with legacy hybrid path, re-encrypted.
|
|
120
|
+
* - Version 0x01 / unknown: decrypted with RSA-only, re-encrypted.
|
|
121
|
+
*
|
|
122
|
+
* @param legacyCiphertext - Base64-encoded legacy ciphertext
|
|
123
|
+
* @param rsaPrivateKey - JWK string of RSA private key for decryption
|
|
124
|
+
* @param pqSecretKey - Base64-encoded ML-KEM-768 secret key (required for hybrid legacy)
|
|
125
|
+
* @param pqPublicKey - Base64-encoded ML-KEM-768 public key
|
|
126
|
+
* @param rsaPublicKey - JWK string of RSA public key
|
|
127
|
+
* @returns Base64-encoded hybrid ciphertext (version 0x04)
|
|
128
|
+
*/
|
|
129
|
+
declare function migrateToHybrid(legacyCiphertext: string, rsaPrivateKey: string, pqSecretKey: string | null, pqPublicKey: string, rsaPublicKey: string, aad?: string): Promise<string>;
|
|
130
|
+
/**
|
|
131
|
+
* ML-KEM-768 key pair
|
|
132
|
+
*/
|
|
133
|
+
interface PQKeyPair {
|
|
134
|
+
/** Base64-encoded ML-KEM-768 public key (1184 bytes) */
|
|
135
|
+
publicKey: string;
|
|
136
|
+
/** Base64-encoded ML-KEM-768 secret key (2400 bytes) */
|
|
137
|
+
secretKey: string;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Combined hybrid key pair with both PQ and classical keys
|
|
141
|
+
*/
|
|
142
|
+
interface HybridKeyPair {
|
|
143
|
+
/** Base64-encoded ML-KEM-768 public key */
|
|
144
|
+
pqPublicKey: string;
|
|
145
|
+
/** Base64-encoded ML-KEM-768 secret key */
|
|
146
|
+
pqSecretKey: string;
|
|
147
|
+
/** JWK string of RSA-4096 public key */
|
|
148
|
+
rsaPublicKey: string;
|
|
149
|
+
/** JWK string of RSA-4096 private key */
|
|
150
|
+
rsaPrivateKey: string;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export { HYBRID_VERSION, type HybridKeyPair, type PQKeyPair, SECURITY_STANDARD_VERSION, type SharedKeyWrapAadInput, buildSharedKeyWrapAad, generateHybridKeyPair, generatePQKeyPair, hybridDecrypt, hybridEncrypt, hybridUnwrapKey, hybridWrapKey, isCurrentStandardEncrypted, isHybridEncrypted, migrateToHybrid };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { HYBRID_VERSION, SECURITY_STANDARD_VERSION, buildSharedKeyWrapAad, generateHybridKeyPair, generatePQKeyPair, hybridDecrypt, hybridEncrypt, hybridUnwrapKey, hybridWrapKey, isCurrentStandardEncrypted, isHybridEncrypted, migrateToHybrid } from '../chunk-T3IV7SHD.js';
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dis-random — secure random generation.
|
|
3
|
+
*
|
|
4
|
+
* Always sources entropy from the active crypto provider's CSPRNG
|
|
5
|
+
* (`getRandomValues`). DIS never uses `Math.random` for any value that affects
|
|
6
|
+
* confidentiality, integrity, or unpredictability.
|
|
7
|
+
*/
|
|
8
|
+
/** Returns `length` cryptographically secure random bytes. */
|
|
9
|
+
declare function randomBytes(length: number): Uint8Array;
|
|
10
|
+
/**
|
|
11
|
+
* Fills an existing `ArrayBufferView` with cryptographically secure random
|
|
12
|
+
* bytes in place. Used by callers that own a buffer they want to overwrite
|
|
13
|
+
* (e.g. secure-memory scrubbing) without allocating a second array.
|
|
14
|
+
*/
|
|
15
|
+
declare function fillRandom<T extends ArrayBufferView>(view: T): T;
|
|
16
|
+
/**
|
|
17
|
+
* Returns a cryptographically secure random integer in the inclusive range
|
|
18
|
+
* `[min, max]` using rejection sampling to avoid modulo bias.
|
|
19
|
+
*
|
|
20
|
+
* Byte-for-byte equivalent to the `getSecureRandomInt` helpers in Singra Vault
|
|
21
|
+
* (password generator, backup-code generator): it draws `ceil(log2(range)/8)`
|
|
22
|
+
* bytes big-endian and rejects values above the largest multiple of `range`.
|
|
23
|
+
*/
|
|
24
|
+
declare function randomInt(min: number, max: number): number;
|
|
25
|
+
/** Returns a RFC 4122 v4 UUID using the provider's CSPRNG. */
|
|
26
|
+
declare function randomUuid(): string;
|
|
27
|
+
|
|
28
|
+
export { fillRandom, randomBytes, randomInt, randomUuid };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dis-secure-storage / secure-memory — memory-safe handling of key material.
|
|
3
|
+
*
|
|
4
|
+
* Ported from Singra Vault's SecureBuffer. Provides controlled, callback-scoped
|
|
5
|
+
* access to sensitive bytes with explicit zeroing on destroy and a
|
|
6
|
+
* FinalizationRegistry fallback. This is defense-in-depth: JavaScript cannot
|
|
7
|
+
* guarantee memory wiping (GC is non-deterministic, strings are immutable), but
|
|
8
|
+
* controlled access plus best-effort zeroing materially reduces exposure
|
|
9
|
+
* (cf. KeePass CVE-2023-32784).
|
|
10
|
+
*/
|
|
11
|
+
/** A wrapper for sensitive binary data with controlled access and zeroing. */
|
|
12
|
+
declare class SecureBuffer {
|
|
13
|
+
private buffer;
|
|
14
|
+
private destroyed;
|
|
15
|
+
constructor(size: number);
|
|
16
|
+
/** Copies `bytes` into a new SecureBuffer. The source is NOT auto-zeroed. */
|
|
17
|
+
static fromBytes(bytes: Uint8Array): SecureBuffer;
|
|
18
|
+
/** Builds a SecureBuffer from a hex string (spaces/dashes allowed). */
|
|
19
|
+
static fromHex(hex: string): SecureBuffer;
|
|
20
|
+
/** Allocates a SecureBuffer filled with CSPRNG bytes. */
|
|
21
|
+
static random(size: number): SecureBuffer;
|
|
22
|
+
/** Synchronous controlled access. Do not retain the buffer past `fn`. */
|
|
23
|
+
use<T>(fn: (data: Uint8Array) => T): T;
|
|
24
|
+
/** Asynchronous controlled access. */
|
|
25
|
+
useAsync<T>(fn: (data: Uint8Array) => Promise<T>): Promise<T>;
|
|
26
|
+
get size(): number;
|
|
27
|
+
get isDestroyed(): boolean;
|
|
28
|
+
/** Zeros the buffer and marks it destroyed. Idempotent. */
|
|
29
|
+
destroy(): void;
|
|
30
|
+
/** Returns a mutable copy of the contents (caller must zero it). */
|
|
31
|
+
toBytes(): Uint8Array;
|
|
32
|
+
/** Constant-time equality comparison against another buffer. */
|
|
33
|
+
equals(other: SecureBuffer | Uint8Array): boolean;
|
|
34
|
+
}
|
|
35
|
+
/** Runs `fn` with a temporary SecureBuffer that is always destroyed afterwards. */
|
|
36
|
+
declare function withSecureBuffer<T>(bytes: Uint8Array, fn: (secure: SecureBuffer) => Promise<T>): Promise<T>;
|
|
37
|
+
/** Zeros multiple buffers. Convenience for `finally` cleanup blocks. */
|
|
38
|
+
declare function zeroBuffers(...buffers: (Uint8Array | null | undefined)[]): void;
|
|
39
|
+
|
|
40
|
+
export { SecureBuffer, withSecureBuffer, zeroBuffers };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dis-signing — asymmetric digital signatures.
|
|
3
|
+
*
|
|
4
|
+
* Primitive: ECDSA over the NIST P-256 curve with SHA-256, via WebCrypto.
|
|
5
|
+
* Public keys are exchanged as SPKI bytes; private keys are generated
|
|
6
|
+
* non-extractable so they never leave the device. Signatures are the raw
|
|
7
|
+
* `r || s` concatenation WebCrypto produces (fixed 64 bytes for P-256), which
|
|
8
|
+
* is the exact wire form Singra Vault's op-log device signatures use.
|
|
9
|
+
*
|
|
10
|
+
* Canonicalisation of the signed payload is the caller's responsibility — DIS
|
|
11
|
+
* signs and verifies opaque byte strings and never interprets their structure.
|
|
12
|
+
*/
|
|
13
|
+
/** Raw byte length of a P-256 ECDSA signature (`r || s`, 32 bytes each). */
|
|
14
|
+
declare const ECDSA_P256_SIGNATURE_LENGTH = 64;
|
|
15
|
+
interface EcdsaP256KeyPair {
|
|
16
|
+
readonly privateKey: CryptoKey;
|
|
17
|
+
readonly publicKey: CryptoKey;
|
|
18
|
+
/** SPKI-encoded public key bytes, ready to be base64url-encoded for storage. */
|
|
19
|
+
readonly publicKeySpki: Uint8Array;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generates a fresh non-extractable ECDSA P-256 key pair and exports the
|
|
23
|
+
* public key as SPKI bytes.
|
|
24
|
+
*/
|
|
25
|
+
declare function generateEcdsaP256KeyPair(): Promise<EcdsaP256KeyPair>;
|
|
26
|
+
/** Imports an SPKI-encoded P-256 public key for signature verification. */
|
|
27
|
+
declare function importEcdsaP256PublicKeySpki(spki: Uint8Array): Promise<CryptoKey>;
|
|
28
|
+
/**
|
|
29
|
+
* Signs `data` with an ECDSA P-256 private key, returning the raw 64-byte
|
|
30
|
+
* `r || s` signature. Throws {@link DisInvalidArgumentError} if WebCrypto
|
|
31
|
+
* returns an unexpected length (defends against curve/algorithm misuse).
|
|
32
|
+
*/
|
|
33
|
+
declare function signEcdsaP256(privateKey: CryptoKey, data: Uint8Array): Promise<Uint8Array>;
|
|
34
|
+
/**
|
|
35
|
+
* Verifies a raw 64-byte `r || s` ECDSA P-256 signature over `data`. Returns
|
|
36
|
+
* `false` for an invalid signature; throws {@link DisInvalidArgumentError} if
|
|
37
|
+
* the signature is not the expected length.
|
|
38
|
+
*/
|
|
39
|
+
declare function verifyEcdsaP256(publicKey: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<boolean>;
|
|
40
|
+
|
|
41
|
+
export { ECDSA_P256_SIGNATURE_LENGTH, type EcdsaP256KeyPair, generateEcdsaP256KeyPair, importEcdsaP256PublicKeySpki, signEcdsaP256, verifyEcdsaP256 };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ECDSA_P256_SIGNATURE_LENGTH, generateEcdsaP256KeyPair, importEcdsaP256PublicKeySpki, signEcdsaP256, verifyEcdsaP256 } from '../chunk-AB2WZ7Y2.js';
|
|
2
|
+
import '../chunk-CYIGDF63.js';
|
|
3
|
+
import '../chunk-MJO7IJZC.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dis-totp — time-based one-time passwords (RFC 6238).
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper over the audited `otpauth` library so applications never embed
|
|
5
|
+
* the OTP primitive directly. Parameters are pinned to the values Singra Vault
|
|
6
|
+
* uses (SHA-1, 6 digits, 30-second period, 160-bit secrets) so existing
|
|
7
|
+
* enrolled authenticators keep working unchanged.
|
|
8
|
+
*
|
|
9
|
+
* SHA-1 here is the standardised HMAC inside the TOTP construction (RFC 6238),
|
|
10
|
+
* which every authenticator app implements; it is not used as a hash for any
|
|
11
|
+
* security decision elsewhere.
|
|
12
|
+
*/
|
|
13
|
+
/** TOTP parameters, fixed to remain compatible with enrolled authenticators. */
|
|
14
|
+
declare const TOTP_ALGORITHM: "SHA1";
|
|
15
|
+
declare const TOTP_DIGITS = 6;
|
|
16
|
+
declare const TOTP_PERIOD_SECONDS = 30;
|
|
17
|
+
/** Secret size in bytes (160-bit) as produced by {@link generateTotpSecret}. */
|
|
18
|
+
declare const TOTP_SECRET_SIZE = 20;
|
|
19
|
+
/** HMAC algorithms RFC 6238 permits and authenticator apps implement. */
|
|
20
|
+
type TotpAlgorithm = 'SHA1' | 'SHA256' | 'SHA512';
|
|
21
|
+
/**
|
|
22
|
+
* Parameters for third-party TOTP entries (password-manager authenticator
|
|
23
|
+
* storage). Unlike Singra's own 2FA enrolment — which is pinned to
|
|
24
|
+
* SHA-1 / 6 digits / 30 s — imported entries carry whatever parameters the
|
|
25
|
+
* issuing service chose, so each knob is explicit here.
|
|
26
|
+
*/
|
|
27
|
+
interface TotpCodeOptions {
|
|
28
|
+
/** HMAC algorithm. Defaults to {@link TOTP_ALGORITHM}. */
|
|
29
|
+
readonly algorithm?: TotpAlgorithm;
|
|
30
|
+
/** Code length. Defaults to {@link TOTP_DIGITS}. */
|
|
31
|
+
readonly digits?: number;
|
|
32
|
+
/** Time step in seconds. Defaults to {@link TOTP_PERIOD_SECONDS}. */
|
|
33
|
+
readonly period?: number;
|
|
34
|
+
/** Epoch milliseconds to generate for. Defaults to the current time. */
|
|
35
|
+
readonly timestamp?: number;
|
|
36
|
+
}
|
|
37
|
+
interface TotpParams {
|
|
38
|
+
/** Issuer label shown in the authenticator app. */
|
|
39
|
+
readonly issuer: string;
|
|
40
|
+
/** Account label (typically the user's email). */
|
|
41
|
+
readonly label: string;
|
|
42
|
+
/** Base32-encoded shared secret. */
|
|
43
|
+
readonly secret: string;
|
|
44
|
+
}
|
|
45
|
+
/** Generates a new base32-encoded 160-bit TOTP secret. */
|
|
46
|
+
declare function generateTotpSecret(): string;
|
|
47
|
+
/** Builds the `otpauth://` provisioning URI for a QR code. */
|
|
48
|
+
declare function buildTotpUri(params: TotpParams): string;
|
|
49
|
+
/**
|
|
50
|
+
* Generates the TOTP code for a base32 `secret` with explicit parameters —
|
|
51
|
+
* the primitive behind a password manager's authenticator view. Throws
|
|
52
|
+
* {@link DisInvalidArgumentError} on a malformed secret so callers can decide
|
|
53
|
+
* how to surface the error.
|
|
54
|
+
*/
|
|
55
|
+
declare function generateTotpCode(secret: string, options?: TotpCodeOptions): string;
|
|
56
|
+
/**
|
|
57
|
+
* Builds the `otpauth://` provisioning URI for an entry with explicit
|
|
58
|
+
* parameters (third-party authenticator entries). Singra's own 2FA enrolment
|
|
59
|
+
* should keep using {@link buildTotpUri}, which pins the Singra parameter set.
|
|
60
|
+
*/
|
|
61
|
+
declare function buildTotpUriWithOptions(params: TotpParams, options?: Omit<TotpCodeOptions, 'timestamp'>): string;
|
|
62
|
+
/**
|
|
63
|
+
* Verifies a TOTP `code` against a base32 `secret`, allowing `window` periods
|
|
64
|
+
* of clock drift on either side (default 1 = ±30s). Returns `true` on a match.
|
|
65
|
+
* Malformed secrets/codes return `false` rather than throwing.
|
|
66
|
+
*/
|
|
67
|
+
declare function verifyTotpCode(secret: string, code: string, window?: number): boolean;
|
|
68
|
+
|
|
69
|
+
export { TOTP_ALGORITHM, TOTP_DIGITS, TOTP_PERIOD_SECONDS, TOTP_SECRET_SIZE, type TotpAlgorithm, type TotpCodeOptions, type TotpParams, buildTotpUri, buildTotpUriWithOptions, generateTotpCode, generateTotpSecret, verifyTotpCode };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { TOTP_ALGORITHM, TOTP_DIGITS, TOTP_PERIOD_SECONDS, TOTP_SECRET_SIZE, buildTotpUri, buildTotpUriWithOptions, generateTotpCode, generateTotpSecret, verifyTotpCode } from '../chunk-OA5ARYJM.js';
|
|
2
|
+
import '../chunk-MJO7IJZC.js';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|