@cloudpss/crypto 0.5.26 → 0.5.29
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/dist/encryption/common.d.ts +4 -4
- package/dist/encryption/common.js +5 -5
- package/dist/encryption/common.js.map +1 -1
- package/dist/encryption/index.js +4 -1
- package/dist/encryption/index.js.map +1 -1
- package/dist/encryption/module.js +2 -2
- package/dist/encryption/module.js.map +1 -1
- package/dist/encryption/node.js +4 -3
- package/dist/encryption/node.js.map +1 -1
- package/dist/encryption/wasm.js +4 -3
- package/dist/encryption/wasm.js.map +1 -1
- package/dist/encryption/web.js +5 -1
- package/dist/encryption/web.js.map +1 -1
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +2 -0
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/encryption/common.ts +7 -7
- package/src/encryption/index.ts +3 -1
- package/src/encryption/module.ts +3 -3
- package/src/encryption/node.ts +4 -3
- package/src/encryption/wasm.ts +4 -3
- package/src/encryption/web.ts +5 -1
- package/src/utils.ts +3 -0
- package/tests/encryption.js +17 -14
|
@@ -15,7 +15,7 @@ export declare const AES_TAG_SIZE: number;
|
|
|
15
15
|
/** 加密输入/解密结果 */
|
|
16
16
|
export interface PlainData {
|
|
17
17
|
/** 附加数据 */
|
|
18
|
-
aad
|
|
18
|
+
aad: Uint8Array;
|
|
19
19
|
/** 明文数据 */
|
|
20
20
|
data: Uint8Array;
|
|
21
21
|
}
|
|
@@ -24,7 +24,7 @@ export interface EncryptedData {
|
|
|
24
24
|
/** NONCE */
|
|
25
25
|
nonce: Uint8Array;
|
|
26
26
|
/** 附加数据 */
|
|
27
|
-
aad
|
|
27
|
+
aad: Uint8Array;
|
|
28
28
|
/** 加密后的数据和 tag */
|
|
29
29
|
data: Uint8Array;
|
|
30
30
|
}
|
|
@@ -32,13 +32,13 @@ export interface EncryptedData {
|
|
|
32
32
|
* CloudPSS 数据加密
|
|
33
33
|
* - 密钥生成算法:PBKDF2-HMAC-SHA256,盐长度 96,迭代 100,000 次
|
|
34
34
|
* - 加密算法:AES-256-GCM,使用与密钥生成算法的盐作为 NONCE,TAG 长度 128
|
|
35
|
-
* - 附加数据:最大长度
|
|
35
|
+
* - 附加数据:最大长度 256MiB -1B
|
|
36
36
|
*
|
|
37
37
|
* - 文件格式:
|
|
38
38
|
* - Magic Number: 0e 02 49 29 3f 07 7b 0a
|
|
39
39
|
* - Nonce: 96 bits
|
|
40
40
|
* - Length of AAD: 4 bytes
|
|
41
|
-
* - AAD (if exists)
|
|
41
|
+
* - AAD (if exists) (padded to 128 bits)
|
|
42
42
|
* - Encrypted Data
|
|
43
43
|
* - Auth Tag: 128 bits
|
|
44
44
|
*/
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { toUint8Array } from '../utils.js';
|
|
1
|
+
import { EMPTY_BUFFER, toUint8Array } from '../utils.js';
|
|
2
2
|
/** PBKDF2 迭代次数 */
|
|
3
3
|
export const PBKDF2_ITERATIONS = 100_000;
|
|
4
4
|
/** NONCE 长度(byte) */
|
|
5
5
|
export const NONCE_SIZE = 96 / 8;
|
|
6
6
|
/** AAD 最大长度(byte) */
|
|
7
|
-
export const AAD_MAX_SIZE =
|
|
7
|
+
export const AAD_MAX_SIZE = 256 * 1024 * 1024 - 1; // 256MiB -1B
|
|
8
8
|
/** AAD 长度字段长度(byte) */
|
|
9
9
|
export const AAD_LEN_SIZE = 4;
|
|
10
10
|
// 与 AES 一致对齐
|
|
@@ -18,13 +18,13 @@ export const AES_TAG_SIZE = 128 / 8;
|
|
|
18
18
|
* CloudPSS 数据加密
|
|
19
19
|
* - 密钥生成算法:PBKDF2-HMAC-SHA256,盐长度 96,迭代 100,000 次
|
|
20
20
|
* - 加密算法:AES-256-GCM,使用与密钥生成算法的盐作为 NONCE,TAG 长度 128
|
|
21
|
-
* - 附加数据:最大长度
|
|
21
|
+
* - 附加数据:最大长度 256MiB -1B
|
|
22
22
|
*
|
|
23
23
|
* - 文件格式:
|
|
24
24
|
* - Magic Number: 0e 02 49 29 3f 07 7b 0a
|
|
25
25
|
* - Nonce: 96 bits
|
|
26
26
|
* - Length of AAD: 4 bytes
|
|
27
|
-
* - AAD (if exists)
|
|
27
|
+
* - AAD (if exists) (padded to 128 bits)
|
|
28
28
|
* - Encrypted Data
|
|
29
29
|
* - Auth Tag: 128 bits
|
|
30
30
|
*/
|
|
@@ -56,7 +56,7 @@ export function parseEncrypted(data) {
|
|
|
56
56
|
}
|
|
57
57
|
const aad = aadSize
|
|
58
58
|
? buffer.subarray(MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE, MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE + aadSize)
|
|
59
|
-
:
|
|
59
|
+
: EMPTY_BUFFER;
|
|
60
60
|
const encrypted = buffer.subarray(MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE + paddingAadSize);
|
|
61
61
|
return { nonce, aad, data: encrypted };
|
|
62
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/encryption/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/encryption/common.ts"],"names":[],"mappings":"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"}
|
package/dist/encryption/index.js
CHANGED
|
@@ -15,7 +15,10 @@ export function extractAad(data) {
|
|
|
15
15
|
if (encrypted == null) {
|
|
16
16
|
throw new TypeError('Invalid encrypted data');
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
const { aad } = encrypted;
|
|
19
|
+
if (!aad.byteLength)
|
|
20
|
+
return undefined;
|
|
21
|
+
return aad;
|
|
19
22
|
}
|
|
20
23
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
21
24
|
export const { encrypt, decrypt, encryptAad } = createModule(impl);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/encryption/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,0BAA0B;AAC1B,MAAM,UAAU,WAAW,CAAC,IAAgB;IACxC,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAgB;IACvC,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,SAAS,CAAC,wBAAwB,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,SAAS,CAAC,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/encryption/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,0BAA0B;AAC1B,MAAM,UAAU,WAAW,CAAC,IAAgB;IACxC,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAgB;IACvC,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,SAAS,CAAC,wBAAwB,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,GAAG,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IACtC,OAAO,GAAG,CAAC;AACf,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { toUint8Array } from '../utils.js';
|
|
1
|
+
import { EMPTY_BUFFER, toUint8Array } from '../utils.js';
|
|
2
2
|
import { AAD_LEN_SIZE, AAD_MAX_SIZE, AAD_PADDING, MAGIC_NUMBER, NONCE_SIZE, padding, parseEncrypted, } from './common.js';
|
|
3
3
|
/** 检查密码 */
|
|
4
4
|
function assertPassphrase(passphrase) {
|
|
@@ -19,7 +19,7 @@ export function createModule(impl) {
|
|
|
19
19
|
}
|
|
20
20
|
const paddedAddSize = padding(aadSize, AAD_PADDING);
|
|
21
21
|
const plain = {
|
|
22
|
-
aad: aadSize ? toUint8Array(aad) :
|
|
22
|
+
aad: aadSize ? toUint8Array(aad) : EMPTY_BUFFER,
|
|
23
23
|
data: toUint8Array(data),
|
|
24
24
|
};
|
|
25
25
|
const encrypted = await impl.encrypt(plain, passphrase);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/encryption/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/encryption/module.ts"],"names":[],"mappings":"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"}
|
package/dist/encryption/node.js
CHANGED
|
@@ -11,11 +11,12 @@ export async function encrypt({ data, aad }, passphrase) {
|
|
|
11
11
|
const nonce = randomBytes(NONCE_SIZE);
|
|
12
12
|
const key = await aesKdf(passphrase, nonce);
|
|
13
13
|
const cipher = createCipheriv('aes-256-gcm', key, nonce, { authTagLength: AES_TAG_SIZE });
|
|
14
|
-
if (aad)
|
|
14
|
+
if (aad.byteLength)
|
|
15
15
|
cipher.setAAD(aad);
|
|
16
16
|
const encrypted = Buffer.concat([cipher.update(data), cipher.final(), cipher.getAuthTag()]);
|
|
17
17
|
return {
|
|
18
18
|
nonce: toUint8Array(nonce),
|
|
19
|
+
aad,
|
|
19
20
|
data: toUint8Array(encrypted),
|
|
20
21
|
};
|
|
21
22
|
}
|
|
@@ -24,9 +25,9 @@ export async function decrypt({ nonce, aad, data }, passphrase) {
|
|
|
24
25
|
const key = await aesKdf(passphrase, nonce);
|
|
25
26
|
const decipher = createDecipheriv('aes-256-gcm', key, nonce, { authTagLength: AES_TAG_SIZE });
|
|
26
27
|
decipher.setAuthTag(data.subarray(data.length - AES_TAG_SIZE));
|
|
27
|
-
if (aad)
|
|
28
|
+
if (aad.byteLength)
|
|
28
29
|
decipher.setAAD(aad);
|
|
29
30
|
const decrypted = Buffer.concat([decipher.update(data.subarray(0, data.length - AES_TAG_SIZE)), decipher.final()]);
|
|
30
|
-
return { data: toUint8Array(decrypted) };
|
|
31
|
+
return { data: toUint8Array(decrypted), aad };
|
|
31
32
|
}
|
|
32
33
|
//# sourceMappingURL=node.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/encryption/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EACH,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,YAAY,GAGf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;AAClC,MAAM,MAAM,GAAG,CAAC,UAAkB,EAAE,IAAgB,EAAmB,EAAE;IACrE,OAAO,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,iBAAiB,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC/E,CAAC,CAAC;AAEF,qBAAqB;AACrB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAa,EAAE,UAAkB;IACtE,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC;IAC1F,IAAI,GAAG;QAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/encryption/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EACH,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,YAAY,GAGf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;AAClC,MAAM,MAAM,GAAG,CAAC,UAAkB,EAAE,IAAgB,EAAmB,EAAE;IACrE,OAAO,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,iBAAiB,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC/E,CAAC,CAAC;AAEF,qBAAqB;AACrB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAa,EAAE,UAAkB;IACtE,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC;IAC1F,IAAI,GAAG,CAAC,UAAU;QAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAC5F,OAAO;QACH,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;QAC1B,GAAG;QACH,IAAI,EAAE,YAAY,CAAC,SAAS,CAAC;KAChC,CAAC;AACN,CAAC;AAED,qBAAqB;AACrB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAiB,EAAE,UAAkB;IACjF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC;IAC9F,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAC/D,IAAI,GAAG,CAAC,UAAU;QAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACnH,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;AAClD,CAAC"}
|
package/dist/encryption/wasm.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { NONCE_SIZE, AES_KEY_SIZE, AES_TAG_SIZE, PBKDF2_ITERATIONS, } from './common.js';
|
|
2
2
|
import * as mod from '#lib-wasm';
|
|
3
|
-
const EMPTY = new Uint8Array(0);
|
|
4
3
|
const encoder = new TextEncoder();
|
|
5
4
|
/** crypto-js encrypt */
|
|
6
5
|
export function encrypt({ data, aad }, passphrase) {
|
|
7
6
|
const nonce = crypto.getRandomValues(new Uint8Array(NONCE_SIZE));
|
|
8
|
-
const result = mod.encrypt(encoder.encode(passphrase), data, aad
|
|
7
|
+
const result = mod.encrypt(encoder.encode(passphrase), data, aad, nonce, PBKDF2_ITERATIONS, AES_KEY_SIZE, AES_TAG_SIZE);
|
|
9
8
|
return {
|
|
10
9
|
nonce,
|
|
10
|
+
aad,
|
|
11
11
|
data: result,
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
/** crypto-js decrypt */
|
|
15
15
|
export function decrypt({ data, aad, nonce }, passphrase) {
|
|
16
|
-
const decrypted = mod.decrypt(encoder.encode(passphrase), data, aad
|
|
16
|
+
const decrypted = mod.decrypt(encoder.encode(passphrase), data, aad, nonce, PBKDF2_ITERATIONS, AES_KEY_SIZE, AES_TAG_SIZE);
|
|
17
17
|
return {
|
|
18
|
+
aad,
|
|
18
19
|
data: decrypted,
|
|
19
20
|
};
|
|
20
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasm.js","sourceRoot":"","sources":["../../src/encryption/wasm.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,UAAU,EACV,YAAY,EACZ,YAAY,EAEZ,iBAAiB,GAEpB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AAEjC,MAAM,
|
|
1
|
+
{"version":3,"file":"wasm.js","sourceRoot":"","sources":["../../src/encryption/wasm.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,UAAU,EACV,YAAY,EACZ,YAAY,EAEZ,iBAAiB,GAEpB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AAEjC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,wBAAwB;AACxB,MAAM,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAa,EAAE,UAAkB;IAChE,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CACtB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAC1B,IAAI,EACJ,GAAG,EACH,KAAK,EACL,iBAAiB,EACjB,YAAY,EACZ,YAAY,CACf,CAAC;IACF,OAAO;QACH,KAAK;QACL,GAAG;QACH,IAAI,EAAE,MAAM;KACf,CAAC;AACN,CAAC;AAED,wBAAwB;AACxB,MAAM,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAiB,EAAE,UAAkB;IAC3E,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CACzB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAC1B,IAAI,EACJ,GAAG,EACH,KAAK,EACL,iBAAiB,EACjB,YAAY,EACZ,YAAY,CACf,CAAC;IACF,OAAO;QACH,GAAG;QACH,IAAI,EAAE,SAAS;KAClB,CAAC;AACN,CAAC"}
|
package/dist/encryption/web.js
CHANGED
|
@@ -26,6 +26,7 @@ export async function encrypt({ data, aad }, passphrase) {
|
|
|
26
26
|
}, key, data);
|
|
27
27
|
return {
|
|
28
28
|
nonce,
|
|
29
|
+
aad,
|
|
29
30
|
data: new Uint8Array(encrypted),
|
|
30
31
|
};
|
|
31
32
|
}
|
|
@@ -38,6 +39,9 @@ export async function decrypt({ data, nonce, aad }, passphrase) {
|
|
|
38
39
|
tagLength: AES_TAG_SIZE * 8,
|
|
39
40
|
additionalData: aad,
|
|
40
41
|
}, key, data);
|
|
41
|
-
return {
|
|
42
|
+
return {
|
|
43
|
+
aad,
|
|
44
|
+
data: new Uint8Array(decrypted),
|
|
45
|
+
};
|
|
42
46
|
}
|
|
43
47
|
//# sourceMappingURL=web.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/encryption/web.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,UAAU,EACV,YAAY,EACZ,YAAY,EAGZ,iBAAiB,GACpB,MAAM,aAAa,CAAC;AAErB,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,wBAAwB;AACxB,KAAK,UAAU,SAAS,CAAC,UAAkB,EAAE,IAAgB;IACzD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAC9G,MAAM,YAAY,GAAiB;QAC/B,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,UAAU,EAAE,iBAAiB;QAC7B,IAAI,EAAE,SAAS;KAClB,CAAC;IACF,OAAO,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE;QAC3G,SAAS;QACT,SAAS;KACZ,CAAC,CAAC;AACP,CAAC;AAED,wBAAwB;AACxB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAa,EAAE,UAAkB;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CACzC;QACI,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,KAAK;QACT,SAAS,EAAE,YAAY,GAAG,CAAC;QAC3B,cAAc,EAAE,GAAG;KACtB,EACD,GAAG,EACH,IAAI,CACP,CAAC;IACF,OAAO;QACH,KAAK;QACL,IAAI,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC;KAClC,CAAC;AACN,CAAC;AAED,wBAAwB;AACxB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAiB,EAAE,UAAkB;IACjF,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CACzC;QACI,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,KAAK;QACT,SAAS,EAAE,YAAY,GAAG,CAAC;QAC3B,cAAc,EAAE,GAAG;KACtB,EACD,GAAG,EACH,IAAI,CACP,CAAC;IACF,OAAO,
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/encryption/web.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,UAAU,EACV,YAAY,EACZ,YAAY,EAGZ,iBAAiB,GACpB,MAAM,aAAa,CAAC;AAErB,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,wBAAwB;AACxB,KAAK,UAAU,SAAS,CAAC,UAAkB,EAAE,IAAgB;IACzD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAC9G,MAAM,YAAY,GAAiB;QAC/B,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,UAAU,EAAE,iBAAiB;QAC7B,IAAI,EAAE,SAAS;KAClB,CAAC;IACF,OAAO,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE;QAC3G,SAAS;QACT,SAAS;KACZ,CAAC,CAAC;AACP,CAAC;AAED,wBAAwB;AACxB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAa,EAAE,UAAkB;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CACzC;QACI,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,KAAK;QACT,SAAS,EAAE,YAAY,GAAG,CAAC;QAC3B,cAAc,EAAE,GAAG;KACtB,EACD,GAAG,EACH,IAAI,CACP,CAAC;IACF,OAAO;QACH,KAAK;QACL,GAAG;QACH,IAAI,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC;KAClC,CAAC;AACN,CAAC;AAED,wBAAwB;AACxB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAiB,EAAE,UAAkB;IACjF,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CACzC;QACI,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,KAAK;QACT,SAAS,EAAE,YAAY,GAAG,CAAC;QAC3B,cAAc,EAAE,GAAG;KACtB,EACD,GAAG,EACH,IAAI,CACP,CAAC;IACF,OAAO;QACH,GAAG;QACH,IAAI,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC;KAClC,CAAC;AACN,CAAC"}
|
package/dist/utils.d.ts
CHANGED
package/dist/utils.js
CHANGED
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,MAAM,UAAU,YAAY,CAAC,IAAgB;IACzC,IAAI,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,QAAQ,IAAI,OAAO,IAAI,CAAC,UAAU,IAAI,QAAQ,EAAE,CAAC;QAChF,MAAM,IAAI,SAAS,CAAC,cAAc,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;AACpD,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,MAAM,UAAU,YAAY,CAAC,IAAgB;IACzC,IAAI,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,QAAQ,IAAI,OAAO,IAAI,CAAC,UAAU,IAAI,QAAQ,EAAE,CAAC;QAChF,MAAM,IAAI,SAAS,CAAC,cAAc,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;AACpD,CAAC;AAED,yBAAyB;AACzB,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
package/src/encryption/common.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { toUint8Array } from '../utils.js';
|
|
1
|
+
import { EMPTY_BUFFER, toUint8Array } from '../utils.js';
|
|
2
2
|
|
|
3
3
|
/** PBKDF2 迭代次数 */
|
|
4
4
|
export const PBKDF2_ITERATIONS = 100_000;
|
|
5
5
|
/** NONCE 长度(byte) */
|
|
6
6
|
export const NONCE_SIZE = 96 / 8;
|
|
7
7
|
/** AAD 最大长度(byte) */
|
|
8
|
-
export const AAD_MAX_SIZE =
|
|
8
|
+
export const AAD_MAX_SIZE = 256 * 1024 * 1024 - 1; // 256MiB -1B
|
|
9
9
|
/** AAD 长度字段长度(byte) */
|
|
10
10
|
export const AAD_LEN_SIZE = 4;
|
|
11
11
|
|
|
@@ -20,7 +20,7 @@ export const AES_TAG_SIZE = 128 / 8;
|
|
|
20
20
|
/** 加密输入/解密结果 */
|
|
21
21
|
export interface PlainData {
|
|
22
22
|
/** 附加数据 */
|
|
23
|
-
aad
|
|
23
|
+
aad: Uint8Array;
|
|
24
24
|
/** 明文数据 */
|
|
25
25
|
data: Uint8Array;
|
|
26
26
|
}
|
|
@@ -30,7 +30,7 @@ export interface EncryptedData {
|
|
|
30
30
|
/** NONCE */
|
|
31
31
|
nonce: Uint8Array;
|
|
32
32
|
/** 附加数据 */
|
|
33
|
-
aad
|
|
33
|
+
aad: Uint8Array;
|
|
34
34
|
/** 加密后的数据和 tag */
|
|
35
35
|
data: Uint8Array;
|
|
36
36
|
}
|
|
@@ -39,13 +39,13 @@ export interface EncryptedData {
|
|
|
39
39
|
* CloudPSS 数据加密
|
|
40
40
|
* - 密钥生成算法:PBKDF2-HMAC-SHA256,盐长度 96,迭代 100,000 次
|
|
41
41
|
* - 加密算法:AES-256-GCM,使用与密钥生成算法的盐作为 NONCE,TAG 长度 128
|
|
42
|
-
* - 附加数据:最大长度
|
|
42
|
+
* - 附加数据:最大长度 256MiB -1B
|
|
43
43
|
*
|
|
44
44
|
* - 文件格式:
|
|
45
45
|
* - Magic Number: 0e 02 49 29 3f 07 7b 0a
|
|
46
46
|
* - Nonce: 96 bits
|
|
47
47
|
* - Length of AAD: 4 bytes
|
|
48
|
-
* - AAD (if exists)
|
|
48
|
+
* - AAD (if exists) (padded to 128 bits)
|
|
49
49
|
* - Encrypted Data
|
|
50
50
|
* - Auth Tag: 128 bits
|
|
51
51
|
*/
|
|
@@ -83,7 +83,7 @@ export function parseEncrypted(data: BinaryData): EncryptedData | undefined {
|
|
|
83
83
|
MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE,
|
|
84
84
|
MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE + aadSize,
|
|
85
85
|
)
|
|
86
|
-
:
|
|
86
|
+
: EMPTY_BUFFER;
|
|
87
87
|
const encrypted = buffer.subarray(MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE + paddingAadSize);
|
|
88
88
|
return { nonce, aad, data: encrypted };
|
|
89
89
|
}
|
package/src/encryption/index.ts
CHANGED
|
@@ -18,7 +18,9 @@ export function extractAad(data: BinaryData): Uint8Array | undefined {
|
|
|
18
18
|
if (encrypted == null) {
|
|
19
19
|
throw new TypeError('Invalid encrypted data');
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
const { aad } = encrypted;
|
|
22
|
+
if (!aad.byteLength) return undefined;
|
|
23
|
+
return aad;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
package/src/encryption/module.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { toUint8Array } from '../utils.js';
|
|
1
|
+
import { EMPTY_BUFFER, toUint8Array } from '../utils.js';
|
|
2
2
|
import {
|
|
3
3
|
AAD_LEN_SIZE,
|
|
4
4
|
AAD_MAX_SIZE,
|
|
@@ -50,7 +50,7 @@ export function createModule(impl: typeof import('#encryption') | typeof import(
|
|
|
50
50
|
}
|
|
51
51
|
const paddedAddSize = padding(aadSize, AAD_PADDING);
|
|
52
52
|
const plain: PlainData = {
|
|
53
|
-
aad: aadSize ? toUint8Array(aad!) :
|
|
53
|
+
aad: aadSize ? toUint8Array(aad!) : EMPTY_BUFFER,
|
|
54
54
|
data: toUint8Array(data),
|
|
55
55
|
};
|
|
56
56
|
const encrypted = await impl.encrypt(plain, passphrase);
|
|
@@ -64,7 +64,7 @@ export function createModule(impl: typeof import('#encryption') | typeof import(
|
|
|
64
64
|
result[MAGIC_NUMBER.length + NONCE_SIZE + 1] = aadSize >>> 16;
|
|
65
65
|
result[MAGIC_NUMBER.length + NONCE_SIZE + 2] = aadSize >>> 8;
|
|
66
66
|
result[MAGIC_NUMBER.length + NONCE_SIZE + 3] = aadSize;
|
|
67
|
-
result.set(plain.aad
|
|
67
|
+
result.set(plain.aad, MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE);
|
|
68
68
|
}
|
|
69
69
|
result.set(encrypted.data, MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE + paddedAddSize);
|
|
70
70
|
return result;
|
package/src/encryption/node.ts
CHANGED
|
@@ -20,10 +20,11 @@ export async function encrypt({ data, aad }: PlainData, passphrase: string): Pro
|
|
|
20
20
|
const nonce = randomBytes(NONCE_SIZE);
|
|
21
21
|
const key = await aesKdf(passphrase, nonce);
|
|
22
22
|
const cipher = createCipheriv('aes-256-gcm', key, nonce, { authTagLength: AES_TAG_SIZE });
|
|
23
|
-
if (aad) cipher.setAAD(aad);
|
|
23
|
+
if (aad.byteLength) cipher.setAAD(aad);
|
|
24
24
|
const encrypted = Buffer.concat([cipher.update(data), cipher.final(), cipher.getAuthTag()]);
|
|
25
25
|
return {
|
|
26
26
|
nonce: toUint8Array(nonce),
|
|
27
|
+
aad,
|
|
27
28
|
data: toUint8Array(encrypted),
|
|
28
29
|
};
|
|
29
30
|
}
|
|
@@ -33,7 +34,7 @@ export async function decrypt({ nonce, aad, data }: EncryptedData, passphrase: s
|
|
|
33
34
|
const key = await aesKdf(passphrase, nonce);
|
|
34
35
|
const decipher = createDecipheriv('aes-256-gcm', key, nonce, { authTagLength: AES_TAG_SIZE });
|
|
35
36
|
decipher.setAuthTag(data.subarray(data.length - AES_TAG_SIZE));
|
|
36
|
-
if (aad) decipher.setAAD(aad);
|
|
37
|
+
if (aad.byteLength) decipher.setAAD(aad);
|
|
37
38
|
const decrypted = Buffer.concat([decipher.update(data.subarray(0, data.length - AES_TAG_SIZE)), decipher.final()]);
|
|
38
|
-
return { data: toUint8Array(decrypted) };
|
|
39
|
+
return { data: toUint8Array(decrypted), aad };
|
|
39
40
|
}
|
package/src/encryption/wasm.ts
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
} from './common.js';
|
|
9
9
|
import * as mod from '#lib-wasm';
|
|
10
10
|
|
|
11
|
-
const EMPTY = new Uint8Array(0);
|
|
12
11
|
const encoder = new TextEncoder();
|
|
13
12
|
|
|
14
13
|
/** crypto-js encrypt */
|
|
@@ -17,7 +16,7 @@ export function encrypt({ data, aad }: PlainData, passphrase: string): Encrypted
|
|
|
17
16
|
const result = mod.encrypt(
|
|
18
17
|
encoder.encode(passphrase),
|
|
19
18
|
data,
|
|
20
|
-
aad
|
|
19
|
+
aad,
|
|
21
20
|
nonce,
|
|
22
21
|
PBKDF2_ITERATIONS,
|
|
23
22
|
AES_KEY_SIZE,
|
|
@@ -25,6 +24,7 @@ export function encrypt({ data, aad }: PlainData, passphrase: string): Encrypted
|
|
|
25
24
|
);
|
|
26
25
|
return {
|
|
27
26
|
nonce,
|
|
27
|
+
aad,
|
|
28
28
|
data: result,
|
|
29
29
|
};
|
|
30
30
|
}
|
|
@@ -34,13 +34,14 @@ export function decrypt({ data, aad, nonce }: EncryptedData, passphrase: string)
|
|
|
34
34
|
const decrypted = mod.decrypt(
|
|
35
35
|
encoder.encode(passphrase),
|
|
36
36
|
data,
|
|
37
|
-
aad
|
|
37
|
+
aad,
|
|
38
38
|
nonce,
|
|
39
39
|
PBKDF2_ITERATIONS,
|
|
40
40
|
AES_KEY_SIZE,
|
|
41
41
|
AES_TAG_SIZE,
|
|
42
42
|
);
|
|
43
43
|
return {
|
|
44
|
+
aad,
|
|
44
45
|
data: decrypted,
|
|
45
46
|
};
|
|
46
47
|
}
|
package/src/encryption/web.ts
CHANGED
|
@@ -40,6 +40,7 @@ export async function encrypt({ data, aad }: PlainData, passphrase: string): Pro
|
|
|
40
40
|
);
|
|
41
41
|
return {
|
|
42
42
|
nonce,
|
|
43
|
+
aad,
|
|
43
44
|
data: new Uint8Array(encrypted),
|
|
44
45
|
};
|
|
45
46
|
}
|
|
@@ -57,5 +58,8 @@ export async function decrypt({ data, nonce, aad }: EncryptedData, passphrase: s
|
|
|
57
58
|
key,
|
|
58
59
|
data,
|
|
59
60
|
);
|
|
60
|
-
return {
|
|
61
|
+
return {
|
|
62
|
+
aad,
|
|
63
|
+
data: new Uint8Array(decrypted),
|
|
64
|
+
};
|
|
61
65
|
}
|
package/src/utils.ts
CHANGED
package/tests/encryption.js
CHANGED
|
@@ -7,13 +7,14 @@ import * as browserImpl from '../dist/encryption/browser.js';
|
|
|
7
7
|
import * as webImpl from '../dist/encryption/web.js';
|
|
8
8
|
import * as wasmImpl from '../dist/encryption/wasm.js';
|
|
9
9
|
|
|
10
|
-
const data =
|
|
11
|
-
Buffer.from(''),
|
|
12
|
-
Buffer.from('Hello, World!'),
|
|
13
|
-
Buffer.from('Hello, World!'.repeat(100)),
|
|
14
|
-
new Uint8Array(100),
|
|
15
|
-
Buffer.from('Hello, World!'.repeat(1000)).buffer,
|
|
16
|
-
|
|
10
|
+
const data = Object.entries({
|
|
11
|
+
empty: Buffer.from(''),
|
|
12
|
+
short: Buffer.from('Hello, World!'),
|
|
13
|
+
long: Buffer.from('Hello, World!'.repeat(100)),
|
|
14
|
+
zeros: new Uint8Array(100),
|
|
15
|
+
longlong: Buffer.from('Hello, World!'.repeat(1000)).buffer,
|
|
16
|
+
unaligned: Buffer.from('Hello, World!'.repeat(1000)).subarray(1),
|
|
17
|
+
}).map(([k, d]) => ({ raw: d, length: d.byteLength, type: d.constructor.name, tag: k }));
|
|
17
18
|
const passphrase = 'test';
|
|
18
19
|
|
|
19
20
|
describe('Encryption root export', () => {
|
|
@@ -110,7 +111,7 @@ function checkModule(module) {
|
|
|
110
111
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
111
112
|
const { encrypt, decrypt, encryptAad } = module;
|
|
112
113
|
|
|
113
|
-
it.each(data)('encrypt/decrypt $type[$length]', async ({ raw }) => {
|
|
114
|
+
it.each(data)('encrypt/decrypt $type[$length] ($tag)', async ({ raw }) => {
|
|
114
115
|
const encrypted = await encrypt(raw, passphrase);
|
|
115
116
|
expect(encrypted).toBeInstanceOf(Uint8Array);
|
|
116
117
|
expect(encrypted.byteLength).toBeGreaterThan(raw.byteLength);
|
|
@@ -125,7 +126,7 @@ function checkModule(module) {
|
|
|
125
126
|
expect(decrypted).toEqual(toUint8Array(raw));
|
|
126
127
|
});
|
|
127
128
|
|
|
128
|
-
it.each(data)('encrypt/decrypt $type[$length] with aad', async ({ raw }) => {
|
|
129
|
+
it.each(data)('encrypt/decrypt $type[$length] ($tag) with aad', async ({ raw }) => {
|
|
129
130
|
const aad = Buffer.from('Hello, AAD!');
|
|
130
131
|
const encrypted = await encryptAad(raw, aad, passphrase);
|
|
131
132
|
expect(encrypted).toBeInstanceOf(Uint8Array);
|
|
@@ -153,12 +154,13 @@ function checkModule(module) {
|
|
|
153
154
|
*/
|
|
154
155
|
function checkImplEncryption(encrypt, decrypt) {
|
|
155
156
|
it.each(data)(
|
|
156
|
-
`$type[$length]`,
|
|
157
|
+
`$type[$length] ($tag)`,
|
|
157
158
|
async ({ raw }) => {
|
|
158
|
-
const encrypted = await encrypt({ data: toUint8Array(raw) }, passphrase);
|
|
159
|
+
const encrypted = await encrypt({ data: toUint8Array(raw), aad: new Uint8Array(0) }, passphrase);
|
|
159
160
|
expect(encrypted.nonce).toBeInstanceOf(Uint8Array);
|
|
160
161
|
expect(encrypted.nonce.byteLength).toBe(12);
|
|
161
|
-
expect(encrypted.aad).
|
|
162
|
+
expect(encrypted.aad).toBeInstanceOf(Uint8Array);
|
|
163
|
+
expect(encrypted.aad.byteLength).toBe(0);
|
|
162
164
|
expect(encrypted.data).toBeInstanceOf(Uint8Array);
|
|
163
165
|
|
|
164
166
|
await expect(async () => {
|
|
@@ -168,12 +170,13 @@ function checkImplEncryption(encrypt, decrypt) {
|
|
|
168
170
|
const decrypted = await decrypt(encrypted, passphrase);
|
|
169
171
|
expect(decrypted.data).toBeInstanceOf(Uint8Array);
|
|
170
172
|
expect(decrypted.data).toEqual(toUint8Array(raw));
|
|
171
|
-
expect(decrypted.aad).
|
|
173
|
+
expect(decrypted.aad).toBeInstanceOf(Uint8Array);
|
|
174
|
+
expect(decrypted.aad.byteLength).toBe(0);
|
|
172
175
|
},
|
|
173
176
|
100_000,
|
|
174
177
|
);
|
|
175
178
|
it.each(data)(
|
|
176
|
-
`(aad) $type[$length]`,
|
|
179
|
+
`(aad) $type[$length] ($tag)`,
|
|
177
180
|
async ({ raw }) => {
|
|
178
181
|
const aad = Buffer.from('Hello, AAD!');
|
|
179
182
|
const encrypted = await encrypt({ data: toUint8Array(raw), aad }, passphrase);
|