favalib 0.0.10 → 0.0.12

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.
Files changed (43) hide show
  1. package/build/Command/commandConstructors.d.mts +2 -2
  2. package/build/Command/commandConstructors.mjs +2 -2
  3. package/build/Command/commands/ChangeDeviceInfoCommand.d.mts +6 -6
  4. package/build/Command/commands/ChangeDeviceInfoCommand.mjs +3 -3
  5. package/build/TwoFaLib.d.mts +3 -3
  6. package/build/TwoFaLib.mjs +16 -12
  7. package/build/interfaces/CommandTypes.d.mts +4 -4
  8. package/build/interfaces/OpenPgpLib.d.mts +20 -0
  9. package/build/interfaces/OpenPgpLib.mjs +1 -0
  10. package/build/interfaces/PlatformProviders.d.mts +26 -0
  11. package/build/interfaces/PlatformProviders.mjs +1 -0
  12. package/build/interfaces/QrCodeLib.d.mts +19 -0
  13. package/build/interfaces/QrCodeLib.mjs +1 -0
  14. package/build/main.d.mts +2 -1
  15. package/build/platformProviders/browser/index.d.mts +6 -0
  16. package/build/platformProviders/browser/index.mjs +13 -0
  17. package/build/platformProviders/browser/openPgpLib.d.mts +20 -0
  18. package/build/platformProviders/browser/openPgpLib.mjs +44 -0
  19. package/build/platformProviders/browser/qrCodeLib.d.mts +25 -0
  20. package/build/platformProviders/browser/qrCodeLib.mjs +69 -0
  21. package/build/{CryptoProviders/node/index.mjs → platformProviders/node/cryptoLib.mjs} +1 -1
  22. package/build/platformProviders/node/index.d.mts +6 -0
  23. package/build/platformProviders/node/index.mjs +13 -0
  24. package/build/platformProviders/node/openPgpLib.d.mts +20 -0
  25. package/build/platformProviders/node/openPgpLib.mjs +44 -0
  26. package/build/platformProviders/node/qrCodeLib.d.mts +28 -0
  27. package/build/platformProviders/node/qrCodeLib.mjs +54 -0
  28. package/build/subclasses/ExportImportManager.mjs +3 -3
  29. package/build/subclasses/LibraryLoader.d.mts +26 -12
  30. package/build/subclasses/LibraryLoader.mjs +26 -34
  31. package/build/subclasses/SyncManager.mjs +7 -6
  32. package/build/utils/creationUtils.d.mts +3 -3
  33. package/build/utils/creationUtils.mjs +7 -5
  34. package/build/utils/exportImportUtils.d.mts +5 -3
  35. package/build/utils/exportImportUtils.mjs +2 -12
  36. package/build/utils/qrUtils.d.mts +0 -16
  37. package/build/utils/qrUtils.mjs +2 -68
  38. package/build/utils/syncUtils.d.mts +3 -2
  39. package/build/utils/syncUtils.mjs +3 -19
  40. package/package.json +8 -8
  41. /package/build/{CryptoProviders/browser/index.d.mts → platformProviders/browser/cryptoLib.d.mts} +0 -0
  42. /package/build/{CryptoProviders/browser/index.mjs → platformProviders/browser/cryptoLib.mjs} +0 -0
  43. /package/build/{CryptoProviders/node/index.d.mts → platformProviders/node/cryptoLib.d.mts} +0 -0
@@ -2,12 +2,12 @@ import AddEntryCommand from './commands/AddEntryCommand.mjs';
2
2
  import AddSyncDeviceCommand from './commands/AddSyncDeviceCommand.mjs';
3
3
  import DeleteEntryCommand from './commands/DeleteEntryCommand.mjs';
4
4
  import UpdateEntryCommand from './commands/UpdateEntryCommand.mjs';
