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
|
@@ -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
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type CryptoLib from '../../interfaces/CryptoLib.mjs';
|
|
2
|
-
import type { Encrypted, EncryptedPrivateKey, EncryptedSymmetricKey,
|
|
2
|
+
import type { Encrypted, EncryptedPrivateKey, EncryptedSymmetricKey, Password, PrivateKey, PublicKey, Salt, SymmetricKey, SyncKey } from '../../interfaces/CryptoLib.mjs';
|
|
3
3
|
/**
|
|
4
4
|
* @inheritdoc
|
|
5
5
|
*/
|
|
@@ -11,7 +11,7 @@ declare class NodeCryptoLib implements CryptoLib {
|
|
|
11
11
|
/**
|
|
12
12
|
* @inheritdoc
|
|
13
13
|
*/
|
|
14
|
-
createKeys(
|
|
14
|
+
createKeys(password: Password): Promise<{
|
|
15
15
|
privateKey: PrivateKey;
|
|
16
16
|
symmetricKey: SymmetricKey;
|
|
17
17
|
publicKey: PublicKey;
|
|
@@ -22,14 +22,14 @@ declare class NodeCryptoLib implements CryptoLib {
|
|
|
22
22
|
/**
|
|
23
23
|
* @inheritdoc
|
|
24
24
|
*/
|
|
25
|
-
encryptKeys(privateKey: PrivateKey, symmetricKey: SymmetricKey, salt: Salt,
|
|
25
|
+
encryptKeys(privateKey: PrivateKey, symmetricKey: SymmetricKey, salt: Salt, password: Password): Promise<{
|
|
26
26
|
encryptedPrivateKey: EncryptedPrivateKey;
|
|
27
27
|
encryptedSymmetricKey: EncryptedSymmetricKey;
|
|
28
28
|
}>;
|
|
29
29
|
/**
|
|
30
30
|
* @inheritdoc
|
|
31
31
|
*/
|
|
32
|
-
decryptKeys(encryptedPrivateKey: EncryptedPrivateKey, encryptedSymmetricKey: EncryptedSymmetricKey, salt: Salt,
|
|
32
|
+
decryptKeys(encryptedPrivateKey: EncryptedPrivateKey, encryptedSymmetricKey: EncryptedSymmetricKey, salt: Salt, password: Password): Promise<{
|
|
33
33
|
privateKey: PrivateKey;
|
|
34
34
|
publicKey: PublicKey;
|
|
35
35
|
symmetricKey: SymmetricKey;
|
|
@@ -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 {
|
|
7
|
+
import { generatePasswordHash } from '../browser/cryptoLib.mjs';
|
|
8
8
|
const generateKeyPair = promisify(generateKeyPairCb);
|
|
9
9
|
const generateKey = promisify(generateKeyCb);
|
|
10
10
|
/**
|
|
@@ -20,11 +20,11 @@ class NodeCryptoLib {
|
|
|
20
20
|
/**
|
|
21
21
|
* @inheritdoc
|
|
22
22
|
*/
|
|
23
|
-
async createKeys(
|
|
23
|
+
async createKeys(password) {
|
|
24
24
|
// create random salt
|
|
25
25
|
const salt = randomBytes(16).toString('base64');
|
|
26
26
|
// create passwordHash
|
|
27
|
-
const
|
|
27
|
+
const passwordHash = await generatePasswordHash(salt, password);
|
|
28
28
|
// Generate public/private key pair
|
|
29
29
|
const { publicKey, privateKey: encryptedPrivateKey } = await generateKeyPair('rsa', {
|
|
30
30
|
modulusLength: 4096,
|
|
@@ -36,13 +36,13 @@ class NodeCryptoLib {
|
|
|
36
36
|
type: 'pkcs8',
|
|
37
37
|
format: 'pem',
|
|
38
38
|
cipher: 'aes-256-cbc',
|
|
39
|
-
passphrase:
|
|
39
|
+
passphrase: passwordHash,
|
|
40
40
|
},
|
|
41
41
|
});
|
|
42
42
|
// Create and encrypt symmetric key with public key
|
|
43
43
|
const symmetricKey = await this.createSymmetricKey();
|
|
44
44
|
const encryptedSymmetricKey = await this.encrypt(publicKey, symmetricKey);
|
|
45
|
-
const { privateKey } = await this.decryptKeys(encryptedPrivateKey, encryptedSymmetricKey, salt,
|
|
45
|
+
const { privateKey } = await this.decryptKeys(encryptedPrivateKey, encryptedSymmetricKey, salt, password);
|
|
46
46
|
return {
|
|
47
47
|
privateKey: privateKey,
|
|
48
48
|
symmetricKey,
|
|
@@ -55,9 +55,9 @@ class NodeCryptoLib {
|
|
|
55
55
|
/**
|
|
56
56
|
* @inheritdoc
|
|
57
57
|
*/
|
|
58
|
-
async encryptKeys(privateKey, symmetricKey, salt,
|
|
58
|
+
async encryptKeys(privateKey, symmetricKey, salt, password) {
|
|
59
59
|
// recreate passwordHash
|
|
60
|
-
const
|
|
60
|
+
const passwordHash = await generatePasswordHash(salt, password);
|
|
61
61
|
// Encrypt private key
|
|
62
62
|
const privateKeyObject = createPrivateKey({
|
|
63
63
|
key: privateKey,
|
|
@@ -67,7 +67,7 @@ class NodeCryptoLib {
|
|
|
67
67
|
type: 'pkcs8',
|
|
68
68
|
format: 'pem',
|
|
69
69
|
cipher: 'aes-256-cbc',
|
|
70
|
-
passphrase:
|
|
70
|
+
passphrase: passwordHash,
|
|
71
71
|
});
|
|
72
72
|
// Encrypt symmetric key with public key
|
|
73
73
|
const publicKeyObject = createPublicKey(privateKeyObject);
|
|
@@ -84,9 +84,9 @@ class NodeCryptoLib {
|
|
|
84
84
|
/**
|
|
85
85
|
* @inheritdoc
|
|
86
86
|
*/
|
|
87
|
-
async decryptKeys(encryptedPrivateKey, encryptedSymmetricKey, salt,
|
|
87
|
+
async decryptKeys(encryptedPrivateKey, encryptedSymmetricKey, salt, password) {
|
|
88
88
|
// recreate passwordHash
|
|
89
|
-
const
|
|
89
|
+
const passwordHash = await generatePasswordHash(salt, password);
|
|
90
90
|
let privateKeyObject;
|
|
91
91
|
let privateKey;
|
|
92
92
|
try {
|
|
@@ -94,7 +94,7 @@ class NodeCryptoLib {
|
|
|
94
94
|
key: encryptedPrivateKey,
|
|
95
95
|
type: 'pkcs8',
|
|
96
96
|
format: 'pem',
|
|
97
|
-
passphrase:
|
|
97
|
+
passphrase: passwordHash,
|
|
98
98
|
});
|
|
99
99
|
privateKey = privateKeyObject.export({
|
|
100
100
|
type: 'pkcs8',
|
|
@@ -105,7 +105,7 @@ class NodeCryptoLib {
|
|
|
105
105
|
// eslint-disable-next-line no-restricted-globals
|
|
106
106
|
if (err instanceof Error && 'code' in err) {
|
|
107
107
|
if (err.code === 'ERR_OSSL_BAD_DECRYPT') {
|
|
108
|
-
throw new CryptoError('Invalid
|
|
108
|
+
throw new CryptoError('Invalid password');
|
|
109
109
|
}
|
|
110
110
|
if (err.code === 'ERR_OSSL_UNSUPPORTED') {
|
|
111
111
|
throw new CryptoError('Invalid private key');
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { TwoFALibError } from '../../TwoFALibError.mjs';
|
|
2
|
+
import { isUint8Array } from 'uint8array-extras';
|
|
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 const getImageDataFromInput = async (inputImage) => {
|
|
10
|
+
if (inputImage instanceof File) {
|
|
11
|
+
throw new TwoFALibError('Getting data from QR where image type is "File" is not supported in the node environment');
|
|
12
|
+
}
|
|
13
|
+
const canvasLib = await import('canvas');
|
|
14
|
+
const { createCanvas, loadImage } = canvasLib;
|
|
15
|
+
// eslint-disable-next-line no-restricted-globals
|
|
16
|
+
const input = isUint8Array(inputImage) ? Buffer.from(inputImage) : inputImage;
|
|
17
|
+
const image = await loadImage(input); // canvaslib expects a buffer
|
|
18
|
+
const canvas = createCanvas(image.width, image.height);
|
|
19
|
+
const ctx = canvas.getContext('2d');
|
|
20
|
+
ctx.drawImage(image, 0, 0);
|
|
21
|
+
return ctx.getImageData(0, 0, image.width, image.height);
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Node.js implementation of QR code library wrapper
|
|
25
|
+
*/
|
|
26
|
+
export class NodeQrCodeLib {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.qrCodeModule = null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Gets the QR code module, loading it if necessary
|
|
32
|
+
* @returns Promise that resolves to the QR code module
|
|
33
|
+
*/
|
|
34
|
+
async getQrCodeModule() {
|
|
35
|
+
if (!this.qrCodeModule) {
|
|
36
|
+
const qrcode = await import('qrcode');
|
|
37
|
+
this.qrCodeModule = qrcode.default;
|
|
38
|
+
}
|
|
39
|
+
return this.qrCodeModule;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* @inheritdoc
|
|
43
|
+
*/
|
|
44
|
+
async toDataURL(text) {
|
|
45
|
+
const qrCode = await this.getQrCodeModule();
|
|
46
|
+
return qrCode.toDataURL(text);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @inheritdoc
|
|
50
|
+
*/
|
|
51
|
+
async getImageDataFromInput(imageInput) {
|
|
52
|
+
return getImageDataFromInput(imageInput);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { EntryId } from '../interfaces/Entry.mjs';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PasswordExtraDict } from '../interfaces/PasswordExtraDict.js';
|
|
3
3
|
import type TwoFaLibMediator from '../TwoFaLibMediator.mjs';
|
|
4
4
|
/**
|
|
5
5
|
* Manages the export and import of entries in various formats.
|
|
6
6
|
*/
|
|
7
7
|
declare class ExportImportManager {
|
|
8
8
|
private readonly mediator;
|
|
9
|
-
private readonly
|
|
9
|
+
private readonly passwordExtraDict;
|
|
10
10
|
/**
|
|
11
11
|
* Constructs a new instance of ExportImportManager.
|
|
12
12
|
* @param mediator - The mediator for accessing other components.
|
|
13
|
-
* @param
|
|
13
|
+
* @param passwordExtraDict - Additional words to be used for password strength evaluation.
|
|
14
14
|
*/
|
|
15
|
-
constructor(mediator: TwoFaLibMediator,
|
|
15
|
+
constructor(mediator: TwoFaLibMediator, passwordExtraDict: PasswordExtraDict);
|
|
16
16
|
private get libraryLoader();
|
|
17
17
|
private get vaultDataManager();
|
|
18
18
|
private get vaultOperationsManager();
|
|
@@ -21,21 +21,21 @@ declare class ExportImportManager {
|
|
|
21
21
|
* Export entries in the specified format, optionally (when a password is provided) encrypted.
|
|
22
22
|
* If the password is not provided, the user be warned about the dangers of exporting clear text.
|
|
23
23
|
* @param format - The export format ('text' or 'html').
|
|
24
|
-
* @param
|
|
24
|
+
* @param password - Optional password for encryption.
|
|
25
25
|
* @param userWasWarnedAboutExportingClearText - Whether the user was warned about exporting clear text.
|
|
26
26
|
* @returns A promise that resolves to the exported data as a string.
|
|
27
27
|
*/
|
|
28
|
-
exportEntries(format: 'text' | 'html',
|
|
28
|
+
exportEntries(format: 'text' | 'html', password?: string, userWasWarnedAboutExportingClearText?: boolean): Promise<string>;
|
|
29
29
|
private generateTextExport;
|
|
30
30
|
private generateHtmlExport;
|
|
31
31
|
/**
|
|
32
32
|
* Import entries from a text file, optionally (when a password is provided) decrypt first
|
|
33
33
|
* @param fileContents - The contents of the text file.
|
|
34
|
-
* @param
|
|
34
|
+
* @param password - Optional password for decryption.
|
|
35
35
|
* @returns A promise that resolves to an array of objects, each containing the line number,
|
|
36
36
|
* the EntryId or null if it was not a valid entry and the error if there was one.
|
|
37
37
|
*/
|
|
38
|
-
importFromTextFile(fileContents: string,
|
|
38
|
+
importFromTextFile(fileContents: string, password?: string): Promise<{
|
|
39
39
|
lineNr: number;
|
|
40
40
|
entryId: EntryId | null;
|
|
41
41
|
error: unknown;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parseOtpUri, generateHtmlExport, generateTextExport, processImportLines, encryptExport, decryptExport, } from '../utils/exportImportUtils.mjs';
|
|
2
2
|
import { getDataFromQRImage } from '../utils/qrUtils.mjs';
|
|
3
3
|
import { ExportImportError } from '../TwoFALibError.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { validatePasswordStrength } from '../utils/creationUtils.mjs';
|
|
5
5
|
/**
|
|
6
6
|
* Manages the export and import of entries in various formats.
|
|
7
7
|
*/
|
|
@@ -9,11 +9,11 @@ class ExportImportManager {
|
|
|
9
9
|
/**
|
|
10
10
|
* Constructs a new instance of ExportImportManager.
|
|
11
11
|
* @param mediator - The mediator for accessing other components.
|
|
12
|
-
* @param
|
|
12
|
+
* @param passwordExtraDict - Additional words to be used for password strength evaluation.
|
|
13
13
|
*/
|
|
14
|
-
constructor(mediator,
|
|
14
|
+
constructor(mediator, passwordExtraDict) {
|
|
15
15
|
this.mediator = mediator;
|
|
16
|
-
this.
|
|
16
|
+
this.passwordExtraDict = passwordExtraDict;
|
|
17
17
|
}
|
|
18
18
|
get libraryLoader() {
|
|
19
19
|
return this.mediator.getComponent('libraryLoader');
|
|
@@ -31,13 +31,13 @@ class ExportImportManager {
|
|
|
31
31
|
* Export entries in the specified format, optionally (when a password is provided) encrypted.
|
|
32
32
|
* If the password is not provided, the user be warned about the dangers of exporting clear text.
|
|
33
33
|
* @param format - The export format ('text' or 'html').
|
|
34
|
-
* @param
|
|
34
|
+
* @param password - Optional password for encryption.
|
|
35
35
|
* @param userWasWarnedAboutExportingClearText - Whether the user was warned about exporting clear text.
|
|
36
36
|
* @returns A promise that resolves to the exported data as a string.
|
|
37
37
|
*/
|
|
38
|
-
async exportEntries(format,
|
|
38
|
+
async exportEntries(format, password, userWasWarnedAboutExportingClearText) {
|
|
39
39
|
let exportData;
|
|
40
|
-
if (!
|
|
40
|
+
if (!password && !userWasWarnedAboutExportingClearText) {
|
|
41
41
|
throw new ExportImportError('User was not warned about the dangers of unencrypted exporting');
|
|
42
42
|
}
|
|
43
43
|
if (format === 'text') {
|
|
@@ -49,9 +49,9 @@ class ExportImportManager {
|
|
|
49
49
|
else {
|
|
50
50
|
throw new ExportImportError('Invalid export format');
|
|
51
51
|
}
|
|
52
|
-
if (
|
|
53
|
-
await
|
|
54
|
-
return encryptExport(
|
|
52
|
+
if (password) {
|
|
53
|
+
await validatePasswordStrength(this.libraryLoader, password, this.passwordExtraDict);
|
|
54
|
+
return encryptExport(this.libraryLoader.getOpenPGPLib(), exportData, password);
|
|
55
55
|
}
|
|
56
56
|
return exportData;
|
|
57
57
|
}
|
|
@@ -59,19 +59,19 @@ class ExportImportManager {
|
|
|
59
59
|
return generateTextExport(this.vaultDataManager.getAllEntries());
|
|
60
60
|
}
|
|
61
61
|
async generateHtmlExport() {
|
|
62
|
-
const qrGeneratorLib =
|
|
62
|
+
const qrGeneratorLib = this.libraryLoader.getQrGeneratorLib();
|
|
63
63
|
return generateHtmlExport(qrGeneratorLib, this.vaultDataManager.getAllEntries());
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
66
|
* Import entries from a text file, optionally (when a password is provided) decrypt first
|
|
67
67
|
* @param fileContents - The contents of the text file.
|
|
68
|
-
* @param
|
|
68
|
+
* @param password - Optional password for decryption.
|
|
69
69
|
* @returns A promise that resolves to an array of objects, each containing the line number,
|
|
70
70
|
* the EntryId or null if it was not a valid entry and the error if there was one.
|
|
71
71
|
*/
|
|
72
|
-
async importFromTextFile(fileContents,
|
|
73
|
-
if (
|
|
74
|
-
const decrypted = await decryptExport(
|
|
72
|
+
async importFromTextFile(fileContents, password) {
|
|
73
|
+
if (password) {
|
|
74
|
+
const decrypted = await decryptExport(this.libraryLoader.getOpenPGPLib(), fileContents, password);
|
|
75
75
|
return this.importFromTextFile(decrypted);
|
|
76
76
|
}
|
|
77
77
|
const lines = fileContents.trim().split('\n');
|
|
@@ -1,52 +1,66 @@
|
|
|
1
1
|
import type CryptoLib from '../interfaces/CryptoLib.mjs';
|
|
2
|
+
import type { PlatformProviders } from '../interfaces/PlatformProviders.mjs';
|
|
3
|
+
import type { QrCodeLib } from '../interfaces/QrCodeLib.mjs';
|
|
4
|
+
import type { OpenPgpLib } from '../interfaces/OpenPgpLib.mjs';
|
|
2
5
|
/**
|
|
3
6
|
* Class responsible for loading various external (big) libraries required by the application.
|
|
4
7
|
* All libraries (except CryptoLib) are loaded on demand. This helps to reduce the initial bundle size.
|
|
5
8
|
*/
|
|
6
9
|
declare class LibraryLoader {
|
|
10
|
+
private platformProviders;
|
|
7
11
|
private cryptoLib;
|
|
8
12
|
private openPgpLib?;
|
|
9
13
|
private qrGeneratorLib?;
|
|
10
14
|
private jsQrLib?;
|
|
11
|
-
private canvasLib?;
|
|
12
15
|
private urlParserLib?;
|
|
13
16
|
private zxcvbn?;
|
|
17
|
+
private webSocketLib?;
|
|
14
18
|
/**
|
|
15
19
|
* Constructs a new instance of LibraryLoader.
|
|
16
|
-
* @param
|
|
17
|
-
* @throws {InitializationError} If the provided
|
|
20
|
+
* @param platformProviders - Platform-specific providers containing CryptoLib and other providers.
|
|
21
|
+
* @throws {InitializationError} If the provided platform providers are invalid.
|
|
18
22
|
*/
|
|
19
|
-
constructor(
|
|
23
|
+
constructor(platformProviders: PlatformProviders);
|
|
20
24
|
/**
|
|
21
25
|
* @returns The CryptoLib instance.
|
|
22
26
|
*/
|
|
23
27
|
getCryptoLib(): CryptoLib;
|
|
28
|
+
/**
|
|
29
|
+
* @returns The PlatformProviders instance.
|
|
30
|
+
*/
|
|
31
|
+
getPlatformProviders(): PlatformProviders;
|
|
24
32
|
/**
|
|
25
33
|
* Loads and returns the OpenPGP library on demand.
|
|
26
34
|
* @returns A promise that resolves to the OpenPGP library.
|
|
27
35
|
*/
|
|
28
|
-
getOpenPGPLib():
|
|
36
|
+
getOpenPGPLib(): OpenPgpLib;
|
|
29
37
|
/**
|
|
30
38
|
* Loads and returns the QR Generator library on demand.
|
|
31
39
|
* @returns A promise that resolves to the QR Generator library.
|
|
32
40
|
*/
|
|
33
|
-
getQrGeneratorLib():
|
|
41
|
+
getQrGeneratorLib(): QrCodeLib;
|
|
34
42
|
/**
|
|
35
43
|
* Loads and returns the JsQR library on demand.
|
|
36
44
|
* @returns A promise that resolves to the JsQR library.
|
|
37
45
|
*/
|
|
38
46
|
getJsQrLib(): Promise<typeof import("jsqr").default>;
|
|
39
|
-
/**
|
|
40
|
-
* Loads and returns the Canvas library on demand.
|
|
41
|
-
* @returns A promise that resolves to the Canvas library.
|
|
42
|
-
* @throws {TwoFALibError} If the library cannot be loaded in a browser environment.
|
|
43
|
-
*/
|
|
44
|
-
getCanvasLib(): Promise<typeof import("canvas")>;
|
|
45
47
|
/**
|
|
46
48
|
* Loads and returns the URL Parser library on demand.
|
|
47
49
|
* @returns A promise that resolves to the URL Parser library.
|
|
48
50
|
*/
|
|
49
51
|
getUrlParserLib(): Promise<typeof import("whatwg-url")>;
|
|
52
|
+
/**
|
|
53
|
+
* Loads and returns the WebSocket library on demand.
|
|
54
|
+
* @returns The WebSocket library.
|
|
55
|
+
*/
|
|
56
|
+
getWebSocketLib(): {
|
|
57
|
+
new (url: string | URL, protocols?: string | string[]): WebSocket;
|
|
58
|
+
prototype: WebSocket;
|
|
59
|
+
readonly CONNECTING: 0;
|
|
60
|
+
readonly OPEN: 1;
|
|
61
|
+
readonly CLOSING: 2;
|
|
62
|
+
readonly CLOSED: 3;
|
|
63
|
+
};
|
|
50
64
|
/**
|
|
51
65
|
* Loads and returns the Zxcvbn library on demand.
|
|
52
66
|
* @returns A promise that resolves to the Zxcvbn library.
|