@digitaldefiance/ecies-lib 1.0.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 +21 -0
- package/README.md +237 -0
- package/dist/backup-code-string.d.ts +26 -0
- package/dist/backup-code-string.d.ts.map +1 -0
- package/dist/backup-code-string.js +69 -0
- package/dist/backup-code-string.js.map +1 -0
- package/dist/constants.d.ts +22 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +177 -0
- package/dist/constants.js.map +1 -0
- package/dist/email-string.d.ts +42 -0
- package/dist/email-string.d.ts.map +1 -0
- package/dist/email-string.js +67 -0
- package/dist/email-string.js.map +1 -0
- package/dist/enumerations/ecies-encryption-type.d.ts +15 -0
- package/dist/enumerations/ecies-encryption-type.d.ts.map +1 -0
- package/dist/enumerations/ecies-encryption-type.js +63 -0
- package/dist/enumerations/ecies-encryption-type.js.map +1 -0
- package/dist/enumerations/ecies-error-type.d.ts +32 -0
- package/dist/enumerations/ecies-error-type.d.ts.map +1 -0
- package/dist/enumerations/ecies-error-type.js +33 -0
- package/dist/enumerations/ecies-error-type.js.map +1 -0
- package/dist/enumerations/guid-brand-type.d.ts +27 -0
- package/dist/enumerations/guid-brand-type.d.ts.map +1 -0
- package/dist/enumerations/guid-brand-type.js +28 -0
- package/dist/enumerations/guid-brand-type.js.map +1 -0
- package/dist/enumerations/guid-error-type.d.ts +7 -0
- package/dist/enumerations/guid-error-type.d.ts.map +1 -0
- package/dist/enumerations/guid-error-type.js +8 -0
- package/dist/enumerations/guid-error-type.js.map +1 -0
- package/dist/enumerations/index.d.ts +13 -0
- package/dist/enumerations/index.d.ts.map +1 -0
- package/dist/enumerations/index.js +13 -0
- package/dist/enumerations/index.js.map +1 -0
- package/dist/enumerations/invalid-email-type.d.ts +6 -0
- package/dist/enumerations/invalid-email-type.d.ts.map +1 -0
- package/dist/enumerations/invalid-email-type.js +7 -0
- package/dist/enumerations/invalid-email-type.js.map +1 -0
- package/dist/enumerations/length-encoding-type.d.ts +7 -0
- package/dist/enumerations/length-encoding-type.d.ts.map +1 -0
- package/dist/enumerations/length-encoding-type.js +8 -0
- package/dist/enumerations/length-encoding-type.js.map +1 -0
- package/dist/enumerations/length-error-type.d.ts +6 -0
- package/dist/enumerations/length-error-type.d.ts.map +1 -0
- package/dist/enumerations/length-error-type.js +7 -0
- package/dist/enumerations/length-error-type.js.map +1 -0
- package/dist/enumerations/member-error-type.d.ts +87 -0
- package/dist/enumerations/member-error-type.d.ts.map +1 -0
- package/dist/enumerations/member-error-type.js +88 -0
- package/dist/enumerations/member-error-type.js.map +1 -0
- package/dist/enumerations/member-type.d.ts +16 -0
- package/dist/enumerations/member-type.d.ts.map +1 -0
- package/dist/enumerations/member-type.js +17 -0
- package/dist/enumerations/member-type.js.map +1 -0
- package/dist/enumerations/pbkdf2-error-type.d.ts +5 -0
- package/dist/enumerations/pbkdf2-error-type.d.ts.map +1 -0
- package/dist/enumerations/pbkdf2-error-type.js +6 -0
- package/dist/enumerations/pbkdf2-error-type.js.map +1 -0
- package/dist/enumerations/pbkdf2-profile.d.ts +5 -0
- package/dist/enumerations/pbkdf2-profile.d.ts.map +1 -0
- package/dist/enumerations/pbkdf2-profile.js +6 -0
- package/dist/enumerations/pbkdf2-profile.js.map +1 -0
- package/dist/enumerations/secure-storage-error-type.d.ts +6 -0
- package/dist/enumerations/secure-storage-error-type.d.ts.map +1 -0
- package/dist/enumerations/secure-storage-error-type.js +7 -0
- package/dist/enumerations/secure-storage-error-type.js.map +1 -0
- package/dist/errors/disposed.d.ts +4 -0
- package/dist/errors/disposed.d.ts.map +1 -0
- package/dist/errors/disposed.js +8 -0
- package/dist/errors/disposed.js.map +1 -0
- package/dist/errors/ecies.d.ts +6 -0
- package/dist/errors/ecies.d.ts.map +1 -0
- package/dist/errors/ecies.js +8 -0
- package/dist/errors/ecies.js.map +1 -0
- package/dist/errors/guid.d.ts +14 -0
- package/dist/errors/guid.d.ts.map +1 -0
- package/dist/errors/guid.js +19 -0
- package/dist/errors/guid.js.map +1 -0
- package/dist/errors/index.d.ts +9 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +9 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/invalid-backup-code.d.ts +4 -0
- package/dist/errors/invalid-backup-code.d.ts.map +1 -0
- package/dist/errors/invalid-backup-code.js +7 -0
- package/dist/errors/invalid-backup-code.js.map +1 -0
- package/dist/errors/invalid-email.d.ts +6 -0
- package/dist/errors/invalid-email.d.ts.map +1 -0
- package/dist/errors/invalid-email.js +9 -0
- package/dist/errors/invalid-email.js.map +1 -0
- package/dist/errors/length.d.ts +6 -0
- package/dist/errors/length.d.ts.map +1 -0
- package/dist/errors/length.js +9 -0
- package/dist/errors/length.js.map +1 -0
- package/dist/errors/member.d.ts +6 -0
- package/dist/errors/member.d.ts.map +1 -0
- package/dist/errors/member.js +8 -0
- package/dist/errors/member.js.map +1 -0
- package/dist/errors/pbkdf2.d.ts +6 -0
- package/dist/errors/pbkdf2.d.ts.map +1 -0
- package/dist/errors/pbkdf2.js +8 -0
- package/dist/errors/pbkdf2.js.map +1 -0
- package/dist/errors/secure-storage.d.ts +6 -0
- package/dist/errors/secure-storage.d.ts.map +1 -0
- package/dist/errors/secure-storage.js +8 -0
- package/dist/errors/secure-storage.js.map +1 -0
- package/dist/errors/typed.d.ts +5 -0
- package/dist/errors/typed.d.ts.map +1 -0
- package/dist/errors/typed.js +11 -0
- package/dist/errors/typed.js.map +1 -0
- package/dist/guid.d.ts +153 -0
- package/dist/guid.d.ts.map +1 -0
- package/dist/guid.js +604 -0
- package/dist/guid.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/backup-code-consts.d.ts +16 -0
- package/dist/interfaces/backup-code-consts.d.ts.map +1 -0
- package/dist/interfaces/backup-code-consts.js +2 -0
- package/dist/interfaces/backup-code-consts.js.map +1 -0
- package/dist/interfaces/backup-code.d.ts +7 -0
- package/dist/interfaces/backup-code.d.ts.map +1 -0
- package/dist/interfaces/backup-code.js +2 -0
- package/dist/interfaces/backup-code.js.map +1 -0
- package/dist/interfaces/constants.d.ts +45 -0
- package/dist/interfaces/constants.d.ts.map +1 -0
- package/dist/interfaces/constants.js +2 -0
- package/dist/interfaces/constants.js.map +1 -0
- package/dist/interfaces/ecies-config.d.ts +9 -0
- package/dist/interfaces/ecies-config.d.ts.map +1 -0
- package/dist/interfaces/ecies-config.js +2 -0
- package/dist/interfaces/ecies-config.js.map +1 -0
- package/dist/interfaces/ecies-consts.d.ts +58 -0
- package/dist/interfaces/ecies-consts.d.ts.map +1 -0
- package/dist/interfaces/ecies-consts.js +2 -0
- package/dist/interfaces/ecies-consts.js.map +1 -0
- package/dist/interfaces/ecies-file-service.d.ts +7 -0
- package/dist/interfaces/ecies-file-service.d.ts.map +1 -0
- package/dist/interfaces/ecies-file-service.js +2 -0
- package/dist/interfaces/ecies-file-service.js.map +1 -0
- package/dist/interfaces/guid.d.ts +45 -0
- package/dist/interfaces/guid.d.ts.map +1 -0
- package/dist/interfaces/guid.js +2 -0
- package/dist/interfaces/guid.js.map +1 -0
- package/dist/interfaces/index.d.ts +14 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/index.js +14 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/interfaces/member-operational.d.ts +39 -0
- package/dist/interfaces/member-operational.d.ts.map +1 -0
- package/dist/interfaces/member-operational.js +2 -0
- package/dist/interfaces/member-operational.js.map +1 -0
- package/dist/interfaces/member-storage.d.ts +21 -0
- package/dist/interfaces/member-storage.d.ts.map +1 -0
- package/dist/interfaces/member-storage.js +2 -0
- package/dist/interfaces/member-storage.js.map +1 -0
- package/dist/interfaces/member-with-mnemonic.d.ts +7 -0
- package/dist/interfaces/member-with-mnemonic.d.ts.map +1 -0
- package/dist/interfaces/member-with-mnemonic.js +2 -0
- package/dist/interfaces/member-with-mnemonic.js.map +1 -0
- package/dist/interfaces/pbkdf2-config.d.ts +7 -0
- package/dist/interfaces/pbkdf2-config.d.ts.map +1 -0
- package/dist/interfaces/pbkdf2-config.js +2 -0
- package/dist/interfaces/pbkdf2-config.js.map +1 -0
- package/dist/interfaces/pbkdf2-consts.d.ts +9 -0
- package/dist/interfaces/pbkdf2-consts.d.ts.map +1 -0
- package/dist/interfaces/pbkdf2-consts.js +2 -0
- package/dist/interfaces/pbkdf2-consts.js.map +1 -0
- package/dist/interfaces/pbkdf2-result.d.ts +6 -0
- package/dist/interfaces/pbkdf2-result.d.ts.map +1 -0
- package/dist/interfaces/pbkdf2-result.js +2 -0
- package/dist/interfaces/pbkdf2-result.js.map +1 -0
- package/dist/member.d.ts +68 -0
- package/dist/member.d.ts.map +1 -0
- package/dist/member.js +256 -0
- package/dist/member.js.map +1 -0
- package/dist/pbkdf2-profiles.d.ts +6 -0
- package/dist/pbkdf2-profiles.d.ts.map +1 -0
- package/dist/pbkdf2-profiles.js +2 -0
- package/dist/pbkdf2-profiles.js.map +1 -0
- package/dist/secure-buffer.d.ts +38 -0
- package/dist/secure-buffer.d.ts.map +1 -0
- package/dist/secure-buffer.js +161 -0
- package/dist/secure-buffer.js.map +1 -0
- package/dist/secure-string.d.ts +39 -0
- package/dist/secure-string.d.ts.map +1 -0
- package/dist/secure-string.js +188 -0
- package/dist/secure-string.js.map +1 -0
- package/dist/services/aes-gcm.d.ts +56 -0
- package/dist/services/aes-gcm.d.ts.map +1 -0
- package/dist/services/aes-gcm.js +101 -0
- package/dist/services/aes-gcm.js.map +1 -0
- package/dist/services/ecies/crypto-core.d.ts +53 -0
- package/dist/services/ecies/crypto-core.d.ts.map +1 -0
- package/dist/services/ecies/crypto-core.js +158 -0
- package/dist/services/ecies/crypto-core.js.map +1 -0
- package/dist/services/ecies/example.d.ts +25 -0
- package/dist/services/ecies/example.d.ts.map +1 -0
- package/dist/services/ecies/example.js +121 -0
- package/dist/services/ecies/example.js.map +1 -0
- package/dist/services/ecies/file.d.ts +18 -0
- package/dist/services/ecies/file.d.ts.map +1 -0
- package/dist/services/ecies/file.js +106 -0
- package/dist/services/ecies/file.js.map +1 -0
- package/dist/services/ecies/index.d.ts +38 -0
- package/dist/services/ecies/index.d.ts.map +1 -0
- package/dist/services/ecies/index.js +39 -0
- package/dist/services/ecies/index.js.map +1 -0
- package/dist/services/ecies/integration.d.ts +59 -0
- package/dist/services/ecies/integration.d.ts.map +1 -0
- package/dist/services/ecies/integration.js +163 -0
- package/dist/services/ecies/integration.js.map +1 -0
- package/dist/services/ecies/interfaces.d.ts +51 -0
- package/dist/services/ecies/interfaces.d.ts.map +1 -0
- package/dist/services/ecies/interfaces.js +5 -0
- package/dist/services/ecies/interfaces.js.map +1 -0
- package/dist/services/ecies/manual-test.d.ts +29 -0
- package/dist/services/ecies/manual-test.d.ts.map +1 -0
- package/dist/services/ecies/manual-test.js +163 -0
- package/dist/services/ecies/manual-test.js.map +1 -0
- package/dist/services/ecies/multi-recipient.d.ts +49 -0
- package/dist/services/ecies/multi-recipient.d.ts.map +1 -0
- package/dist/services/ecies/multi-recipient.js +222 -0
- package/dist/services/ecies/multi-recipient.js.map +1 -0
- package/dist/services/ecies/service.d.ts +100 -0
- package/dist/services/ecies/service.d.ts.map +1 -0
- package/dist/services/ecies/service.js +186 -0
- package/dist/services/ecies/service.js.map +1 -0
- package/dist/services/ecies/signature.d.ts +27 -0
- package/dist/services/ecies/signature.d.ts.map +1 -0
- package/dist/services/ecies/signature.js +72 -0
- package/dist/services/ecies/signature.js.map +1 -0
- package/dist/services/ecies/single-recipient.d.ts +43 -0
- package/dist/services/ecies/single-recipient.d.ts.map +1 -0
- package/dist/services/ecies/single-recipient.js +196 -0
- package/dist/services/ecies/single-recipient.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +5 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/password-login.d.ts +41 -0
- package/dist/services/password-login.d.ts.map +1 -0
- package/dist/services/password-login.js +96 -0
- package/dist/services/password-login.js.map +1 -0
- package/dist/services/pbkdf2.d.ts +49 -0
- package/dist/services/pbkdf2.d.ts.map +1 -0
- package/dist/services/pbkdf2.js +97 -0
- package/dist/services/pbkdf2.js.map +1 -0
- package/dist/services/xor.d.ts +37 -0
- package/dist/services/xor.d.ts.map +1 -0
- package/dist/services/xor.js +63 -0
- package/dist/services/xor.js.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +62 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +244 -0
- package/dist/utils.js.map +1 -0
- package/dist/xor.d.ts +37 -0
- package/dist/xor.d.ts.map +1 -0
- package/dist/xor.js +63 -0
- package/dist/xor.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Digital Defiance
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# @digitaldefiance/ecies-lib
|
|
2
|
+
|
|
3
|
+
A production-ready, browser-friendly implementation of Elliptic Curve Integrated Encryption Scheme (ECIES) and related primitives for modern TypeScript runtimes. The library ships with end-to-end test coverage, high-level services for common workflows, and low-level utilities you can compose to build secure storage, file sharing, and password-login flows.
|
|
4
|
+
|
|
5
|
+
## Highlights
|
|
6
|
+
|
|
7
|
+
- **Web & Node compatible** – built around the Web Crypto API (`crypto.subtle`) and `secp256k1` from `@noble/curves`, tested against Node 18+ and headless browser environments.
|
|
8
|
+
- **Multiple ECIES modes** – "simple" (no length metadata), "single" (length-prefixed payloads), and a dedicated `EciesMultiRecipient` helper for wrapping symmetric keys across large recipient sets.
|
|
9
|
+
- **Typed safety net** – exhaustive error/enum catalog (e.g., `ECIESErrorTypeEnum`, `Pbkdf2ErrorType`, `InvalidEmailErrorType`) backed by strongly typed error classes.
|
|
10
|
+
- **Ancillary crypto services** – AES-GCM helpers, PBKDF2 profiles, secure buffers/strings, mnemonic-based key derivation, and password-login tooling.
|
|
11
|
+
- **Rock-solid tests** – 380+ Jest specs, including multi-recipient integration, file encryption round-trips, and e2e login flows.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add @digitaldefiance/ecies-lib
|
|
17
|
+
# or
|
|
18
|
+
yarn add @digitaldefiance/ecies-lib
|
|
19
|
+
# or
|
|
20
|
+
npm install @digitaldefiance/ecies-lib
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
> **Runtime requirements**
|
|
24
|
+
>
|
|
25
|
+
> - Node.js 18+ (ships with the Web Crypto API). For earlier Node versions, polyfill `globalThis.crypto` before importing the library.
|
|
26
|
+
> - Browsers with Web Crypto + `BigInt` support (Chromium, Firefox, Safari >= 14).
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { ECIESService } from '@digitaldefiance/ecies-lib';
|
|
32
|
+
|
|
33
|
+
const ecies = new ECIESService();
|
|
34
|
+
|
|
35
|
+
// 1. Generate deterministic recipient keys from a mnemonic
|
|
36
|
+
const recipientMnemonic = ecies.generateNewMnemonic();
|
|
37
|
+
const recipientKeys = ecies.mnemonicToSimpleKeyPair(recipientMnemonic);
|
|
38
|
+
|
|
39
|
+
// 2. Encrypt in "single" mode (length metadata included)
|
|
40
|
+
const message = new TextEncoder().encode('Sign the blocks.');
|
|
41
|
+
const encrypted = await ecies.encryptSimpleOrSingle(
|
|
42
|
+
false, // false => EciesEncryptionTypeEnum.Single
|
|
43
|
+
recipientKeys.publicKey,
|
|
44
|
+
message,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// 3. Decrypt by honoring the header
|
|
48
|
+
const decrypted = await ecies.decryptSimpleOrSingleWithHeader(
|
|
49
|
+
false,
|
|
50
|
+
recipientKeys.privateKey,
|
|
51
|
+
encrypted,
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
console.log(new TextDecoder().decode(decrypted)); // "Sign the blocks."
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Multi-recipient encryption
|
|
58
|
+
|
|
59
|
+
The high-level `ECIESService.encrypt` method intentionally throws for `EciesEncryptionTypeEnum.Multiple` until the orchestration layer is finalized. The lower-level `EciesMultiRecipient` helper is fully functional and end-to-end tested.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import {
|
|
63
|
+
ECIES,
|
|
64
|
+
EciesMultiRecipient,
|
|
65
|
+
EciesCryptoCore,
|
|
66
|
+
concatUint8Arrays,
|
|
67
|
+
} from '@digitaldefiance/ecies-lib';
|
|
68
|
+
|
|
69
|
+
const config = {
|
|
70
|
+
curveName: ECIES.CURVE_NAME,
|
|
71
|
+
primaryKeyDerivationPath: ECIES.PRIMARY_KEY_DERIVATION_PATH,
|
|
72
|
+
mnemonicStrength: ECIES.MNEMONIC_STRENGTH,
|
|
73
|
+
symmetricAlgorithm: ECIES.SYMMETRIC.ALGORITHM,
|
|
74
|
+
symmetricKeyBits: ECIES.SYMMETRIC.KEY_BITS,
|
|
75
|
+
symmetricKeyMode: ECIES.SYMMETRIC.MODE,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const multi = new EciesMultiRecipient(config);
|
|
79
|
+
const core = new EciesCryptoCore(config);
|
|
80
|
+
|
|
81
|
+
const recipients = await Promise.all(
|
|
82
|
+
[...Array(3)].map(async () => {
|
|
83
|
+
const { privateKey, publicKey } = await core.generateEphemeralKeyPair();
|
|
84
|
+
return {
|
|
85
|
+
id: crypto.getRandomValues(new Uint8Array(ECIES.MULTIPLE.RECIPIENT_ID_SIZE)),
|
|
86
|
+
privateKey,
|
|
87
|
+
publicKey,
|
|
88
|
+
};
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const payload = new TextEncoder().encode('Broadcast to the ops team');
|
|
93
|
+
const encrypted = await multi.encryptMultiple(
|
|
94
|
+
recipients.map(({ id, publicKey }) => ({ id, publicKey })),
|
|
95
|
+
payload,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const transportFrame = concatUint8Arrays(
|
|
99
|
+
multi.buildHeader(encrypted),
|
|
100
|
+
encrypted.encryptedMessage,
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// Recipient 0 decrypts
|
|
104
|
+
const cleartext = await multi.decryptMultipleForRecipient(
|
|
105
|
+
multi.parseMessage(transportFrame),
|
|
106
|
+
recipients[0].id,
|
|
107
|
+
recipients[0].privateKey,
|
|
108
|
+
);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## File encryption service
|
|
112
|
+
|
|
113
|
+
`EciesFileService` wraps `ECIESService` to provide authenticated file encryption/decryption in the browser. It streams large files, supports zero-length payloads, and handles download flows.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { ECIESService, EciesFileService } from '@digitaldefiance/ecies-lib';
|
|
117
|
+
|
|
118
|
+
const ecies = new ECIESService();
|
|
119
|
+
const { privateKey, publicKey } = ecies.mnemonicToSimpleKeyPair(ecies.generateNewMnemonic());
|
|
120
|
+
const fileService = new EciesFileService(ecies, privateKey);
|
|
121
|
+
|
|
122
|
+
const encryptedBytes = await fileService.encryptFile(fileInput.files![0], publicKey);
|
|
123
|
+
const plainBytes = await fileService.decryptFile(encryptedBytes);
|
|
124
|
+
fileService.downloadEncryptedFile(encryptedBytes, `${Date.now()}.enc`);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
See `src/services/ecies/file.ts` and `tests/services/ecies/file.spec.ts` for stream management details.
|
|
128
|
+
|
|
129
|
+
## Password login + PBKDF2 helpers
|
|
130
|
+
|
|
131
|
+
The library also addresses user authentication workflows. `PasswordLoginService` manages PBKDF2 hashing, login challenges, and secure storage, while `Pbkdf2Service` exposes low-level derivation utilities and hardened presets.
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
import { PasswordLoginService, Pbkdf2Service } from '@digitaldefiance/ecies-lib';
|
|
135
|
+
|
|
136
|
+
const passwordService = new PasswordLoginService();
|
|
137
|
+
|
|
138
|
+
// Derive a login hash with a hardened profile
|
|
139
|
+
const passwordBytes = new TextEncoder().encode('xX_password_Xx!');
|
|
140
|
+
const pbkdf2 = await Pbkdf2Service.deriveKeyFromPasswordWithProfileAsync(
|
|
141
|
+
passwordBytes,
|
|
142
|
+
'BROWSER_PASSWORD',
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const loginPayload = await passwordService.generateLoginPayload({
|
|
146
|
+
email: 'alice@example.org',
|
|
147
|
+
password: passwordBytes,
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Check `src/services/password-login.ts` and the comprehensive spec files in `tests/password-login*.spec.ts` and `tests/pbkdf2*.spec.ts` for concrete edge cases.
|
|
152
|
+
|
|
153
|
+
## Secure primitives & value objects
|
|
154
|
+
|
|
155
|
+
- `SecureString` / `SecureBuffer`: auto-zero, opt-in disposal, and helper methods for dealing with sensitive material.
|
|
156
|
+
- `BackupCodeString` / `EmailString`: validated wrappers around critical data, catching malformed inputs early.
|
|
157
|
+
- `Guid` utilities: strong typing via `ts-brand`, plus brand-aware error classes.
|
|
158
|
+
|
|
159
|
+
These primitives are exported via `src/index.ts` and come with targeted tests in `tests/backup-code-string.spec.ts`, `tests/email-string.spec.ts`, `src/guid.spec.ts`, etc.
|
|
160
|
+
|
|
161
|
+
## Error handling
|
|
162
|
+
|
|
163
|
+
Every failure path maps to a typed error, so consumers can branch without string comparisons. Example:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import { ECIESError, ECIESErrorTypeEnum } from '@digitaldefiance/ecies-lib';
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
await ecies.decryptSimpleOrSingleWithHeader(false, privateKey, tamperedData);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (error instanceof ECIESError) {
|
|
172
|
+
if (error.type === ECIESErrorTypeEnum.DecryptionFailed) {
|
|
173
|
+
// attempt recovery or alert the user
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Project structure
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
packages/digitaldefiance-ecies-lib/
|
|
183
|
+
├─ src/
|
|
184
|
+
│ ├─ services/ # ECIES, AES-GCM, PBKDF2, password login
|
|
185
|
+
│ ├─ errors/ # Typed error classes
|
|
186
|
+
│ ├─ enumerations/ # Public enums exported via the barrel
|
|
187
|
+
│ ├─ interfaces/ # Shared type definitions
|
|
188
|
+
│ ├─ secure-*.ts # SecureString / SecureBuffer implementations
|
|
189
|
+
│ └─ utils.ts # Buffer/string helpers, CRC, etc.
|
|
190
|
+
├─ tests/
|
|
191
|
+
│ ├─ services/ # Service-level unit + integration suites
|
|
192
|
+
│ ├─ *.spec.ts # Domain-specific validators and helpers
|
|
193
|
+
│ ├─ *.e2e.spec.ts # Password login, PBKDF2, AES-GCM end-to-end coverage
|
|
194
|
+
│ └─ support/ # LocalStorage mocks, custom Jest matchers
|
|
195
|
+
└─ jest.config.js
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Quality gates
|
|
199
|
+
|
|
200
|
+
The project ships with mandatory linting, formatting, and testing commands:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
yarn lint # ESLint across src/**/*.ts
|
|
204
|
+
yarn prettier:check # Enforce formatting
|
|
205
|
+
yarn test # Jest unit + e2e suites
|
|
206
|
+
yarn build # Compile TypeScript into dist/
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Continuous integration mirrors these gates, and the repository currently passes 389 Jest specs (unit + e2e).
|
|
210
|
+
|
|
211
|
+
## Browser vs. Node tips
|
|
212
|
+
|
|
213
|
+
- **Node**: Node 18+ exposes `globalThis.crypto`. If you target older runtimes, polyfill before importing the library:
|
|
214
|
+
```ts
|
|
215
|
+
import { webcrypto } from 'crypto';
|
|
216
|
+
globalThis.crypto = webcrypto as unknown as Crypto;
|
|
217
|
+
```
|
|
218
|
+
- **Browser bundlers**: the package ships TypeScript sources; rely on your bundler (Vite, Webpack, Next.js) to tree-shake unused exports. All external dependencies are ESM-friendly.
|
|
219
|
+
- **Memory hygiene**: many helpers (e.g., `SecureBuffer`) provide `.dispose()` to zero sensitive data. Call them when you’re done.
|
|
220
|
+
|
|
221
|
+
## Contributing
|
|
222
|
+
|
|
223
|
+
1. Fork & clone the repo.
|
|
224
|
+
2. Install dependencies with `yarn install` (Yarn 4 is already configured via `.yarnrc`).
|
|
225
|
+
3. Create a feature branch (`git checkout -b feature/awesome`).
|
|
226
|
+
4. Make changes and run `yarn format && yarn lint && yarn test`.
|
|
227
|
+
5. Submit a PR with a clear description and test evidence.
|
|
228
|
+
|
|
229
|
+
Bug reports and feature requests are welcome—open an issue with reproduction steps and expected behavior.
|
|
230
|
+
|
|
231
|
+
## Security
|
|
232
|
+
|
|
233
|
+
If you discover a vulnerability, please **do not** open a public issue. Email security@digitaldefiance.io with details so we can coordinate a fix and responsible disclosure timeline.
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT © Digital Defiance
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SecureString } from './secure-string';
|
|
2
|
+
export declare class BackupCodeString extends SecureString {
|
|
3
|
+
private readonly _normalizedCode;
|
|
4
|
+
constructor(code: string);
|
|
5
|
+
get value(): string;
|
|
6
|
+
get notNullValue(): string;
|
|
7
|
+
get valueAsHexString(): string;
|
|
8
|
+
get valueAsBase64String(): string;
|
|
9
|
+
get valueAsUint8Array(): Uint8Array;
|
|
10
|
+
/**
|
|
11
|
+
* Format a 32-char normalized code into display form (8 groups of 4).
|
|
12
|
+
* Does not restrict characters beyond grouping.
|
|
13
|
+
*/
|
|
14
|
+
static formatBackupCode(code: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Normalize user-entered code: remove spaces and hyphens, lowercase, and trim.
|
|
17
|
+
*/
|
|
18
|
+
static normalizeCode(input: string): string;
|
|
19
|
+
static generateBackupCode(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Generate the configured number of backup codes.
|
|
22
|
+
* Note: If generation alphabet/length is controlled elsewhere, prefer that path.
|
|
23
|
+
*/
|
|
24
|
+
static generateBackupCodes(): Array<BackupCodeString>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=backup-code-string.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup-code-string.d.ts","sourceRoot":"","sources":["../src/backup-code-string.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,IAAI,EAAE,MAAM;IASxB,IAAoB,KAAK,IAAI,MAAM,CAElC;IAED,IAAoB,YAAY,IAAI,MAAM,CAEzC;IAED,IAAoB,gBAAgB,IAAI,MAAM,CAO7C;IAED,IAAoB,mBAAmB,IAAI,MAAM,CAKhD;IAED,IAAoB,iBAAiB,IAAI,UAAU,CAKlD;IAED;;;OAGG;WACW,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIpD;;OAEG;WACW,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;WAIpC,kBAAkB,IAAI,MAAM;IAU1C;;;OAGG;WACW,mBAAmB,IAAI,KAAK,CAAC,gBAAgB,CAAC;CAO7D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Constants } from './constants';
|
|
2
|
+
import { InvalidBackupCodeError } from './errors/invalid-backup-code';
|
|
3
|
+
import { SecureString } from './secure-string';
|
|
4
|
+
export class BackupCodeString extends SecureString {
|
|
5
|
+
_normalizedCode;
|
|
6
|
+
constructor(code) {
|
|
7
|
+
const normalizedCode = BackupCodeString.normalizeCode(code);
|
|
8
|
+
if (!Constants.BACKUP_CODES.NormalizedHexRegex.test(normalizedCode)) {
|
|
9
|
+
throw new InvalidBackupCodeError();
|
|
10
|
+
}
|
|
11
|
+
super(normalizedCode);
|
|
12
|
+
this._normalizedCode = normalizedCode;
|
|
13
|
+
}
|
|
14
|
+
get value() {
|
|
15
|
+
return this.notNullValue;
|
|
16
|
+
}
|
|
17
|
+
get notNullValue() {
|
|
18
|
+
return BackupCodeString.formatBackupCode(this._normalizedCode);
|
|
19
|
+
}
|
|
20
|
+
get valueAsHexString() {
|
|
21
|
+
const formattedValue = BackupCodeString.formatBackupCode(this._normalizedCode);
|
|
22
|
+
return new TextEncoder().encode(formattedValue).reduce((str, byte) => {
|
|
23
|
+
return str + byte.toString(16).padStart(2, '0');
|
|
24
|
+
}, '');
|
|
25
|
+
}
|
|
26
|
+
get valueAsBase64String() {
|
|
27
|
+
const formattedValue = BackupCodeString.formatBackupCode(this._normalizedCode);
|
|
28
|
+
return btoa(formattedValue);
|
|
29
|
+
}
|
|
30
|
+
get valueAsUint8Array() {
|
|
31
|
+
const formattedValue = BackupCodeString.formatBackupCode(this._normalizedCode);
|
|
32
|
+
return new TextEncoder().encode(formattedValue);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Format a 32-char normalized code into display form (8 groups of 4).
|
|
36
|
+
* Does not restrict characters beyond grouping.
|
|
37
|
+
*/
|
|
38
|
+
static formatBackupCode(code) {
|
|
39
|
+
const groups = code.match(/.{1,4}/g) ?? [code];
|
|
40
|
+
return groups.join('-');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Normalize user-entered code: remove spaces and hyphens, lowercase, and trim.
|
|
44
|
+
*/
|
|
45
|
+
static normalizeCode(input) {
|
|
46
|
+
return input.replace(/[\s-]/g, '').toLowerCase().trim();
|
|
47
|
+
}
|
|
48
|
+
static generateBackupCode() {
|
|
49
|
+
const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
50
|
+
const rnd = crypto.getRandomValues(new Uint8Array(32));
|
|
51
|
+
let raw = '';
|
|
52
|
+
for (let j = 0; j < 32; j++) {
|
|
53
|
+
raw += alphabet[rnd[j] % alphabet.length];
|
|
54
|
+
}
|
|
55
|
+
return raw;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Generate the configured number of backup codes.
|
|
59
|
+
* Note: If generation alphabet/length is controlled elsewhere, prefer that path.
|
|
60
|
+
*/
|
|
61
|
+
static generateBackupCodes() {
|
|
62
|
+
const codes = [];
|
|
63
|
+
for (let i = 0; i < Constants.BACKUP_CODES.Count; i++) {
|
|
64
|
+
codes.push(new BackupCodeString(BackupCodeString.generateBackupCode()));
|
|
65
|
+
}
|
|
66
|
+
return codes;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=backup-code-string.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup-code-string.js","sourceRoot":"","sources":["../src/backup-code-string.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { IBackupCodeConstants } from './interfaces';
|
|
2
|
+
import { IConstants } from './interfaces/constants';
|
|
3
|
+
import { IECIESConstants } from './interfaces/ecies-consts';
|
|
4
|
+
import { IPBkdf2Consts } from './interfaces/pbkdf2-consts';
|
|
5
|
+
import { Pbkdf2Profiles } from './pbkdf2-profiles';
|
|
6
|
+
export declare const UINT8_SIZE: number;
|
|
7
|
+
export declare const UINT16_SIZE: number;
|
|
8
|
+
export declare const UINT16_MAX: number;
|
|
9
|
+
export declare const UINT32_SIZE: number;
|
|
10
|
+
export declare const UINT32_MAX: number;
|
|
11
|
+
export declare const UINT64_SIZE: number;
|
|
12
|
+
export declare const UINT64_MAX: bigint;
|
|
13
|
+
/**
|
|
14
|
+
* Standard size of a UUID v4 in bytes.
|
|
15
|
+
*/
|
|
16
|
+
export declare const GUID_SIZE: number;
|
|
17
|
+
export declare const BACKUP_CODES: IBackupCodeConstants;
|
|
18
|
+
export declare const PBKDF2: IPBkdf2Consts;
|
|
19
|
+
export declare const PBKDF2_PROFILES: Pbkdf2Profiles;
|
|
20
|
+
export declare const ECIES: IECIESConstants;
|
|
21
|
+
export declare const Constants: IConstants;
|
|
22
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,eAAO,MAAM,UAAU,EAAE,MAAmB,CAAC;AAC7C,eAAO,MAAM,WAAW,EAAE,MAAmB,CAAC;AAC9C,eAAO,MAAM,UAAU,EAAE,MAAuB,CAAC;AACjD,eAAO,MAAM,WAAW,EAAE,MAAmB,CAAC;AAC9C,eAAO,MAAM,UAAU,EAAE,MAA4B,CAAC;AACtD,eAAO,MAAM,WAAW,EAAE,MAAmB,CAAC;AAC9C,eAAO,MAAM,UAAU,EAAE,MAAuC,CAAC;AACjE;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,MAAoB,CAAC;AAE7C,eAAO,MAAM,YAAY,EAAE,oBAOjB,CAAC;AAEX,eAAO,MAAM,MAAM,EAAE,aAQX,CAAC;AAEX,eAAO,MAAM,eAAe,EAAE,cAa7B,CAAC;AAyBF,eAAO,MAAM,KAAK,EAAE,eAoEnB,CAAC;AAGF,eAAO,MAAM,SAAS,EAAE,UA8Cd,CAAC"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { ObjectId } from 'bson';
|
|
2
|
+
import { ECIESErrorTypeEnum } from './enumerations';
|
|
3
|
+
import { ECIESError } from './errors/ecies';
|
|
4
|
+
export const UINT8_SIZE = 1;
|
|
5
|
+
export const UINT16_SIZE = 2;
|
|
6
|
+
export const UINT16_MAX = 65535;
|
|
7
|
+
export const UINT32_SIZE = 4;
|
|
8
|
+
export const UINT32_MAX = 4294967295;
|
|
9
|
+
export const UINT64_SIZE = 8;
|
|
10
|
+
export const UINT64_MAX = 18446744073709551615n;
|
|
11
|
+
/**
|
|
12
|
+
* Standard size of a UUID v4 in bytes.
|
|
13
|
+
*/
|
|
14
|
+
export const GUID_SIZE = 16;
|
|
15
|
+
export const BACKUP_CODES = {
|
|
16
|
+
/**
|
|
17
|
+
* How many backup codes to generate for users
|
|
18
|
+
*/
|
|
19
|
+
Count: 10,
|
|
20
|
+
NormalizedHexRegex: /^[a-z0-9]{32}$/, // exactly 32 lowercase alphanumeric chars
|
|
21
|
+
DisplayRegex: /^([a-z0-9]{4}-){7}[a-z0-9]{4}$/, // xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx
|
|
22
|
+
};
|
|
23
|
+
export const PBKDF2 = {
|
|
24
|
+
ALGORITHM: 'SHA-256',
|
|
25
|
+
SALT_BYTES: 32,
|
|
26
|
+
/**
|
|
27
|
+
* Number of pbkdf2 iterations per second when hashing a password.
|
|
28
|
+
* This is the high-security default for user login operations.
|
|
29
|
+
*/
|
|
30
|
+
ITERATIONS_PER_SECOND: 1304000,
|
|
31
|
+
};
|
|
32
|
+
export const PBKDF2_PROFILES = {
|
|
33
|
+
BACKUP_CODES: {
|
|
34
|
+
hashBytes: 32,
|
|
35
|
+
saltBytes: 16,
|
|
36
|
+
iterations: 100000,
|
|
37
|
+
algorithm: 'SHA-256',
|
|
38
|
+
},
|
|
39
|
+
BROWSER_PASSWORD: {
|
|
40
|
+
hashBytes: 32,
|
|
41
|
+
saltBytes: 64,
|
|
42
|
+
iterations: 2000000,
|
|
43
|
+
algorithm: 'SHA-512',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
const ECIES_SYMMETRIC_KEY_SIZE = 32;
|
|
47
|
+
const ECIES_PUBLIC_KEY_LENGTH = 65;
|
|
48
|
+
const ECIES_RAW_PUBLIC_KEY_LENGTH = 64;
|
|
49
|
+
const ECIES_IV_SIZE = 16;
|
|
50
|
+
const ECIES_AUTH_TAG_SIZE = 16;
|
|
51
|
+
const ECIES_MULTIPLE_RECIPIENT_ID_SIZE = 16;
|
|
52
|
+
// Define the expected value for SIMPLE.FIXED_OVERHEAD_SIZE
|
|
53
|
+
const expectedSimpleOverhead = UINT8_SIZE + ECIES_PUBLIC_KEY_LENGTH + ECIES_IV_SIZE + ECIES_AUTH_TAG_SIZE;
|
|
54
|
+
// Define the expected value for MULTIPLE.FIXED_OVERHEAD_SIZE
|
|
55
|
+
// Includes: type (1) + IV (16) + auth tag (16) = 33 (no CRC, AES-GCM provides authentication)
|
|
56
|
+
const expectedMultipleOverhead = UINT8_SIZE + ECIES_IV_SIZE + ECIES_AUTH_TAG_SIZE;
|
|
57
|
+
// Update ENCRYPTED_KEY_SIZE to match Simple encryption (no CRC)
|
|
58
|
+
const expectedMultipleEncryptedKeySize = ECIES_PUBLIC_KEY_LENGTH +
|
|
59
|
+
ECIES_IV_SIZE +
|
|
60
|
+
ECIES_AUTH_TAG_SIZE +
|
|
61
|
+
ECIES_SYMMETRIC_KEY_SIZE;
|
|
62
|
+
export const ECIES = {
|
|
63
|
+
/** The elliptic curve to use for all ECDSA operations */
|
|
64
|
+
CURVE_NAME: 'secp256k1',
|
|
65
|
+
/** The primary key derivation path for HD wallets */
|
|
66
|
+
PRIMARY_KEY_DERIVATION_PATH: "m/44'/60'/0'/0/0",
|
|
67
|
+
SYMMETRIC_ALGORITHM_CONFIGURATION: 'aes-256-gcm',
|
|
68
|
+
/** Length of ECDSA signatures in bytes */
|
|
69
|
+
SIGNATURE_SIZE: 64,
|
|
70
|
+
/** Length of raw public keys in bytes (without 0x04 prefix) */
|
|
71
|
+
RAW_PUBLIC_KEY_LENGTH: ECIES_RAW_PUBLIC_KEY_LENGTH,
|
|
72
|
+
/** Length of public keys in bytes (with 0x04 prefix) */
|
|
73
|
+
PUBLIC_KEY_LENGTH: ECIES_PUBLIC_KEY_LENGTH,
|
|
74
|
+
PUBLIC_KEY_MAGIC: 0x04,
|
|
75
|
+
/** Mnemonic strength in bits. This will produce a 32-bit key for ECDSA */
|
|
76
|
+
MNEMONIC_STRENGTH: 256,
|
|
77
|
+
/** Symmetric encryption algorithm configuration */
|
|
78
|
+
SYMMETRIC: {
|
|
79
|
+
ALGORITHM: 'aes',
|
|
80
|
+
MODE: 'gcm',
|
|
81
|
+
KEY_BITS: 256,
|
|
82
|
+
KEY_SIZE: ECIES_SYMMETRIC_KEY_SIZE, // KEY_BITS / 8
|
|
83
|
+
},
|
|
84
|
+
IV_SIZE: ECIES_IV_SIZE,
|
|
85
|
+
AUTH_TAG_SIZE: ECIES_AUTH_TAG_SIZE,
|
|
86
|
+
MAX_RAW_DATA_SIZE: 9007199254740991, // 2^53 - 1 (max safe integer for JS)
|
|
87
|
+
/**
|
|
88
|
+
* Message encrypts without data length or crc
|
|
89
|
+
*/
|
|
90
|
+
SIMPLE: {
|
|
91
|
+
FIXED_OVERHEAD_SIZE: expectedSimpleOverhead, // type (1) + public key (65) + IV (16) + auth tag (16)
|
|
92
|
+
DATA_LENGTH_SIZE: 0,
|
|
93
|
+
},
|
|
94
|
+
/**
|
|
95
|
+
* Message encrypts with data length but no CRC (AES-GCM provides authentication)
|
|
96
|
+
*/
|
|
97
|
+
SINGLE: {
|
|
98
|
+
FIXED_OVERHEAD_SIZE: 106, // type (1) + public key (65) + IV (16) + auth tag (16) + data length (8)
|
|
99
|
+
DATA_LENGTH_SIZE: 8,
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* Message encrypts for multiple recipients
|
|
103
|
+
*/
|
|
104
|
+
MULTIPLE: {
|
|
105
|
+
FIXED_OVERHEAD_SIZE: expectedMultipleOverhead, // type (1) + IV (16) + auth tag (16), no CRC
|
|
106
|
+
ENCRYPTED_KEY_SIZE: expectedMultipleEncryptedKeySize, // 129
|
|
107
|
+
MAX_RECIPIENTS: 65535,
|
|
108
|
+
RECIPIENT_ID_SIZE: ECIES_MULTIPLE_RECIPIENT_ID_SIZE,
|
|
109
|
+
RECIPIENT_COUNT_SIZE: 2,
|
|
110
|
+
DATA_LENGTH_SIZE: 8,
|
|
111
|
+
},
|
|
112
|
+
ENCRYPTION_TYPE: {
|
|
113
|
+
SIMPLE: 33,
|
|
114
|
+
SINGLE: 66,
|
|
115
|
+
MULTIPLE: 99,
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
const objectIdLength = new ObjectId().toHexString().length / 2;
|
|
119
|
+
export const Constants = {
|
|
120
|
+
/**
|
|
121
|
+
* The length of a raw object ID (not the hex string representation)
|
|
122
|
+
*/
|
|
123
|
+
OBJECT_ID_LENGTH: objectIdLength,
|
|
124
|
+
UINT8_SIZE: UINT8_SIZE,
|
|
125
|
+
UINT16_SIZE: UINT16_SIZE,
|
|
126
|
+
UINT16_MAX: UINT16_MAX,
|
|
127
|
+
UINT32_SIZE: UINT32_SIZE,
|
|
128
|
+
UINT32_MAX: UINT32_MAX,
|
|
129
|
+
UINT64_SIZE: UINT64_SIZE,
|
|
130
|
+
UINT64_MAX: UINT64_MAX,
|
|
131
|
+
HEX_RADIX: 16,
|
|
132
|
+
GUID_SIZE: GUID_SIZE,
|
|
133
|
+
BACKUP_CODES: BACKUP_CODES,
|
|
134
|
+
ECIES: ECIES,
|
|
135
|
+
PBKDF2: PBKDF2,
|
|
136
|
+
PBKDF2_PROFILES: PBKDF2_PROFILES,
|
|
137
|
+
/**
|
|
138
|
+
* Number of rounds for bcrypt hashing. Higher values increase security but also consume more CPU resources.
|
|
139
|
+
*/
|
|
140
|
+
BcryptRounds: 10,
|
|
141
|
+
/**
|
|
142
|
+
* Minimum password length
|
|
143
|
+
*/
|
|
144
|
+
PasswordMinLength: 8,
|
|
145
|
+
/**
|
|
146
|
+
* The regular expression for valid passwords.
|
|
147
|
+
*/
|
|
148
|
+
PasswordRegex: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?])[A-Za-z\d!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]{8,}$/,
|
|
149
|
+
/**
|
|
150
|
+
* The regular expression for valid mnemonic phrases.
|
|
151
|
+
* BIP39 - supports 12, 15, 18, 21, or 24 word mnemonics
|
|
152
|
+
*/
|
|
153
|
+
MnemonicRegex: /^(?:\w+\s){11}\w+$|^(?:\w+\s){14}\w+$|^(?:\w+\s){17}\w+$|^(?:\w+\s){20}\w+$|^(?:\w+\s){23}\w+$/i,
|
|
154
|
+
/**
|
|
155
|
+
* Matches a 64-character hexadecimal string (SHA-256).
|
|
156
|
+
*/
|
|
157
|
+
HmacRegex: /^[a-f0-9]{64}$/,
|
|
158
|
+
};
|
|
159
|
+
if (objectIdLength !== 12) {
|
|
160
|
+
console.warn('ObjectID length may have changed, breaking encryption', objectIdLength);
|
|
161
|
+
}
|
|
162
|
+
if (ECIES.MULTIPLE.ENCRYPTED_KEY_SIZE !== 129) {
|
|
163
|
+
throw new ECIESError(ECIESErrorTypeEnum.InvalidECIESMultipleEncryptedKeySize);
|
|
164
|
+
}
|
|
165
|
+
if (ECIES.PUBLIC_KEY_LENGTH !== ECIES.RAW_PUBLIC_KEY_LENGTH + 1) {
|
|
166
|
+
throw new ECIESError(ECIESErrorTypeEnum.InvalidECIESPublicKeyLength);
|
|
167
|
+
}
|
|
168
|
+
if (ECIES.MULTIPLE.RECIPIENT_COUNT_SIZE !== UINT16_SIZE) {
|
|
169
|
+
throw new ECIESError(ECIESErrorTypeEnum.InvalidECIESMultipleRecipientCountSize);
|
|
170
|
+
}
|
|
171
|
+
if (ECIES.MULTIPLE.DATA_LENGTH_SIZE !== UINT64_SIZE) {
|
|
172
|
+
throw new ECIESError(ECIESErrorTypeEnum.InvalidECIESMultipleDataLengthSize);
|
|
173
|
+
}
|
|
174
|
+
if (ECIES.MULTIPLE.RECIPIENT_ID_SIZE !== GUID_SIZE) {
|
|
175
|
+
throw new ECIESError(ECIESErrorTypeEnum.InvalidECIESMultipleRecipientIdSize);
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EmailString represents a validated email address.
|
|
3
|
+
* It ensures that the email is not empty, does not have leading or trailing spaces,
|
|
4
|
+
* and is a valid email format.
|
|
5
|
+
*/
|
|
6
|
+
export declare class EmailString {
|
|
7
|
+
readonly email: string;
|
|
8
|
+
/**
|
|
9
|
+
* Creates an instance of EmailString.
|
|
10
|
+
* @param email - The email address to validate and store.
|
|
11
|
+
* @throws Will throw an error if the email is invalid.
|
|
12
|
+
*/
|
|
13
|
+
constructor(email: string);
|
|
14
|
+
/**
|
|
15
|
+
* Returns the email address as a string.
|
|
16
|
+
* @returns The email address.
|
|
17
|
+
*/
|
|
18
|
+
toString(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Checks if this email address is equal to another email address.
|
|
21
|
+
* @param other - The other email address to compare.
|
|
22
|
+
* @returns True if the email addresses are equal, false otherwise.
|
|
23
|
+
*/
|
|
24
|
+
equals(other: EmailString): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Converts the email address to a JSON string.
|
|
27
|
+
* @returns The email address as a JSON string.
|
|
28
|
+
*/
|
|
29
|
+
toJson(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Creates an EmailString instance from a JSON string.
|
|
32
|
+
* @param email - The JSON string representing the email address.
|
|
33
|
+
* @returns The EmailString instance.
|
|
34
|
+
*/
|
|
35
|
+
static fromJson(email: string): EmailString;
|
|
36
|
+
/**
|
|
37
|
+
* Gets the length of the email address.
|
|
38
|
+
* @returns The length of the email address.
|
|
39
|
+
*/
|
|
40
|
+
get length(): number;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=email-string.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-string.d.ts","sourceRoot":"","sources":["../src/email-string.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,qBAAa,WAAW;IACtB,SAAgB,KAAK,EAAE,MAAM,CAAC;IAE9B;;;;OAIG;gBACS,KAAK,EAAE,MAAM;IAczB;;;OAGG;IACI,QAAQ,IAAI,MAAM;IAIzB;;;;OAIG;IACI,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO;IAI1C;;;OAGG;IACI,MAAM,IAAI,MAAM;IAIvB;;;;OAIG;WACW,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;IAIlD;;;OAGG;IACH,IAAW,MAAM,IAAI,MAAM,CAE1B;CACF"}
|