5
- import ChangeSyncDeviceInfoCommand from './commands/ChangeDeviceInfoCommand.mjs';
5
+ import ChangeDeviceInfoCommand from './commands/ChangeDeviceInfoCommand.mjs';
6
6
  declare const commandConstructors: {
7
7
  AddEntry: typeof AddEntryCommand;
8
8
  DeleteEntry: typeof DeleteEntryCommand;
9
9
  UpdateEntry: typeof UpdateEntryCommand;
10
10
  AddSyncDevice: typeof AddSyncDeviceCommand;
11
- ChangeSyncDeviceInfo: typeof ChangeSyncDeviceInfoCommand;
11
+ ChangeDeviceInfo: typeof ChangeDeviceInfoCommand;
12
12
  };
13
13
  export default commandConstructors;
@@ -2,12 +2,12 @@ import AddEntryCommand from './commands/AddEntryCommand.mjs';
2
2
  import AddSyncDeviceCommand from './commands/AddSyncDeviceCommand.mjs';
3
3
  import DeleteEntryCommand from './commands/DeleteEntryCommand.mjs';
4
4
  import UpdateEntryCommand from './commands/UpdateEntryCommand.mjs';
5
- import ChangeSyncDeviceInfoCommand from './commands/ChangeDeviceInfoCommand.mjs';
5
+ import ChangeDeviceInfoCommand from './commands/ChangeDeviceInfoCommand.mjs';
6
6
  const commandConstructors = {
7
7
  AddEntry: AddEntryCommand,
8
8
  DeleteEntry: DeleteEntryCommand,
9
9
  UpdateEntry: UpdateEntryCommand,
10
10
  AddSyncDevice: AddSyncDeviceCommand,
11
- ChangeSyncDeviceInfo: ChangeSyncDeviceInfoCommand,
11
+ ChangeDeviceInfo: ChangeDeviceInfoCommand,
12
12
  };
13
13
  export default commandConstructors;
@@ -1,7 +1,7 @@
1
1
  import type TwoFaLibMediator from '../../TwoFaLibMediator.mjs';
2
2
  import Command from '../BaseCommand.mjs';
3
3
  import type { DeviceFriendlyName, DeviceId, DeviceType } from '../../interfaces/SyncTypes.mjs';
