favalib 0.0.11 → 0.0.13
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/build/TwoFALibError.d.mts +1 -1
- package/build/TwoFALibError.mjs +1 -1
- package/build/TwoFaLib.d.mts +6 -6
- package/build/TwoFaLib.mjs +22 -18
- package/build/interfaces/CryptoLib.d.mts +11 -11
- package/build/interfaces/OpenPgpLib.d.mts +20 -0
- package/build/interfaces/PasswordExtraDict.d.ts +2 -0
- package/build/interfaces/PasswordExtraDict.js +1 -0
- package/build/interfaces/PlatformProviders.d.mts +26 -0
- package/build/interfaces/PlatformProviders.mjs +1 -0
- package/build/interfaces/QrCodeLib.d.mts +19 -0
- package/build/interfaces/QrCodeLib.mjs +1 -0
- package/build/main.d.mts +3 -2
- package/build/{CryptoProviders/browser/index.d.mts → platformProviders/browser/cryptoLib.d.mts} +6 -6
- package/build/{CryptoProviders/browser/index.mjs → platformProviders/browser/cryptoLib.mjs} +21 -21
- package/build/platformProviders/browser/index.d.mts +6 -0
- package/build/platformProviders/browser/index.mjs +13 -0
- package/build/platformProviders/browser/openPgpLib.d.mts +20 -0
- package/build/platformProviders/browser/openPgpLib.mjs +44 -0
- package/build/platformProviders/browser/qrCodeLib.d.mts +25 -0
- package/build/platformProviders/browser/qrCodeLib.mjs +69 -0
- package/build/{CryptoProviders/node/index.d.mts → platformProviders/node/cryptoLib.d.mts} +4 -4
- package/build/{CryptoProviders/node/index.mjs → platformProviders/node/cryptoLib.mjs} +12 -12
- package/build/platformProviders/node/index.d.mts +6 -0
- package/build/platformProviders/node/index.mjs +13 -0
- package/build/platformProviders/node/openPgpLib.d.mts +20 -0
- package/build/platformProviders/node/openPgpLib.mjs +44 -0
- package/build/platformProviders/node/qrCodeLib.d.mts +28 -0
- package/build/platformProviders/node/qrCodeLib.mjs +54 -0
- package/build/subclasses/ExportImportManager.d.mts +8 -8
- package/build/subclasses/ExportImportManager.mjs +15 -15
- package/build/subclasses/LibraryLoader.d.mts +26 -12
- package/build/subclasses/LibraryLoader.mjs +26 -34
- package/build/subclasses/PersistentStorageManager.d.mts +16 -16
- package/build/subclasses/PersistentStorageManager.mjs +20 -20
- package/build/subclasses/StorageOperationsManager.d.mts +7 -7
- package/build/subclasses/StorageOperationsManager.mjs +7 -7
- package/build/subclasses/SyncManager.mjs +7 -6
- package/build/utils/creationUtils.d.mts +20 -20
- package/build/utils/creationUtils.mjs +36 -34
- package/build/utils/exportImportUtils.d.mts +5 -3
- package/build/utils/exportImportUtils.mjs +2 -12
- package/build/utils/qrUtils.d.mts +0 -16
- package/build/utils/qrUtils.mjs +2 -68
- package/build/utils/syncUtils.d.mts +3 -2
- package/build/utils/syncUtils.mjs +3 -19
- package/package.json +8 -8
- package/build/interfaces/PassphraseExtraDict.d.ts +0 -2
- /package/build/interfaces/{PassphraseExtraDict.js → OpenPgpLib.mjs} +0 -0
|
@@ -14,7 +14,7 @@ export declare class TwoFALibError extends Error {
|
|
|
14
14
|
export declare class InitializationError extends TwoFALibError {
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* Error thrown during authentication, e.g. wrong
|
|
17
|
+
* Error thrown during authentication, e.g. wrong password for locked vault.
|
|
18
18
|
*/
|
|
19
19
|
export declare class AuthenticationError extends TwoFALibError {
|
|
20
20
|
}
|
package/build/TwoFALibError.mjs
CHANGED
|
@@ -18,7 +18,7 @@ export class TwoFALibError extends Error {
|
|
|
18
18
|
export class InitializationError extends TwoFALibError {
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Error thrown during authentication, e.g. wrong
|
|
21
|
+
* Error thrown during authentication, e.g. wrong password for locked vault.
|
|
22
22
|
*/
|
|
23
23
|
export class AuthenticationError extends TwoFALibError {
|
|
24
24
|
}
|
package/build/TwoFaLib.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { TypedEventTarget } from 'typescript-event-target';
|
|
2
|
-
import type
|
|
2
|
+
import type { PlatformProviders } from './interfaces/PlatformProviders.mjs';
|
|
3
3
|
import type { EncryptedPrivateKey, EncryptedSymmetricKey, PrivateKey, PublicKey, Salt, SymmetricKey } from './interfaces/CryptoLib.mjs';
|
|
4
4
|
import type { DeviceFriendlyName, DeviceType } from './interfaces/SyncTypes.mjs';
|
|
5
5
|
import type { TwoFaLibEventMapEvents } from './interfaces/Events.mjs';
|
|
6
|
-
import type {
|
|
6
|
+
import type { PasswordExtraDict } from './interfaces/PasswordExtraDict.js';
|
|
7
7
|
import type { Vault, VaultSyncState } from './interfaces/Vault.mjs';
|
|
8
8
|
import type { SaveFunction } from './interfaces/SaveFunction.mjs';
|
|
9
9
|
import type { FavaMeta } from './interfaces/FavaMeta.mjs';
|
|
@@ -34,8 +34,8 @@ declare class TwoFaLib extends TypedEventTarget<TwoFaLibEventMapEvents> {
|
|
|
34
34
|
/**
|
|
35
35
|
* Constructs a new instance of TwoFaLib. If a serverUrl is provided, the library will use it for its sync operations.
|
|
36
36
|
* @param deviceType - The identifier for this device type (e.g. 2fa-cli).
|
|
37
|
-
* @param
|
|
38
|
-
* @param
|
|
37
|
+
* @param platformProviders - The platform-specific providers containing CryptoLib and other providers.
|
|
38
|
+
* @param passwordExtraDict - Additional words to be used for password strength evaluation.
|
|
39
39
|
* @param privateKey - The private key used for cryptographic operations.
|
|
40
40
|
* @param symmetricKey - The symmetric key used for cryptographic operations.
|
|
41
41
|
* @param encryptedPrivateKey - The encrypted private key
|
|
@@ -48,9 +48,9 @@ declare class TwoFaLib extends TypedEventTarget<TwoFaLibEventMapEvents> {
|
|
|
48
48
|
* @param syncState - The state of the sync, includes the serverUrl
|
|
49
49
|
* @returns A promise that resolves when initialization is complete.
|
|
50
50
|
* @throws {InitializationError} If some parameter has an invalid value
|
|
51
|
-
* @throws {AuthenticationError} If the provided
|
|
51
|
+
* @throws {AuthenticationError} If the provided password is incorrect.
|
|
52
52
|
*/
|
|
53
|
-
constructor(deviceType: DeviceType,
|
|
53
|
+
constructor(deviceType: DeviceType, platformProviders: PlatformProviders, passwordExtraDict: PasswordExtraDict, privateKey: PrivateKey, symmetricKey: SymmetricKey, encryptedPrivateKey: EncryptedPrivateKey, encryptedSymmetricKey: EncryptedSymmetricKey, salt: Salt, publicKey: PublicKey, favaMeta: FavaMeta, vault?: Vault, saveFunction?: SaveFunction, syncState?: VaultSyncState);
|
|
54
54
|
/**
|
|
55
55
|
* @returns The persistent storage manager instance which can be used to store data.
|
|
56
56
|
*/
|
package/build/TwoFaLib.mjs
CHANGED
|
@@ -30,8 +30,8 @@ class TwoFaLib extends TypedEventTarget {
|
|
|
30
30
|
/**
|
|
31
31
|
* Constructs a new instance of TwoFaLib. If a serverUrl is provided, the library will use it for its sync operations.
|
|
32
32
|
* @param deviceType - The identifier for this device type (e.g. 2fa-cli).
|
|
33
|
-
* @param
|
|
34
|
-
* @param
|
|
33
|
+
* @param platformProviders - The platform-specific providers containing CryptoLib and other providers.
|
|
34
|
+
* @param passwordExtraDict - Additional words to be used for password strength evaluation.
|
|
35
35
|
* @param privateKey - The private key used for cryptographic operations.
|
|
36
36
|
* @param symmetricKey - The symmetric key used for cryptographic operations.
|
|
37
37
|
* @param encryptedPrivateKey - The encrypted private key
|
|
@@ -44,9 +44,9 @@ class TwoFaLib extends TypedEventTarget {
|
|
|
44
44
|
* @param syncState - The state of the sync, includes the serverUrl
|
|
45
45
|
* @returns A promise that resolves when initialization is complete.
|
|
46
46
|
* @throws {InitializationError} If some parameter has an invalid value
|
|
47
|
-
* @throws {AuthenticationError} If the provided
|
|
47
|
+
* @throws {AuthenticationError} If the provided password is incorrect.
|
|
48
48
|
*/
|
|
49
|
-
constructor(deviceType,
|
|
49
|
+
constructor(deviceType, platformProviders, passwordExtraDict, privateKey, symmetricKey, encryptedPrivateKey, encryptedSymmetricKey, salt, publicKey, favaMeta, vault, saveFunction, syncState) {
|
|
50
50
|
super();
|
|
51
51
|
if (!deviceType) {
|
|
52
52
|
throw new InitializationError('Device type is required');
|
|
@@ -61,8 +61,8 @@ class TwoFaLib extends TypedEventTarget {
|
|
|
61
61
|
favaMeta.deviceFriendlyName.length > 256) {
|
|
62
62
|
throw new InitializationError('Device friendly name is too long, max 256 characters');
|
|
63
63
|
}
|
|
64
|
-
if (
|
|
65
|
-
throw new InitializationError('
|
|
64
|
+
if (passwordExtraDict?.length === 0) {
|
|
65
|
+
throw new InitializationError('Password extra dictionary is required and must contain at least one element (eg phone)');
|
|
66
66
|
}
|
|
67
67
|
this.favaMeta = favaMeta;
|
|
68
68
|
this.deviceType = deviceType;
|
|
@@ -70,10 +70,10 @@ class TwoFaLib extends TypedEventTarget {
|
|
|
70
70
|
this.privateKey = privateKey;
|
|
71
71
|
this.mediator = new TwoFaLibMediator();
|
|
72
72
|
this.mediator.registerComponents([
|
|
73
|
-
['libraryLoader', new LibraryLoader(
|
|
73
|
+
['libraryLoader', new LibraryLoader(platformProviders)],
|
|
74
74
|
[
|
|
75
75
|
'persistentStorageManager',
|
|
76
|
-
new PersistentStorageManager(this.mediator,
|
|
76
|
+
new PersistentStorageManager(this.mediator, passwordExtraDict, favaMeta, privateKey, symmetricKey, encryptedPrivateKey, encryptedSymmetricKey, salt, saveFunction),
|
|
77
77
|
],
|
|
78
78
|
['vaultDataManager', new VaultDataManager(this.mediator)],
|
|
79
79
|
['commandManager', new CommandManager(this.mediator)],
|
|
@@ -81,7 +81,7 @@ class TwoFaLib extends TypedEventTarget {
|
|
|
81
81
|
['storageOperationsManager', new StorageOperationsManager(this.mediator)],
|
|
82
82
|
[
|
|
83
83
|
'exportImportManager',
|
|
84
|
-
new ExportImportManager(this.mediator,
|
|
84
|
+
new ExportImportManager(this.mediator, passwordExtraDict),
|
|
85
85
|
],
|
|
86
86
|
['dispatchLibEvent', this.dispatchLibEvent.bind(this)],
|
|
87
87
|
['log', this.log.bind(this)],
|
|
@@ -153,9 +153,10 @@ class TwoFaLib extends TypedEventTarget {
|
|
|
153
153
|
* @param force - Force setting the sync server url, even if no connection can be made
|
|
154
154
|
*/
|
|
155
155
|
async setSyncServerUrl(serverUrl, force = false) {
|
|
156
|
-
|
|
156
|
+
const oldSyncManager = this.sync;
|
|
157
|
+
if (oldSyncManager) {
|
|
157
158
|
// close connection so no data is send to the old syncServer
|
|
158
|
-
|
|
159
|
+
oldSyncManager.closeServerConnection();
|
|
159
160
|
}
|
|
160
161
|
const newSyncState = {
|
|
161
162
|
serverUrl,
|
|
@@ -163,6 +164,9 @@ class TwoFaLib extends TypedEventTarget {
|
|
|
163
164
|
commandSendQueue: [],
|
|
164
165
|
};
|
|
165
166
|
const newSyncManager = new SyncManager(this.mediator, this.publicKey, this.privateKey, this.favaMeta, newSyncState, this.deviceType);
|
|
167
|
+
// Temporarily register the new sync manager so its events can be heard
|
|
168
|
+
this.mediator.unRegisterComponent('syncManager');
|
|
169
|
+
this.mediator.registerComponent('syncManager', newSyncManager);
|
|
166
170
|
const success = await new Promise((resolve) => {
|
|
167
171
|
this.addEventListener(TwoFaLibEvent.ConnectionToSyncServerStatusChanged, (event) => {
|
|
168
172
|
if (event.detail.newStatus === ConnectionStatus.CONNECTED) {
|
|
@@ -178,18 +182,18 @@ class TwoFaLib extends TypedEventTarget {
|
|
|
178
182
|
this.log('warning', `Failed to connect to server at ${serverUrl}, force setting`);
|
|
179
183
|
}
|
|
180
184
|
else {
|
|
181
|
-
|
|
185
|
+
// Close the new sync manager and restore the old one
|
|
186
|
+
newSyncManager.closeServerConnection();
|
|
187
|
+
this.mediator.unRegisterComponent('syncManager');
|
|
188
|
+
if (oldSyncManager) {
|
|
182
189
|
// re-establish old connection
|
|
183
|
-
this.
|
|
190
|
+
this.mediator.registerComponent('syncManager', oldSyncManager);
|
|
191
|
+
oldSyncManager.initServerConnection();
|
|
184
192
|
}
|
|
185
|
-
newSyncManager.closeServerConnection();
|
|
186
193
|
throw new SyncError(`Failed to connect to server at ${serverUrl}, not setting`);
|
|
187
194
|
}
|
|
188
195
|
}
|
|
189
|
-
// connection succeeded (or force=true)
|
|
190
|
-
// switch to the new syncManager
|
|
191
|
-
this.mediator.unRegisterComponent('syncManager');
|
|
192
|
-
this.mediator.registerComponent('syncManager', newSyncManager);
|
|
196
|
+
// connection succeeded (or force=true) - new sync manager is already registered
|
|
193
197
|
// save
|
|
194
198
|
await this.persistentStorageManager.save();
|
|
195
199
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Tagged } from 'type-fest';
|
|
2
2
|
export type Encrypted<T extends string> = Tagged<T, 'Encrypted'>;
|
|
3
|
-
/** Represents a
|
|
4
|
-
export type
|
|
5
|
-
/** Represents a
|
|
6
|
-
export type
|
|
3
|
+
/** Represents a password */
|
|
4
|
+
export type Password = Tagged<string, 'Password'>;
|
|
5
|
+
/** Represents a passwordHash */
|
|
6
|
+
export type PasswordHash = Tagged<string, 'PasswordHash'>;
|
|
7
7
|
/** Represents a salt (base64 encoded) */
|
|
8
8
|
export type Salt = Tagged<string, 'Salt'>;
|
|
9
9
|
/** Represents a private key */
|
|
@@ -33,12 +33,12 @@ interface CryptoLib {
|
|
|
33
33
|
getRandomBytes: (count: number) => Promise<Uint8Array>;
|
|
34
34
|
/**
|
|
35
35
|
* Creates the keys required for further operations.
|
|
36
|
-
* It first creates a public/private key pair, with the private key being encrypted using the
|
|
36
|
+
* It first creates a public/private key pair, with the private key being encrypted using the password.
|
|
37
37
|
* It then generates a symmetricKey. It will then encrypt this symmetricKey using the generated public key.
|
|
38
|
-
* @param
|
|
38
|
+
* @param password - The password to encrypt the private key with
|
|
39
39
|
* @returns A promise that resolves to an object containing the encrypted private key, encrypted symmetric key and public key
|
|
40
40
|
*/
|
|
41
|
-
createKeys: (
|
|
41
|
+
createKeys: (password: Password) => Promise<{
|
|
42
42
|
privateKey: PrivateKey;
|
|
43
43
|
symmetricKey: SymmetricKey;
|
|
44
44
|
encryptedPrivateKey: EncryptedPrivateKey;
|
|
@@ -50,10 +50,10 @@ interface CryptoLib {
|
|
|
50
50
|
* Decrypts the keys required for further operations
|
|
51
51
|
* @param encryptedPrivateKey - The encrypted private key
|
|
52
52
|
* @param encryptedSymmetricKey - The encrypted symmetric key
|
|
53
|
-
* @param
|
|
53
|
+
* @param password - The password to decrypt the private key with
|
|
54
54
|
* @returns A promise that resolves to an object containing the decrypted private, symmetric and public key
|
|
55
55
|
*/
|
|
56
|
-
decryptKeys: (encryptedPrivateKey: EncryptedPrivateKey, encryptedSymmetricKey: EncryptedSymmetricKey, salt: Salt,
|
|
56
|
+
decryptKeys: (encryptedPrivateKey: EncryptedPrivateKey, encryptedSymmetricKey: EncryptedSymmetricKey, salt: Salt, password: Password) => Promise<{
|
|
57
57
|
privateKey: PrivateKey;
|
|
58
58
|
symmetricKey: SymmetricKey;
|
|
59
59
|
publicKey: PublicKey;
|
|
@@ -62,10 +62,10 @@ interface CryptoLib {
|
|
|
62
62
|
* Encrypts the keys required for further operation
|
|
63
63
|
* @param privateKey - The private key to encrypt
|
|
64
64
|
* @param symmetricKey - The symmetric key to encrypt
|
|
65
|
-
* @param
|
|
65
|
+
* @param password - The password to encrypt the private key with
|
|
66
66
|
* @returns A promise that resolves to an object containing the encrypted private and symmetricKey key
|
|
67
67
|
*/
|
|
68
|
-
encryptKeys: (privateKey: PrivateKey, symmetricKey: SymmetricKey, salt: Salt,
|
|
68
|
+
encryptKeys: (privateKey: PrivateKey, symmetricKey: SymmetricKey, salt: Salt, password: Password) => Promise<{
|
|
69
69
|
encryptedPrivateKey: EncryptedPrivateKey;
|
|
70
70
|
encryptedSymmetricKey: EncryptedSymmetricKey;
|
|
71
71
|
}>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for OpenPGP operations
|
|
3
|
+
*/
|
|
4
|
+
export interface OpenPgpLib {
|
|
5
|
+
/**
|
|
6
|
+
* Encrypts the given data using OpenPGP.
|
|
7
|
+
* @param data - The data to encrypt.
|
|
8
|
+
* @param password - The password to use for encryption.
|
|
9
|
+
* @returns A promise that resolves to the encrypted data.
|
|
10
|
+
*/
|
|
11
|
+
encrypt(data: string, password: string): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Decrypts the given data using OpenPGP.
|
|
14
|
+
* @param data - The data to decrypt.
|
|
15
|
+
* @param password - The password to use for decryption.
|
|
16
|
+
* @returns A promise that resolves to the decrypted data.
|
|
17
|
+
*/
|
|
18
|
+
decrypt(data: string, password: string): Promise<string>;
|
|
19
|
+
}
|
|
20
|
+
export default OpenPgpLib;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type CryptoLib from './CryptoLib.mjs';
|
|
2
|
+
import type { QrCodeLib } from './QrCodeLib.mjs';
|
|
3
|
+
import type { OpenPgpLib } from './OpenPgpLib.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* Interface for platform-specific providers
|
|
6
|
+
* Includes platform-specific implementations for various libraries
|
|
7
|
+
*/
|
|
8
|
+
export interface PlatformProviders {
|
|
9
|
+
/**
|
|
10
|
+
* Cryptographic operations provider
|
|
11
|
+
*/
|
|
12
|
+
CryptoLib: new () => CryptoLib;
|
|
13
|
+
/**
|
|
14
|
+
* WebSocket library
|
|
15
|
+
*/
|
|
16
|
+
WebSocketLib: () => typeof WebSocket;
|
|
17
|
+
/**
|
|
18
|
+
* QR code generation library with platform-specific extensions
|
|
19
|
+
*/
|
|
20
|
+
QrCodeLib: new () => QrCodeLib;
|
|
21
|
+
/**
|
|
22
|
+
* OpenPGP encryption library
|
|
23
|
+
*/
|
|
24
|
+
OpenPgpLib: new () => OpenPgpLib;
|
|
25
|
+
}
|
|
26
|
+
export default PlatformProviders;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ImageData } from 'canvas';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for QR code operations
|
|
4
|
+
*/
|
|
5
|
+
export interface QrCodeLib {
|
|
6
|
+
/**
|
|
7
|
+
* Generates a QR code as a data URL.
|
|
8
|
+
* @param text - The text to encode.
|
|
9
|
+
* @returns A promise that resolves to a data URL string.
|
|
10
|
+
*/
|
|
11
|
+
toDataURL(text: string): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Gets ImageData from various input types for QR code processing.
|
|
14
|
+
* @param imageInput - The image input (string URL, File, or Uint8Array).
|
|
15
|
+
* @returns A promise that resolves to ImageData.
|
|
16
|
+
*/
|
|
17
|
+
getImageDataFromInput(imageInput: string | File | Uint8Array): Promise<ImageData>;
|
|
18
|
+
}
|
|
19
|
+
export default QrCodeLib;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/build/main.d.mts
CHANGED
|
@@ -2,12 +2,13 @@ import TwoFaLib from './TwoFaLib.mjs';
|
|
|
2
2
|
import type Entry from './interfaces/Entry.mjs';
|
|
3
3
|
import type { EntryId, NewEntry, EntryMeta, EntryType, TotpPayload, Token, EntryMetaWithToken } from './interfaces/Entry.mjs';
|
|
4
4
|
import type CryptoLib from './interfaces/CryptoLib.mjs';
|
|
5
|
-
import type { Encrypted, EncryptedPrivateKey, EncryptedSymmetricKey, EncryptedPublicKey, PrivateKey, SymmetricKey, PublicKey,
|
|
5
|
+
import type { Encrypted, EncryptedPrivateKey, EncryptedSymmetricKey, EncryptedPublicKey, PrivateKey, SymmetricKey, PublicKey, Password, Salt } from './interfaces/CryptoLib.mjs';
|
|
6
6
|
import type { PublicSyncDevice, DeviceId, DeviceType, DeviceFriendlyName, DeviceInfo } from './interfaces/SyncTypes.mjs';
|
|
7
7
|
import type { EncryptedVaultStateString, LockedRepresentationString } from './interfaces/Vault.mjs';
|
|
8
8
|
import type { SaveFunction } from './interfaces/SaveFunction.mjs';
|
|
9
|
+
import type { PlatformProviders } from './interfaces/PlatformProviders.mjs';
|
|
9
10
|
import { TwoFALibError, InitializationError, AuthenticationError, EntryNotFoundError, TokenGenerationError } from './TwoFALibError.mjs';
|
|
10
11
|
import { TwoFaLibEvent } from './TwoFaLibEvent.mjs';
|
|
11
12
|
import { getTwoFaLibVaultCreationUtils } from './utils/creationUtils.mjs';
|
|
12
13
|
export { TwoFaLib, TwoFALibError, getTwoFaLibVaultCreationUtils, InitializationError, AuthenticationError, EntryNotFoundError, TokenGenerationError, TwoFaLibEvent, };
|
|
13
|
-
export type { Entry, EntryId, NewEntry, EntryMeta, EntryMetaWithToken, EntryType, TotpPayload, Token, EncryptedVaultStateString, LockedRepresentationString, CryptoLib, Encrypted, EncryptedPrivateKey, EncryptedPublicKey, EncryptedSymmetricKey, PrivateKey, SymmetricKey, PublicKey,
|
|
14
|
+
export type { Entry, EntryId, NewEntry, EntryMeta, EntryMetaWithToken, EntryType, TotpPayload, Token, EncryptedVaultStateString, LockedRepresentationString, CryptoLib, Encrypted, EncryptedPrivateKey, EncryptedPublicKey, EncryptedSymmetricKey, PrivateKey, SymmetricKey, PublicKey, Password, Salt, DeviceId, DeviceType, DeviceFriendlyName, DeviceInfo, PublicSyncDevice, SaveFunction, PlatformProviders, };
|
package/build/{CryptoProviders/browser/index.d.mts → platformProviders/browser/cryptoLib.d.mts}
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type CryptoLib from '../../interfaces/CryptoLib.mjs';
|
|
2
|
-
import type { Encrypted, EncryptedPrivateKey, EncryptedSymmetricKey,
|
|
2
|
+
import type { Encrypted, EncryptedPrivateKey, EncryptedSymmetricKey, Password, PasswordHash, PrivateKey, PublicKey, Salt, SymmetricKey, SyncKey } from '../../interfaces/CryptoLib.mjs';
|
|
3
3
|
/**
|
|
4
4
|
* Create a password hash
|
|
5
5
|
* @param salt - The salt to use
|
|
6
|
-
* @param
|
|
6
|
+
* @param password - The password to hash
|
|
7
7
|
* @returns The calculated password hash
|
|
8
8
|
*/
|
|
9
|
-
export declare const
|
|
9
|
+
export declare const generatePasswordHash: (salt: Salt, password: string) => Promise<PasswordHash>;
|
|
10
10
|
/**
|
|
11
11
|
* @inheritdoc
|
|
12
12
|
*/
|
|
@@ -18,7 +18,7 @@ declare class BrowserCryptoLib implements CryptoLib {
|
|
|
18
18
|
/**
|
|
19
19
|
* @inheritdoc
|
|
20
20
|
*/
|
|
21
|
-
createKeys(
|
|
21
|
+
createKeys(password: Password): Promise<{
|
|
22
22
|
privateKey: PrivateKey;
|
|
23
23
|
symmetricKey: SymmetricKey;
|
|
24
24
|
encryptedPrivateKey: EncryptedPrivateKey;
|
|
@@ -29,14 +29,14 @@ declare class BrowserCryptoLib implements CryptoLib {
|
|
|
29
29
|
/**
|
|
30
30
|
* @inheritdoc
|
|
31
31
|
*/
|
|
32
|
-
encryptKeys(privateKey: PrivateKey, symmetricKey: SymmetricKey, salt: Salt,
|
|
32
|
+
encryptKeys(privateKey: PrivateKey, symmetricKey: SymmetricKey, salt: Salt, password: Password): Promise<{
|
|
33
33
|
encryptedPrivateKey: EncryptedPrivateKey;
|
|
34
34
|
encryptedSymmetricKey: EncryptedSymmetricKey;
|
|
35
35
|
}>;
|
|
36
36
|
/**
|
|
37
37
|
* @inheritdoc
|
|
38
38
|
*/
|
|
39
|
-
decryptKeys(encryptedPrivateKey: EncryptedPrivateKey, encryptedSymmetricKey: EncryptedSymmetricKey, salt: Salt,
|
|
39
|
+
decryptKeys(encryptedPrivateKey: EncryptedPrivateKey, encryptedSymmetricKey: EncryptedSymmetricKey, salt: Salt, password: Password): Promise<{
|
|
40
40
|
privateKey: PrivateKey;
|
|
41
41
|
publicKey: PublicKey;
|
|
42
42
|
symmetricKey: SymmetricKey;
|
|
@@ -14,12 +14,12 @@ const normalizeLineEndings = (str) => {
|
|
|
14
14
|
/**
|
|
15
15
|
* Create a password hash
|
|
16
16
|
* @param salt - The salt to use
|
|
17
|
-
* @param
|
|
17
|
+
* @param password - The password to hash
|
|
18
18
|
* @returns The calculated password hash
|
|
19
19
|
*/
|
|
20
|
-
export const
|
|
20
|
+
export const generatePasswordHash = (salt, password) => {
|
|
21
21
|
return argon2id({
|
|
22
|
-
password
|
|
22
|
+
password,
|
|
23
23
|
salt,
|
|
24
24
|
parallelism: 1,
|
|
25
25
|
iterations: 256,
|
|
@@ -41,12 +41,12 @@ class BrowserCryptoLib {
|
|
|
41
41
|
/**
|
|
42
42
|
* @inheritdoc
|
|
43
43
|
*/
|
|
44
|
-
async createKeys(
|
|
44
|
+
async createKeys(password) {
|
|
45
45
|
// create random salt
|
|
46
46
|
const salt = uint8ArrayToBase64(window.crypto.getRandomValues(new Uint8Array(16)));
|
|
47
47
|
// create passwordHash
|
|
48
|
-
const
|
|
49
|
-
const { privateKey, encryptedPrivateKey, publicKey } = await this.createKeyPair(
|
|
48
|
+
const passwordHash = await generatePasswordHash(salt, password);
|
|
49
|
+
const { privateKey, encryptedPrivateKey, publicKey } = await this.createKeyPair(passwordHash);
|
|
50
50
|
const symmetricKey = await this.createSymmetricKey();
|
|
51
51
|
const encryptedSymmetricKey = await this.encrypt(publicKey, symmetricKey);
|
|
52
52
|
return {
|
|
@@ -61,10 +61,10 @@ class BrowserCryptoLib {
|
|
|
61
61
|
/**
|
|
62
62
|
* @inheritdoc
|
|
63
63
|
*/
|
|
64
|
-
async encryptKeys(privateKey, symmetricKey, salt,
|
|
64
|
+
async encryptKeys(privateKey, symmetricKey, salt, password) {
|
|
65
65
|
// recreate passwordHash
|
|
66
|
-
const
|
|
67
|
-
const encryptedPrivateKey = await this.encryptPrivateKey(privateKey,
|
|
66
|
+
const passwordHash = await generatePasswordHash(salt, password);
|
|
67
|
+
const encryptedPrivateKey = await this.encryptPrivateKey(privateKey, passwordHash);
|
|
68
68
|
const publicKey = await this.getPublicKeyFromPrivateKey(privateKey);
|
|
69
69
|
const encryptedSymmetricKey = await this.encrypt(publicKey, symmetricKey);
|
|
70
70
|
return {
|
|
@@ -75,10 +75,10 @@ class BrowserCryptoLib {
|
|
|
75
75
|
/**
|
|
76
76
|
* @inheritdoc
|
|
77
77
|
*/
|
|
78
|
-
async decryptKeys(encryptedPrivateKey, encryptedSymmetricKey, salt,
|
|
78
|
+
async decryptKeys(encryptedPrivateKey, encryptedSymmetricKey, salt, password) {
|
|
79
79
|
// recreate passwordHash
|
|
80
|
-
const
|
|
81
|
-
const { privateKey, publicKey } = await this.decryptPrivateKey(encryptedPrivateKey,
|
|
80
|
+
const passwordHash = await generatePasswordHash(salt, password);
|
|
81
|
+
const { privateKey, publicKey } = await this.decryptPrivateKey(encryptedPrivateKey, passwordHash);
|
|
82
82
|
const symmetricKey = (await this.decrypt(privateKey, encryptedSymmetricKey));
|
|
83
83
|
return { privateKey, publicKey, symmetricKey };
|
|
84
84
|
}
|
|
@@ -146,18 +146,18 @@ class BrowserCryptoLib {
|
|
|
146
146
|
});
|
|
147
147
|
return uint8ArrayToBase64(key);
|
|
148
148
|
}
|
|
149
|
-
async encryptPrivateKey(privateKey,
|
|
149
|
+
async encryptPrivateKey(privateKey, passwordHash) {
|
|
150
150
|
const privateKeyObj = forge.pki.privateKeyFromPem(privateKey);
|
|
151
|
-
const encryptedPrivateKey = forge.pki.encryptRsaPrivateKey(privateKeyObj,
|
|
151
|
+
const encryptedPrivateKey = forge.pki.encryptRsaPrivateKey(privateKeyObj, passwordHash, {
|
|
152
152
|
algorithm: 'aes256',
|
|
153
153
|
});
|
|
154
154
|
return Promise.resolve(encryptedPrivateKey);
|
|
155
155
|
}
|
|
156
|
-
async decryptPrivateKey(encryptedPrivateKey,
|
|
156
|
+
async decryptPrivateKey(encryptedPrivateKey, passwordHash) {
|
|
157
157
|
try {
|
|
158
|
-
const privateKeyPem = forge.pki.decryptRsaPrivateKey(encryptedPrivateKey,
|
|
158
|
+
const privateKeyPem = forge.pki.decryptRsaPrivateKey(encryptedPrivateKey, passwordHash);
|
|
159
159
|
if (!privateKeyPem) {
|
|
160
|
-
throw new CryptoError('Invalid
|
|
160
|
+
throw new CryptoError('Invalid password');
|
|
161
161
|
}
|
|
162
162
|
const privateKey = forge.pki.privateKeyToPem(privateKeyPem);
|
|
163
163
|
const publicKey = forge.pki.publicKeyToPem(forge.pki.setRsaPublicKey(privateKeyPem.n, privateKeyPem.e));
|
|
@@ -169,8 +169,8 @@ class BrowserCryptoLib {
|
|
|
169
169
|
catch (err) {
|
|
170
170
|
// eslint-disable-next-line no-restricted-globals
|
|
171
171
|
if (err instanceof Error) {
|
|
172
|
-
if (err.message === 'Invalid
|
|
173
|
-
throw new CryptoError('Invalid
|
|
172
|
+
if (err.message === 'Invalid password') {
|
|
173
|
+
throw new CryptoError('Invalid password');
|
|
174
174
|
}
|
|
175
175
|
if (err.message.includes('Unsupported private key')) {
|
|
176
176
|
throw new CryptoError('Invalid private key');
|
|
@@ -179,7 +179,7 @@ class BrowserCryptoLib {
|
|
|
179
179
|
throw err;
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
|
-
async createKeyPair(
|
|
182
|
+
async createKeyPair(password) {
|
|
183
183
|
return new Promise((resolve, reject) => {
|
|
184
184
|
forge.pki.rsa.generateKeyPair({ bits: 4096 }, (err, keyPair) => {
|
|
185
185
|
if (err) {
|
|
@@ -188,7 +188,7 @@ class BrowserCryptoLib {
|
|
|
188
188
|
else {
|
|
189
189
|
const publicKey = forge.pki.publicKeyToPem(keyPair.publicKey);
|
|
190
190
|
const privateKey = forge.pki.privateKeyToPem(keyPair.privateKey);
|
|
191
|
-
const encryptedPrivateKey = forge.pki.encryptRsaPrivateKey(keyPair.privateKey,
|
|
191
|
+
const encryptedPrivateKey = forge.pki.encryptRsaPrivateKey(keyPair.privateKey, password, {
|
|
192
192
|
algorithm: 'aes256',
|
|
193
193
|
});
|
|
194
194
|
resolve({
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import BrowserCryptoLib from './cryptoLib.mjs';
|
|
2
|
+
import { BrowserQrCodeLib } from './qrCodeLib.mjs';
|
|
3
|
+
import { BrowserOpenPgpLib } from './openPgpLib.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* Browser-specific platform providers
|
|
6
|
+
*/
|
|
7
|
+
export const browserProviders = {
|
|
8
|
+
CryptoLib: BrowserCryptoLib,
|
|
9
|
+
WebSocketLib: () => WebSocket,
|
|
10
|
+
QrCodeLib: BrowserQrCodeLib,
|
|
11
|
+
OpenPgpLib: BrowserOpenPgpLib,
|
|
12
|
+
};
|
|
13
|
+
export default browserProviders;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { OpenPgpLib } from '../../interfaces/OpenPgpLib.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* Browser implementation of OpenPGP library wrapper
|
|
4
|
+
*/
|
|
5
|
+
export declare class BrowserOpenPgpLib implements OpenPgpLib {
|
|
6
|
+
private openPgpModule;
|
|
7
|
+
/**
|
|
8
|
+
* Gets the OpenPGP module, loading it if necessary
|
|
9
|
+
* @returns Promise that resolves to the OpenPGP module
|
|
10
|
+
*/
|
|
11
|
+
private getOpenPgpModule;
|
|
12
|
+
/**
|
|
13
|
+
* @inheritdoc
|
|
14
|
+
*/
|
|
15
|
+
encrypt(data: string, password: string): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* @inheritdoc
|
|
18
|
+
*/
|
|
19
|
+
decrypt(data: string, password: string): Promise<string>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser implementation of OpenPGP library wrapper
|
|
3
|
+
*/
|
|
4
|
+
export class BrowserOpenPgpLib {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.openPgpModule = null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Gets the OpenPGP module, loading it if necessary
|
|
10
|
+
* @returns Promise that resolves to the OpenPGP module
|
|
11
|
+
*/
|
|
12
|
+
async getOpenPgpModule() {
|
|
13
|
+
if (!this.openPgpModule) {
|
|
14
|
+
this.openPgpModule = await import('openpgp');
|
|
15
|
+
// enable Authenticated Encryption with Associated Data
|
|
16
|
+
this.openPgpModule.config.aeadProtect = true;
|
|
17
|
+
}
|
|
18
|
+
return this.openPgpModule;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @inheritdoc
|
|
22
|
+
*/
|
|
23
|
+
async encrypt(data, password) {
|
|
24
|
+
const openPgp = await this.getOpenPgpModule();
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
26
|
+
const encrypted = await openPgp.encrypt({
|
|
27
|
+
message: await openPgp.createMessage({ text: data }),
|
|
28
|
+
passwords: [password],
|
|
29
|
+
format: 'armored',
|
|
30
|
+
});
|
|
31
|
+
return encrypted;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @inheritdoc
|
|
35
|
+
*/
|
|
36
|
+
async decrypt(data, password) {
|
|
37
|
+
const openPgp = await this.getOpenPgpModule();
|
|
38
|
+
const decrypted = await openPgp.decrypt({
|
|
39
|
+
message: await openPgp.readMessage({ armoredMessage: data }),
|
|
40
|
+
passwords: [password],
|
|
41
|
+
});
|
|
42
|
+
return decrypted.data;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ImageData } from 'canvas';
|
|
2
|
+
import type { QrCodeLib } from '../../interfaces/QrCodeLib.mjs';
|
|
3
|
+
/**
|
|
4
|
+
* Gets the ImageData from an image, for browser environments.
|
|
5
|
+
* This ImageData is then further processed to get QR codes.
|
|
6
|
+
* @param input - The image to get the ImageData from.
|
|
7
|
+
* @returns A promise that resolves to the ImageData.
|
|
8
|
+
*/
|
|
9
|
+
export declare const getImageDataFromInput: (input: string | File | Uint8Array) => Promise<ImageData>;
|
|
10
|
+
/**
|
|
11
|
+
* Browser implementation of QR code library wrapper
|
|
12
|
+
*/
|
|
13
|
+
export declare class BrowserQrCodeLib implements QrCodeLib {
|
|
14
|
+
private qrCodeModule;
|
|
15
|
+
/**
|
|
16
|
+
* Gets the QR code module, loading it if necessary
|
|
17
|
+
* @returns Promise that resolves to the QR code module
|
|
18
|
+
*/
|
|
19
|
+
private getQrCodeModule;
|
|
20
|
+
/**
|
|
21
|
+
* @inheritdoc
|
|
22
|
+
*/
|
|
23
|
+
toDataURL(text: string): Promise<string>;
|
|
24
|
+
getImageDataFromInput: (input: string | File | Uint8Array) => Promise<ImageData>;
|
|
25
|
+
}
|