4
- export interface ChangeSyncDeviceInfoData {
4
+ export interface ChangeDeviceInfoData {
5
5
  deviceId: DeviceId;
6
6
  newDeviceInfo: {
7
7
  deviceFriendlyName?: DeviceFriendlyName;
@@ -11,17 +11,17 @@ export interface ChangeSyncDeviceInfoData {
11
11
  /**
12
12
  * Represents a command that when executed changes the device info of a sync device
13
13
  */
14
- declare class ChangeDeviceInfoCommand extends Command<ChangeSyncDeviceInfoData> {
14
+ declare class ChangeDeviceInfoCommand extends Command<ChangeDeviceInfoData> {
15
15
  /**
16
- * Creates a new ChangeSyncDeviceMetaCommand instance.
16
+ * Creates a new ChangeDeviceMetaCommand instance.
17
17
  * @inheritdoc
18
18
  * @param data - The id of the device to change and the new meta info
19
19
  */
20
- constructor(data: ChangeSyncDeviceInfoData, id?: string, timestamp?: number, version?: string, fromRemote?: boolean);
20
+ constructor(data: ChangeDeviceInfoData, id?: string, timestamp?: number, version?: string, fromRemote?: boolean);
21
21
  /**
22
- * Executes the command to change the sync device info
22
+ * Executes the command to change the device info
23
23
  * @inheritdoc
24
- * @throws {InvalidCommandError} If the referenced sync device cannot be found
24
+ * @throws {InvalidCommandError} If the referenced device cannot be found
25
25
  */
26
26
  execute(mediator: TwoFaLibMediator): Promise<void>;
27
27
  /**
@@ -5,7 +5,7 @@ import Command from '../BaseCommand.mjs';
5
5
  */
6
6
  class ChangeDeviceInfoCommand extends Command {
7
7
  /**
8
- * Creates a new ChangeSyncDeviceMetaCommand instance.
8
+ * Creates a new ChangeDeviceMetaCommand instance.
9
9
  * @inheritdoc
10
10
  * @param data - The id of the device to change and the new meta info
11
11
  */
@@ -13,9 +13,9 @@ class ChangeDeviceInfoCommand extends Command {
13
13
  super('ChangeDeviceInfo', data, id, timestamp, version, fromRemote);
14
14
  }
15
15
  /**
16
- * Executes the command to change the sync device info
16
+ * Executes the command to change the device info
17
17
  * @inheritdoc
18
- * @throws {InvalidCommandError} If the referenced sync device cannot be found
18
+ * @throws {InvalidCommandError} If the referenced device cannot be found
19
19
  */
20
20
  async execute(mediator) {
21
21
  if (!this.validate(mediator)) {
@@ -1,5 +1,5 @@
1
1
  import { TypedEventTarget } from 'typescript-event-target';
2
- import type CryptoLib from './interfaces/CryptoLib.mjs';
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';
@@ -34,7 +34,7 @@ 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 cryptoLib - An instance of CryptoLib that is compatible with the environment.
37
+ * @param platformProviders - The platform-specific providers containing CryptoLib and other providers.
38
38
  * @param passphraseExtraDict - Additional words to be used for passphrase strength evaluation.
39
39
  * @param privateKey - The private key used for cryptographic operations.
40
40
  * @param symmetricKey - The symmetric key used for cryptographic operations.
@@ -50,7 +50,7 @@ declare class TwoFaLib extends TypedEventTarget<TwoFaLibEventMapEvents> {
50
50
  * @throws {InitializationError} If some parameter has an invalid value
51
51
  * @throws {AuthenticationError} If the provided passphrase is incorrect.
52
52
  */
53
- constructor(deviceType: DeviceType, cryptoLib: CryptoLib, passphraseExtraDict: PassphraseExtraDict, privateKey: PrivateKey, symmetricKey: SymmetricKey, encryptedPrivateKey: EncryptedPrivateKey, encryptedSymmetricKey: EncryptedSymmetricKey, salt: Salt, publicKey: PublicKey, favaMeta: FavaMeta, vault?: Vault, saveFunction?: SaveFunction, syncState?: VaultSyncState);
53
+ constructor(deviceType: DeviceType, platformProviders: PlatformProviders, passphraseExtraDict: PassphraseExtraDict, 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
  */
@@ -30,7 +30,7 @@ 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 cryptoLib - An instance of CryptoLib that is compatible with the environment.
33
+ * @param platformProviders - The platform-specific providers containing CryptoLib and other providers.
34
34
  * @param passphraseExtraDict - Additional words to be used for passphrase strength evaluation.
35
35
  * @param privateKey - The private key used for cryptographic operations.
36
36
  * @param symmetricKey - The symmetric key used for cryptographic operations.
@@ -46,7 +46,7 @@ class TwoFaLib extends TypedEventTarget {
46
46
  * @throws {InitializationError} If some parameter has an invalid value
47
47
  * @throws {AuthenticationError} If the provided passphrase is incorrect.
48
48
  */
49
- constructor(deviceType, cryptoLib, passphraseExtraDict, privateKey, symmetricKey, encryptedPrivateKey, encryptedSymmetricKey, salt, publicKey, favaMeta, vault, saveFunction, syncState) {
49
+ constructor(deviceType, platformProviders, passphraseExtraDict, 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');
@@ -70,7 +70,7 @@ class TwoFaLib extends TypedEventTarget {
70
70
  this.privateKey = privateKey;
71
71
  this.mediator = new TwoFaLibMediator();
72
72
  this.mediator.registerComponents([
73
- ['libraryLoader', new LibraryLoader(cryptoLib)],
73
+ ['libraryLoader', new LibraryLoader(platformProviders)],
74
74
  [
75
75
  'persistentStorageManager',
76
76
  new PersistentStorageManager(this.mediator, passphraseExtraDict, favaMeta, privateKey, symmetricKey, encryptedPrivateKey, encryptedSymmetricKey, salt, saveFunction),
@@ -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
- if (this.sync) {
156
+ const oldSyncManager = this.sync;
157
+ if (oldSyncManager) {
157
158
  // close connection so no data is send to the old syncServer
158
- this.sync.closeServerConnection();
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
- if (this.sync) {
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.sync.initServerConnection();
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
  }
@@ -2,7 +2,7 @@ import type { AddEntryData } from '../Command/commands/AddEntryCommand.mjs';
2
2
  import type { DeleteEntryData } from '../Command/commands/DeleteEntryCommand.mjs';
3
3
  import type { UpdateEntryData } from '../Command/commands/UpdateEntryCommand.mjs';
4
4
  import type { AddSyncDeviceData } from '../Command/commands/AddSyncDeviceCommand.mjs';
5
- import type { ChangeSyncDeviceInfoData } from '../Command/commands/ChangeDeviceInfoCommand.mjs';
5
+ import type { ChangeDeviceInfoData } from '../Command/commands/ChangeDeviceInfoCommand.mjs';
6
6
  export type SyncCommand = ({
7
7
  type: 'AddEntry';
8
8
  data: AddEntryData;
@@ -16,9 +16,9 @@ export type SyncCommand = ({
16
16
  type: 'AddSyncDevice';
17
17
  data: AddSyncDeviceData;
18
18
  } | {
19
- type: 'ChangeSyncDeviceInfo';
20
- data: ChangeSyncDeviceInfoData;
19
+ type: 'ChangeDeviceInfo';
20
+ data: ChangeDeviceInfoData;
21
21
  }) & {
22
22
  id: string;
23
23
  };
24
- export type CommandData = AddEntryData | DeleteEntryData | UpdateEntryData | AddSyncDeviceData | ChangeSyncDeviceInfoData;
24
+ export type CommandData = AddEntryData | DeleteEntryData | UpdateEntryData | AddSyncDeviceData | ChangeDeviceInfoData;
@@ -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
@@ -6,8 +6,9 @@ import type { Encrypted, EncryptedPrivateKey, EncryptedSymmetricKey, EncryptedPu
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, Passphrase, Salt, DeviceId, DeviceType, DeviceFriendlyName, DeviceInfo, PublicSyncDevice, SaveFunction, };
14
+ export type { Entry, EntryId, NewEntry, EntryMeta, EntryMetaWithToken, EntryType, TotpPayload, Token, EncryptedVaultStateString, LockedRepresentationString, CryptoLib, Encrypted, EncryptedPrivateKey, EncryptedPublicKey, EncryptedSymmetricKey, PrivateKey, SymmetricKey, PublicKey, Passphrase, Salt, DeviceId, DeviceType, DeviceFriendlyName, DeviceInfo, PublicSyncDevice, SaveFunction, PlatformProviders, };
@@ -0,0 +1,6 @@
1
+ import type { PlatformProviders } from '../../interfaces/PlatformProviders.mjs';
2
+ /**
3
+ * Browser-specific platform providers
4
+ */
5
+ export declare const browserProviders: PlatformProviders;
6
+ export default browserProviders;
@@ -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
+ }
@@ -0,0 +1,69 @@
1
+ import { TwoFALibError } from '../../TwoFALibError.mjs';
2
+ /**
3
+ * Gets the ImageData from an image, for browser environments.
4
+ * This ImageData is then further processed to get QR codes.
5
+ * @param input - The image to get the ImageData from.
6
+ * @returns A promise that resolves to the ImageData.
7
+ */
8
+ export const getImageDataFromInput = (input) => {
9
+ return new Promise((resolve, reject) => {
10
+ if (input instanceof Uint8Array) {
11
+ reject(new TwoFALibError('Uint8Array input not supported in browser environment'));
12
+ return;
13
+ }
14
+ const img = new Image();
15
+ img.onload = () => {
16
+ const canvas = document.createElement('canvas');
17
+ canvas.width = img.width;
18
+ canvas.height = img.height;
19
+ const ctx = canvas.getContext('2d');
20
+ if (!ctx) {
21
+ reject(new TwoFALibError('Could not create canvas context'));
22
+ return;
23
+ }
24
+ ctx.drawImage(img, 0, 0);
25
+ resolve(ctx.getImageData(0, 0, img.width, img.height));
26
+ };
27
+ img.onerror = () => reject(new TwoFALibError('Failed to load image'));
28
+ if (typeof input === 'string') {
29
+ // URL or Data URL
30
+ img.src = input;
31
+ }
32
+ else {
33
+ // File object
34
+ const reader = new FileReader();
35
+ reader.onload = (e) => {
36
+ img.src = e.target?.result;
37
+ };
38
+ reader.onerror = () => reject(new TwoFALibError('Failed to read file'));
39
+ reader.readAsDataURL(input);
40
+ }
41
+ });
42
+ };
43
+ /**
44
+ * Browser implementation of QR code library wrapper
45
+ */
46
+ export class BrowserQrCodeLib {
47
+ constructor() {
48
+ this.qrCodeModule = null;
49
+ this.getImageDataFromInput = getImageDataFromInput;
50
+ }
51
+ /**
52
+ * Gets the QR code module, loading it if necessary
53
+ * @returns Promise that resolves to the QR code module
54
+ */
55
+ async getQrCodeModule() {
56
+ if (!this.qrCodeModule) {
57
+ const qrcode = await import('qrcode');
58
+ this.qrCodeModule = qrcode.default;
59
+ }
60
+ return this.qrCodeModule;
61
+ }
62
+ /**
63
+ * @inheritdoc
64
+ */
65
+ async toDataURL(text) {
66
+ const qrCode = await this.getQrCodeModule();
67
+ return qrCode.toDataURL(text);
68
+ }
69
+ }
@@ -4,7 +4,7 @@ import { generateKeyPair as generateKeyPairCb, generateKey as generateKeyCb, pub
4
4
  import { argon2id } from 'hash-wasm';
5
5
  import { toUint8Array } from 'uint8array-extras';
6
6
  import { CryptoError } from '../../TwoFALibError.mjs';
7
- import { generatePassphraseHash } from '../browser/index.mjs';
7
+ import { generatePassphraseHash } from '../browser/cryptoLib.mjs';
8
8
  const generateKeyPair = promisify(generateKeyPairCb);
9
9
  const generateKey = promisify(generateKeyCb);
10
10
  /**
@@ -0,0 +1,6 @@
1
+ import type { PlatformProviders } from '../../interfaces/PlatformProviders.mjs';
2
+ /**
3
+ * Node.js-specific platform providers
4
+ */
5
+ export declare const nodeProviders: PlatformProviders;
6
+ export default nodeProviders;
@@ -0,0 +1,13 @@
1
+ import NodeCryptoLib from './cryptoLib.mjs';
2
+ import { NodeQrCodeLib } from './qrCodeLib.mjs';
3
+ import { NodeOpenPgpLib } from './openPgpLib.mjs';
4
+ /**
5
+ * Node.js-specific platform providers
6
+ */
7
+ export const nodeProviders = {
8
+ CryptoLib: NodeCryptoLib,
9
+ WebSocketLib: () => WebSocket,
10
+ QrCodeLib: NodeQrCodeLib,
11
+ OpenPgpLib: NodeOpenPgpLib,
12
+ };
13
+ export default nodeProviders;
@@ -0,0 +1,20 @@
1
+ import type { OpenPgpLib } from '../../interfaces/OpenPgpLib.mjs';
2
+ /**
3
+ * Node.js implementation of OpenPGP library wrapper
4
+ */
5
+ export declare class NodeOpenPgpLib 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
+ * Node.js implementation of OpenPGP library wrapper
3
+ */
4
+ export class NodeOpenPgpLib {
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,28 @@
1
+ import type { ImageData } from 'canvas';
2
+ import type { QrCodeLib } from '../../interfaces/QrCodeLib.mjs';
3
+ /**
4
+ * Gets the ImageData from an image, for Node.js environments.
5
+ * This ImageData is then further processed to get QR codes.
6
+ * @param inputImage - The image to get the ImageData from.
7
+ * @returns A promise that resolves to the ImageData.
8
+ */
9
+ export declare const getImageDataFromInput: (inputImage: string | File | Uint8Array) => Promise<ImageData>;
10
+ /**
11
+ * Node.js implementation of QR code library wrapper
12
+ */
13
+ export declare class NodeQrCodeLib 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
+ /**
25
+ * @inheritdoc
26
+ */
27
+ getImageDataFromInput(imageInput: string | File | Uint8Array): Promise<ImageData>;
28
+ }