@cloudpss/crypto 0.6.15 → 0.6.16

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/README.md CHANGED
@@ -1,3 +1,13 @@
1
1
  # @cloudpss/crypto
2
2
 
3
3
  Pre-configured crypto libraries for use in CloudPSS.
4
+
5
+ ## Example
6
+
7
+ ```ts
8
+ import { encrypt, decrypt, isEncrypted } from '@cloudpss/crypto';
9
+
10
+ const encrypted = await encrypt(new TextEncoder().encode('secret'), 'passphrase');
11
+ const ok = isEncrypted(encrypted);
12
+ const plain = await decrypt(encrypted, 'passphrase');
13
+ ```
@@ -1,4 +1,6 @@
1
1
  import type { EncryptedData, PlainData } from './common.js';
2
+ /** For test purposes */
3
+ export declare function resetModuleLoader(): void;
2
4
  /** browser encrypt */
3
5
  export declare function encrypt(data: PlainData, passphrase: string): Promise<EncryptedData>;
4
6
  /** browser decrypt */
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/encryption/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAiB5D,sBAAsB;AACtB,wBAAsB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAGzF;AAED,sBAAsB;AACtB,wBAAsB,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAGzF"}
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/encryption/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAoB5D,wBAAwB;AACxB,wBAAgB,iBAAiB,IAAI,IAAI,CAOxC;AAID,sBAAsB;AACtB,wBAAsB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAGzF;AAED,sBAAsB;AACtB,wBAAsB,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAGzF"}
@@ -1,4 +1,5 @@
1
- const module = async () => {
1
+ /** 动态选择加密模块 */
2
+ async function loadModule() {
2
3
  if (typeof crypto == 'object' &&
3
4
  typeof crypto.subtle == 'object' &&
4
5
  typeof crypto.subtle.importKey == 'function' &&
@@ -10,7 +11,18 @@ const module = async () => {
10
11
  else {
11
12
  return import('./wasm.js');
12
13
  }
13
- };
14
+ }
15
+ let module;
16
+ /** For test purposes */
17
+ export function resetModuleLoader() {
18
+ module = async () => {
19
+ const mod = await loadModule();
20
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
21
+ module = () => Promise.resolve(mod);
22
+ return mod;
23
+ };
24
+ }
25
+ resetModuleLoader();
14
26
  /** browser encrypt */
15
27
  export async function encrypt(data, passphrase) {
16
28
  const { encrypt } = await module();
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/encryption/browser.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;IACtB,IACI,OAAO,MAAM,IAAI,QAAQ;QACzB,OAAO,MAAM,CAAC,MAAM,IAAI,QAAQ;QAChC,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,UAAU;QAC5C,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,UAAU;QAC5C,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,UAAU;QAC1C,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,UAAU,EAC5C,CAAC;QACC,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACJ,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;AACL,CAAC,CAAC;AAEF,sBAAsB;AACtB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAe,EAAE,UAAkB;IAC7D,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,EAAE,CAAC;IACnC,OAAO,MAAM,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED,sBAAsB;AACtB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAmB,EAAE,UAAkB;IACjE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,EAAE,CAAC;IACnC,OAAO,MAAM,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/encryption/browser.ts"],"names":[],"mappings":"AAEA,eAAe;AACf,KAAK,UAAU,UAAU;IACrB,IACI,OAAO,MAAM,IAAI,QAAQ;QACzB,OAAO,MAAM,CAAC,MAAM,IAAI,QAAQ;QAChC,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,UAAU;QAC5C,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,UAAU;QAC5C,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,UAAU;QAC1C,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,UAAU,EAC5C,CAAC;QACC,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACJ,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;AACL,CAAC;AAED,IAAI,MAAyB,CAAC;AAE9B,wBAAwB;AACxB,MAAM,UAAU,iBAAiB;IAC7B,MAAM,GAAG,KAAK,IAAI,EAAE;QAChB,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;QAC/B,qEAAqE;QACrE,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,OAAO,GAAG,CAAC;IACf,CAAC,CAAC;AACN,CAAC;AAED,iBAAiB,EAAE,CAAC;AAEpB,sBAAsB;AACtB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAe,EAAE,UAAkB;IAC7D,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,EAAE,CAAC;IACnC,OAAO,MAAM,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED,sBAAsB;AACtB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAmB,EAAE,UAAkB;IACjE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,EAAE,CAAC;IACnC,OAAO,MAAM,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC"}
@@ -5,22 +5,28 @@ export declare function isEncrypted(data: BufferSource): boolean;
5
5
  * 从加密数据中提取附加数据
6
6
  * @throws {TypeError} 如果数据不是有效的加密数据
7
7
  */
8
- export declare function extractAad(data: BufferSource): Uint8Array | undefined;
8
+ export declare function extractAad(data: BufferSource): Uint8Array<ArrayBuffer> | undefined;
9
9
  export declare const
10
10
  /**
11
- * 加密数据
11
+ * 加密数据,包含不加密的附加数据
12
12
  * @throws {TypeError} 如果密码无效
13
13
  */
14
- encrypt: (data: BufferSource, passphrase: string) => Promise<Uint8Array<ArrayBuffer>>,
14
+ encryptAad: (data: BufferSource, aad: BufferSource | undefined, passphrase: string) => Promise<Uint8Array<ArrayBuffer>>,
15
15
  /**
16
- * 加密数据,包含不加密的附加数据
16
+ * 解密数据,包含不加密的附加数据
17
+ * @throws {TypeError} 如果数据不是有效的加密数据
17
18
  * @throws {TypeError} 如果密码无效
18
19
  */
19
- encryptAad: (data: BufferSource, aad: BufferSource | undefined, passphrase: string) => Promise<Uint8Array<ArrayBuffer>>,
20
+ decryptAad: (data: BufferSource, passphrase: string) => Promise<import("./common.js").PlainData>;
21
+ /**
22
+ * 加密数据
23
+ * @throws {TypeError} 如果密码无效
24
+ */
25
+ export declare function encrypt(data: BufferSource, passphrase: string): Promise<Uint8Array<ArrayBuffer>>;
20
26
  /**
21
27
  * 解密数据
22
28
  * @throws {TypeError} 如果数据不是有效的加密数据
23
29
  * @throws {TypeError} 如果密码无效
24
30
  */
25
- decrypt: (data: BufferSource, passphrase: string) => Promise<Uint8Array<ArrayBuffer>>;
31
+ export declare function decrypt(data: BufferSource, passphrase: string): Promise<Uint8Array<ArrayBuffer>>;
26
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/encryption/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,0BAA0B;AAC1B,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAEvD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,SAAS,CAQrE;AAED,eAAO;AACH;;;GAGG;AAEH,OAAO;AACP;;;GAGG;AAEH,UAAU;AACV;;;;GAIG;AAEH,OAAO,8EACW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/encryption/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,0BAA0B;AAC1B,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAEvD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,SAAS,CAQlF;AAED,eAAO;AACH;;;GAGG;AAEH,UAAU;AACV;;;;GAIG;AAEH,UAAU,sFACQ,CAAC;AAEvB;;;GAGG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAEtG;AACD;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAGtG"}
@@ -22,22 +22,32 @@ export function extractAad(data) {
22
22
  }
23
23
  export const {
24
24
  /**
25
- * 加密数据
25
+ * 加密数据,包含不加密的附加数据
26
26
  * @throws {TypeError} 如果密码无效
27
27
  */
28
28
  // eslint-disable-next-line @typescript-eslint/unbound-method
29
- encrypt,
29
+ encryptAad,
30
30
  /**
31
- * 加密数据,包含不加密的附加数据
31
+ * 解密数据,包含不加密的附加数据
32
+ * @throws {TypeError} 如果数据不是有效的加密数据
32
33
  * @throws {TypeError} 如果密码无效
33
34
  */
34
35
  // eslint-disable-next-line @typescript-eslint/unbound-method
35
- encryptAad,
36
+ decryptAad, } = createModule(impl);
37
+ /**
38
+ * 加密数据
39
+ * @throws {TypeError} 如果密码无效
40
+ */
41
+ export async function encrypt(data, passphrase) {
42
+ return await encryptAad(data, undefined, passphrase);
43
+ }
36
44
  /**
37
45
  * 解密数据
38
46
  * @throws {TypeError} 如果数据不是有效的加密数据
39
47
  * @throws {TypeError} 如果密码无效
40
48
  */
41
- // eslint-disable-next-line @typescript-eslint/unbound-method
42
- decrypt, } = createModule(impl);
49
+ export async function decrypt(data, passphrase) {
50
+ const decrypted = await decryptAad(data, passphrase);
51
+ return decrypted.data;
52
+ }
43
53
  //# sourceMappingURL=index.js.map
@@ -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,IAAkB;IAC1C,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAkB;IACzC,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,MAAM,CAAC,MAAM;AACT;;;GAGG;AACH,6DAA6D;AAC7D,OAAO;AACP;;;GAGG;AACH,6DAA6D;AAC7D,UAAU;AACV;;;;GAIG;AACH,6DAA6D;AAC7D,OAAO,GACV,GAAG,YAAY,CAAC,IAAI,CAAC,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,IAAkB;IAC1C,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAkB;IACzC,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,MAAM,CAAC,MAAM;AACT;;;GAGG;AACH,6DAA6D;AAC7D,UAAU;AACV;;;;GAIG;AACH,6DAA6D;AAC7D,UAAU,GACb,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;AAEvB;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAkB,EAAE,UAAkB;IAChE,OAAO,MAAM,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AACzD,CAAC;AACD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAkB,EAAE,UAAkB;IAChE,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACrD,OAAO,SAAS,CAAC,IAAI,CAAC;AAC1B,CAAC"}
@@ -1,21 +1,17 @@
1
+ import { type PlainData } from './common.js';
1
2
  /** 模块 */
2
3
  interface Module {
3
- /**
4
- * 加密数据
5
- * @throws {TypeError} 如果密码无效
6
- */
7
- encrypt(data: BufferSource, passphrase: string): Promise<Uint8Array<ArrayBuffer>>;
8
4
  /**
9
5
  * 加密数据,包含不加密的附加数据
10
6
  * @throws {TypeError} 如果密码无效
11
7
  */
12
8
  encryptAad(data: BufferSource, aad: BufferSource | undefined, passphrase: string): Promise<Uint8Array<ArrayBuffer>>;
13
9
  /**
14
- * 解密数据
10
+ * 解密数据,包含不加密的附加数据
15
11
  * @throws {TypeError} 如果数据不是有效的加密数据
16
12
  * @throws {TypeError} 如果密码无效
17
13
  */
18
- decrypt(data: BufferSource, passphrase: string): Promise<Uint8Array<ArrayBuffer>>;
14
+ decryptAad(data: BufferSource, passphrase: string): Promise<PlainData>;
19
15
  }
20
16
  /** 创建模块 */
21
17
  export declare function createModule(impl: typeof import('#encryption') | typeof import('./wasm.js')): Module;
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/encryption/module.ts"],"names":[],"mappings":"AAsBA,SAAS;AACT,UAAU,MAAM;IACZ;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IAClF;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACpH;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;CACrF;AAED,WAAW;AACX,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,aAAa,CAAC,GAAG,cAAc,WAAW,CAAC,GAAG,MAAM,CAkDpG"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/encryption/module.ts"],"names":[],"mappings":"AACA,OAAO,EAQH,KAAK,SAAS,EACjB,MAAM,aAAa,CAAC;AAYrB,SAAS;AACT,UAAU,MAAM;IACZ;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACpH;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CAC1E;AAED,WAAW;AACX,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,aAAa,CAAC,GAAG,cAAc,WAAW,CAAC,GAAG,MAAM,CA8CpG"}
@@ -36,27 +36,22 @@ export function createModule(impl) {
36
36
  result.set(encrypted.data, MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE + paddedAddSize);
37
37
  return result;
38
38
  };
39
- const encrypt = async (data, passphrase) => {
40
- return await encryptAad(data, undefined, passphrase);
41
- };
42
- const decrypt = async (data, passphrase) => {
39
+ const decryptAad = async (data, passphrase) => {
43
40
  assertPassphrase(passphrase);
44
41
  const encrypted = parseEncrypted(data);
45
42
  if (encrypted == null) {
46
43
  throw new TypeError('Invalid encrypted data');
47
44
  }
48
45
  try {
49
- const result = await impl.decrypt(encrypted, passphrase);
50
- return result.data;
46
+ return await impl.decrypt(encrypted, passphrase);
51
47
  }
52
48
  catch (ex) {
53
49
  throw new Error('Wrong passphrase', { cause: ex });
54
50
  }
55
51
  };
56
52
  return {
57
- encrypt,
58
53
  encryptAad,
59
- decrypt,
54
+ decryptAad,
60
55
  };
61
56
  }
62
57
  //# sourceMappingURL=module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/encryption/module.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/encryption/module.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { isEncrypted, encrypt, decrypt, encryptAad, extractAad } from './encryption/index.js';
1
+ export { isEncrypted, encrypt, decrypt, encryptAad, extractAad, decryptAad } from './encryption/index.js';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { isEncrypted, encrypt, decrypt, encryptAad, extractAad } from './encryption/index.js';
1
+ export { isEncrypted, encrypt, decrypt, encryptAad, extractAad, decryptAad } from './encryption/index.js';
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudpss/crypto",
3
- "version": "0.6.15",
3
+ "version": "0.6.16",
4
4
  "author": "CloudPSS",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,6 +1,7 @@
1
1
  import type { EncryptedData, PlainData } from './common.js';
2
2
 
3
- const module = async () => {
3
+ /** 动态选择加密模块 */
4
+ async function loadModule() {
4
5
  if (
5
6
  typeof crypto == 'object' &&
6
7
  typeof crypto.subtle == 'object' &&
@@ -13,7 +14,21 @@ const module = async () => {
13
14
  } else {
14
15
  return import('./wasm.js');
15
16
  }
16
- };
17
+ }
18
+
19
+ let module: typeof loadModule;
20
+
21
+ /** For test purposes */
22
+ export function resetModuleLoader(): void {
23
+ module = async () => {
24
+ const mod = await loadModule();
25
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
26
+ module = () => Promise.resolve(mod);
27
+ return mod;
28
+ };
29
+ }
30
+
31
+ resetModuleLoader();
17
32
 
18
33
  /** browser encrypt */
19
34
  export async function encrypt(data: PlainData, passphrase: string): Promise<EncryptedData> {
@@ -13,7 +13,7 @@ export function isEncrypted(data: BufferSource): boolean {
13
13
  * 从加密数据中提取附加数据
14
14
  * @throws {TypeError} 如果数据不是有效的加密数据
15
15
  */
16
- export function extractAad(data: BufferSource): Uint8Array | undefined {
16
+ export function extractAad(data: BufferSource): Uint8Array<ArrayBuffer> | undefined {
17
17
  const encrypted = parseEncrypted(data);
18
18
  if (encrypted == null) {
19
19
  throw new TypeError('Invalid encrypted data');
@@ -24,12 +24,6 @@ export function extractAad(data: BufferSource): Uint8Array | undefined {
24
24
  }
25
25
 
26
26
  export const {
27
- /**
28
- * 加密数据
29
- * @throws {TypeError} 如果密码无效
30
- */
31
- // eslint-disable-next-line @typescript-eslint/unbound-method
32
- encrypt,
33
27
  /**
34
28
  * 加密数据,包含不加密的附加数据
35
29
  * @throws {TypeError} 如果密码无效
@@ -37,10 +31,27 @@ export const {
37
31
  // eslint-disable-next-line @typescript-eslint/unbound-method
38
32
  encryptAad,
39
33
  /**
40
- * 解密数据
34
+ * 解密数据,包含不加密的附加数据
41
35
  * @throws {TypeError} 如果数据不是有效的加密数据
42
36
  * @throws {TypeError} 如果密码无效
43
37
  */
44
38
  // eslint-disable-next-line @typescript-eslint/unbound-method
45
- decrypt,
39
+ decryptAad,
46
40
  } = createModule(impl);
41
+
42
+ /**
43
+ * 加密数据
44
+ * @throws {TypeError} 如果密码无效
45
+ */
46
+ export async function encrypt(data: BufferSource, passphrase: string): Promise<Uint8Array<ArrayBuffer>> {
47
+ return await encryptAad(data, undefined, passphrase);
48
+ }
49
+ /**
50
+ * 解密数据
51
+ * @throws {TypeError} 如果数据不是有效的加密数据
52
+ * @throws {TypeError} 如果密码无效
53
+ */
54
+ export async function decrypt(data: BufferSource, passphrase: string): Promise<Uint8Array<ArrayBuffer>> {
55
+ const decrypted = await decryptAad(data, passphrase);
56
+ return decrypted.data;
57
+ }
@@ -22,22 +22,17 @@ function assertPassphrase(passphrase: string): void {
22
22
 
23
23
  /** 模块 */
24
24
  interface Module {
25
- /**
26
- * 加密数据
27
- * @throws {TypeError} 如果密码无效
28
- */
29
- encrypt(data: BufferSource, passphrase: string): Promise<Uint8Array<ArrayBuffer>>;
30
25
  /**
31
26
  * 加密数据,包含不加密的附加数据
32
27
  * @throws {TypeError} 如果密码无效
33
28
  */
34
29
  encryptAad(data: BufferSource, aad: BufferSource | undefined, passphrase: string): Promise<Uint8Array<ArrayBuffer>>;
35
30
  /**
36
- * 解密数据
31
+ * 解密数据,包含不加密的附加数据
37
32
  * @throws {TypeError} 如果数据不是有效的加密数据
38
33
  * @throws {TypeError} 如果密码无效
39
34
  */
40
- decrypt(data: BufferSource, passphrase: string): Promise<Uint8Array<ArrayBuffer>>;
35
+ decryptAad(data: BufferSource, passphrase: string): Promise<PlainData>;
41
36
  }
42
37
 
43
38
  /** 创建模块 */
@@ -69,26 +64,22 @@ export function createModule(impl: typeof import('#encryption') | typeof import(
69
64
  result.set(encrypted.data, MAGIC_NUMBER.length + NONCE_SIZE + AAD_LEN_SIZE + paddedAddSize);
70
65
  return result;
71
66
  };
72
- const encrypt: Module['encrypt'] = async (data, passphrase) => {
73
- return await encryptAad(data, undefined, passphrase);
74
- };
75
67
 
76
- const decrypt: Module['decrypt'] = async (data, passphrase) => {
68
+ const decryptAad: Module['decryptAad'] = async (data, passphrase) => {
77
69
  assertPassphrase(passphrase);
78
70
  const encrypted = parseEncrypted(data);
79
71
  if (encrypted == null) {
80
72
  throw new TypeError('Invalid encrypted data');
81
73
  }
82
74
  try {
83
- const result = await impl.decrypt(encrypted, passphrase);
84
- return result.data;
75
+ return await impl.decrypt(encrypted, passphrase);
85
76
  } catch (ex) {
86
77
  throw new Error('Wrong passphrase', { cause: ex });
87
78
  }
88
79
  };
80
+
89
81
  return {
90
- encrypt,
91
82
  encryptAad,
92
- decrypt,
83
+ decryptAad,
93
84
  };
94
85
  }
package/src/index.ts CHANGED
@@ -1 +1 @@
1
- export { isEncrypted, encrypt, decrypt, encryptAad, extractAad } from './encryption/index.js';
1
+ export { isEncrypted, encrypt, decrypt, encryptAad, extractAad, decryptAad } from './encryption/index.js';
@@ -0,0 +1,134 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { isEncrypted, extractAad, type encryptAad as e, type decryptAad as d } from '../dist/index.js';
3
+ import { toUint8Array } from '../dist/utils.js';
4
+ import type * as nodeImpl from '../dist/encryption/node.js';
5
+ import type * as webImpl from '../dist/encryption/web.js';
6
+ import type * as wasmImpl from '../dist/encryption/wasm.js';
7
+
8
+ const data = Object.entries({
9
+ empty: Buffer.from(''),
10
+ short: Buffer.from('Hello, World!'),
11
+ long: Buffer.from('Hello, World!'.repeat(100)),
12
+ zeros: new Uint8Array(100),
13
+ longlong: Buffer.from('Hello, World!'.repeat(1000)).buffer,
14
+ unaligned: Buffer.from('Hello, World!'.repeat(1000)).subarray(1),
15
+ }).map(([k, d]) => ({ raw: d, length: d.byteLength, type: d.constructor.name, tag: k }));
16
+
17
+ const passphrase = randomUUID();
18
+
19
+ /**
20
+ * 检查实现模块
21
+ */
22
+ export function checkModule(module: { decryptAad: typeof d; encryptAad: typeof e }): void {
23
+ it('has correct exports', () => {
24
+ expect(module).toMatchObject({
25
+ decryptAad: expect.any(Function) as unknown,
26
+ encryptAad: expect.any(Function) as unknown,
27
+ });
28
+ });
29
+
30
+ const { decryptAad, encryptAad } = module;
31
+
32
+ it.each(data)('encrypt/decrypt $type[$length] ($tag)', async ({ raw }) => {
33
+ const encrypted = await encryptAad(raw, undefined, passphrase);
34
+ expect(encrypted).toBeInstanceOf(Uint8Array);
35
+ expect(encrypted.byteLength).toBeGreaterThan(raw.byteLength);
36
+ expect(isEncrypted(encrypted)).toBe(true);
37
+
38
+ await expect(async () => {
39
+ await decryptAad(encrypted, 'xx');
40
+ }).rejects.toThrow();
41
+
42
+ const decrypted = await decryptAad(encrypted, passphrase);
43
+ expect(decrypted.data).toBeInstanceOf(Uint8Array);
44
+ expect(decrypted.data).toEqual(toUint8Array(raw));
45
+ expect(decrypted.aad).toBeInstanceOf(Uint8Array);
46
+ expect(decrypted.aad.byteLength).toBe(0);
47
+ });
48
+
49
+ it.each(data)('encrypt/decrypt $type[$length] ($tag) with aad', async ({ raw }) => {
50
+ const aad = Buffer.from('Hello, AAD!');
51
+ const encrypted = await encryptAad(raw, aad, passphrase);
52
+ expect(encrypted).toBeInstanceOf(Uint8Array);
53
+ expect(encrypted.byteLength).toBeGreaterThan(raw.byteLength);
54
+ expect(isEncrypted(encrypted)).toBe(true);
55
+
56
+ const extractedAad = extractAad(encrypted);
57
+ expect(extractedAad).toBeInstanceOf(Uint8Array);
58
+ expect(extractedAad).toEqual(toUint8Array(aad));
59
+
60
+ await expect(async () => {
61
+ await decryptAad(encrypted, 'xx');
62
+ }).rejects.toThrow();
63
+
64
+ const decrypted = await decryptAad(encrypted, passphrase);
65
+ expect(decrypted.data).toBeInstanceOf(Uint8Array);
66
+ expect(decrypted.data).toEqual(toUint8Array(raw));
67
+ expect(decrypted.aad).toBeInstanceOf(Uint8Array);
68
+ expect(decrypted.aad).toEqual(toUint8Array(aad));
69
+ });
70
+ }
71
+
72
+ /**
73
+ * 检查实现
74
+ */
75
+ export function checkImplEncryption(
76
+ encrypt: typeof webImpl.encrypt | typeof wasmImpl.encrypt | typeof nodeImpl.encrypt,
77
+ decrypt: typeof webImpl.decrypt | typeof wasmImpl.decrypt | typeof nodeImpl.decrypt,
78
+ ): void {
79
+ it.each(data)(
80
+ `$type[$length] ($tag)`,
81
+ async ({ raw }) => {
82
+ const encrypted = await encrypt({ data: toUint8Array(raw), aad: new Uint8Array(0) }, passphrase);
83
+ expect(encrypted.nonce).toBeInstanceOf(Uint8Array);
84
+ expect(encrypted.nonce.byteLength).toBe(12);
85
+ expect(encrypted.aad).toBeInstanceOf(Uint8Array);
86
+ expect(encrypted.aad.byteLength).toBe(0);
87
+ expect(encrypted.data).toBeInstanceOf(Uint8Array);
88
+
89
+ await expect(async () => {
90
+ await decrypt(encrypted, 'xx');
91
+ }).rejects.toThrow();
92
+
93
+ const decrypted = await decrypt(encrypted, passphrase);
94
+ expect(decrypted.data).toBeInstanceOf(Uint8Array);
95
+ expect(decrypted.data).toEqual(toUint8Array(raw));
96
+ expect(decrypted.aad).toBeInstanceOf(Uint8Array);
97
+ expect(decrypted.aad.byteLength).toBe(0);
98
+ },
99
+ 100_000,
100
+ );
101
+ it.each(data)(
102
+ `(aad) $type[$length] ($tag)`,
103
+ async ({ raw }) => {
104
+ const aad = Buffer.from('Hello, AAD!');
105
+ const encrypted = await encrypt({ data: toUint8Array(raw), aad }, passphrase);
106
+ expect(encrypted.nonce).toBeInstanceOf(Uint8Array);
107
+ expect(encrypted.nonce.byteLength).toBe(12);
108
+ expect(encrypted.data).toBeInstanceOf(Uint8Array);
109
+
110
+ await expect(async () => {
111
+ await decrypt(
112
+ // @ts-expect-error no aad
113
+ {
114
+ nonce: encrypted.nonce,
115
+ data: encrypted.data,
116
+ },
117
+ passphrase,
118
+ );
119
+ }).rejects.toThrow();
120
+
121
+ const decrypted = await decrypt(
122
+ {
123
+ nonce: encrypted.nonce,
124
+ aad: toUint8Array(aad),
125
+ data: encrypted.data,
126
+ },
127
+ passphrase,
128
+ );
129
+ expect(decrypted.data).toBeInstanceOf(Uint8Array);
130
+ expect(decrypted.data).toEqual(toUint8Array(raw));
131
+ },
132
+ 100_000,
133
+ );
134
+ }
@@ -0,0 +1,28 @@
1
+ import { createModule } from '../dist/encryption/module.js';
2
+ import * as browserImpl from '../dist/encryption/browser.js';
3
+
4
+ import { checkModule } from './.check.ts';
5
+
6
+ describe('Encryption impl browser', () => {
7
+ const { subtle } = crypto;
8
+ describe('should work with crypto subtle', () => {
9
+ beforeAll(() => {
10
+ browserImpl.resetModuleLoader();
11
+ });
12
+ test('subtle exists', () => {
13
+ expect(crypto.subtle).toEqual(expect.any(Object));
14
+ });
15
+ checkModule(createModule(browserImpl));
16
+ });
17
+ describe('should work without crypto subtle', () => {
18
+ beforeAll(() => {
19
+ Object.defineProperty(crypto, 'subtle', { value: undefined, configurable: true });
20
+ browserImpl.resetModuleLoader();
21
+ });
22
+ afterAll(() => {
23
+ Object.defineProperty(crypto, 'subtle', { value: subtle, configurable: true });
24
+ browserImpl.resetModuleLoader();
25
+ });
26
+ checkModule(createModule(browserImpl));
27
+ });
28
+ });
@@ -1,21 +1,8 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import { MAGIC_NUMBER } from '../dist/encryption/index.js';
2
- import { isEncrypted, encrypt, decrypt, encryptAad, extractAad } from '../dist/index.js';
3
- import { toUint8Array } from '../dist/utils.js';
4
- import { createModule } from '../dist/encryption/module.js';
5
- import * as nodeImpl from '../dist/encryption/node.js';
6
- import * as browserImpl from '../dist/encryption/browser.js';
7
- import * as webImpl from '../dist/encryption/web.js';
8
- import * as wasmImpl from '../dist/encryption/wasm.js';
9
-
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 }));
18
- const passphrase = 'test';
3
+ import { isEncrypted, encrypt, decrypt, encryptAad, decryptAad, extractAad } from '../dist/index.js';
4
+
5
+ const passphrase = randomUUID();
19
6
 
20
7
  describe('Encryption root export', () => {
21
8
  it('has MAGIC_NUMBER', () => {
@@ -64,6 +51,18 @@ describe('Encryption root export', () => {
64
51
  await expect(async () => decrypt(Buffer.alloc(100), 'xx')).rejects.toThrow('Invalid encrypted data');
65
52
  });
66
53
 
54
+ it('encrypt/decrypt', async () => {
55
+ const raw = Buffer.from('Hello, World!');
56
+ const encrypted = await encrypt(raw, passphrase);
57
+ expect(encrypted).toBeInstanceOf(Uint8Array);
58
+ expect(isEncrypted(encrypted)).toBe(true);
59
+
60
+ const decrypted = await decrypt(encrypted, passphrase);
61
+ expect(decrypted).toBeInstanceOf(Uint8Array);
62
+ expect(decrypted).toEqual(raw);
63
+ expect(decrypted).not.toBe(raw);
64
+ });
65
+
67
66
  describe('aad', () => {
68
67
  it('accepts empty aad', async () => {
69
68
  const encrypted = await encryptAad(Buffer.alloc(0), Buffer.alloc(0), passphrase);
@@ -79,166 +78,37 @@ describe('Encryption root export', () => {
79
78
  expect(extractedAad).toBeUndefined();
80
79
  });
81
80
 
82
- it('rejects invalid aad size', async () => {
83
- const aad2 = Buffer.alloc(1024 * 1024 * 1024 + 1);
84
- await expect(async () => {
85
- await encryptAad(Buffer.alloc(0), aad2, passphrase);
86
- }).rejects.toThrow('Invalid AAD size');
87
- });
88
-
89
- it('rejects invalid data', () => {
90
- const data = Buffer.alloc(10);
91
- expect(() => extractAad(data)).toThrow('Invalid encrypted data');
92
- });
93
- });
94
-
95
- checkModule({ encrypt, decrypt, encryptAad });
96
- });
97
-
98
- /**
99
- * 检查实现模块
100
- */
101
- function checkModule(module: { encrypt: typeof encrypt; decrypt: typeof decrypt; encryptAad: typeof encryptAad }) {
102
- it('has correct exports', () => {
103
- expect(module).toMatchObject({
104
- encrypt: expect.any(Function) as unknown,
105
- decrypt: expect.any(Function) as unknown,
106
- encryptAad: expect.any(Function) as unknown,
107
- });
108
- });
109
-
110
- const { encrypt, decrypt, encryptAad } = module;
111
-
112
- it.each(data)('encrypt/decrypt $type[$length] ($tag)', async ({ raw }) => {
113
- const encrypted = await encrypt(raw, passphrase);
114
- expect(encrypted).toBeInstanceOf(Uint8Array);
115
- expect(encrypted.byteLength).toBeGreaterThan(raw.byteLength);
116
- expect(isEncrypted(encrypted)).toBe(true);
117
-
118
- await expect(async () => {
119
- await decrypt(encrypted, 'xx');
120
- }).rejects.toThrow();
121
-
122
- const decrypted = await decrypt(encrypted, passphrase);
123
- expect(decrypted).toBeInstanceOf(Uint8Array);
124
- expect(decrypted).toEqual(toUint8Array(raw));
125
- });
126
-
127
- it.each(data)('encrypt/decrypt $type[$length] ($tag) with aad', async ({ raw }) => {
128
- const aad = Buffer.from('Hello, AAD!');
129
- const encrypted = await encryptAad(raw, aad, passphrase);
130
- expect(encrypted).toBeInstanceOf(Uint8Array);
131
- expect(encrypted.byteLength).toBeGreaterThan(raw.byteLength);
132
- expect(isEncrypted(encrypted)).toBe(true);
133
-
134
- const extractedAad = extractAad(encrypted);
135
- expect(extractedAad).toBeInstanceOf(Uint8Array);
136
- expect(extractedAad).toEqual(toUint8Array(aad));
137
-
138
- await expect(async () => {
139
- await decrypt(encrypted, 'xx');
140
- }).rejects.toThrow();
81
+ it('encrypts and decrypts with aad', async () => {
82
+ const raw = Buffer.from('Hello, World!');
83
+ const aad = Buffer.from('Hello, AAD!');
84
+ const encrypted = await encryptAad(raw, aad, passphrase);
85
+ expect(encrypted).toBeInstanceOf(Uint8Array);
141
86
 
142
- const decrypted = await decrypt(encrypted, passphrase);
143
- expect(decrypted).toBeInstanceOf(Uint8Array);
144
- expect(decrypted).toEqual(toUint8Array(raw));
145
- });
146
- }
147
-
148
- /**
149
- * 检查实现
150
- */
151
- function checkImplEncryption(
152
- encrypt: typeof webImpl.encrypt | typeof wasmImpl.encrypt | typeof nodeImpl.encrypt,
153
- decrypt: typeof webImpl.decrypt | typeof wasmImpl.decrypt | typeof nodeImpl.decrypt,
154
- ) {
155
- it.each(data)(
156
- `$type[$length] ($tag)`,
157
- async ({ raw }) => {
158
- const encrypted = await encrypt({ data: toUint8Array(raw), aad: new Uint8Array(0) }, passphrase);
159
- expect(encrypted.nonce).toBeInstanceOf(Uint8Array);
160
- expect(encrypted.nonce.byteLength).toBe(12);
161
- expect(encrypted.aad).toBeInstanceOf(Uint8Array);
162
- expect(encrypted.aad.byteLength).toBe(0);
163
- expect(encrypted.data).toBeInstanceOf(Uint8Array);
87
+ const extractedAad = extractAad(encrypted);
88
+ expect(extractedAad).toBeInstanceOf(Uint8Array);
89
+ expect(extractedAad).toEqual(aad);
164
90
 
165
91
  await expect(async () => {
166
- await decrypt(encrypted, 'xx');
92
+ await decryptAad(encrypted, 'xx');
167
93
  }).rejects.toThrow();
168
94
 
169
- const decrypted = await decrypt(encrypted, passphrase);
95
+ const decrypted = await decryptAad(encrypted, passphrase);
170
96
  expect(decrypted.data).toBeInstanceOf(Uint8Array);
171
- expect(decrypted.data).toEqual(toUint8Array(raw));
97
+ expect(decrypted.data).toEqual(raw);
172
98
  expect(decrypted.aad).toBeInstanceOf(Uint8Array);
173
- expect(decrypted.aad.byteLength).toBe(0);
174
- },
175
- 100_000,
176
- );
177
- it.each(data)(
178
- `(aad) $type[$length] ($tag)`,
179
- async ({ raw }) => {
180
- const aad = Buffer.from('Hello, AAD!');
181
- const encrypted = await encrypt({ data: toUint8Array(raw), aad }, passphrase);
182
- expect(encrypted.nonce).toBeInstanceOf(Uint8Array);
183
- expect(encrypted.nonce.byteLength).toBe(12);
184
- expect(encrypted.data).toBeInstanceOf(Uint8Array);
99
+ expect(decrypted.aad).toEqual(aad);
100
+ });
185
101
 
102
+ it('rejects invalid aad size', async () => {
103
+ const aad2 = Buffer.alloc(1024 * 1024 * 1024 + 1);
186
104
  await expect(async () => {
187
- await decrypt(
188
- // @ts-expect-error no aad
189
- {
190
- nonce: encrypted.nonce,
191
- data: encrypted.data,
192
- },
193
- passphrase,
194
- );
195
- }).rejects.toThrow();
196
-
197
- const decrypted = await decrypt(
198
- {
199
- nonce: encrypted.nonce,
200
- aad: toUint8Array(aad),
201
- data: encrypted.data,
202
- },
203
- passphrase,
204
- );
205
- expect(decrypted.data).toBeInstanceOf(Uint8Array);
206
- expect(decrypted.data).toEqual(toUint8Array(raw));
207
- },
208
- 100_000,
209
- );
210
- }
211
-
212
- describe('Encryption impl', () => {
213
- const impls = Object.entries({
214
- node: nodeImpl,
215
- browser: browserImpl,
216
- web: webImpl,
217
- wasm: wasmImpl,
218
- });
219
- describe.each(impls)('impl %s', (name, impl) => {
220
- const module = createModule(impl);
221
- checkModule(module);
222
- });
223
- describe.each(impls.slice(1))(`cross impl %s/${impls[0][0]}`, (name, impl) => {
224
- describe(`${impls[0][0]} -> ${name}`, () => {
225
- checkImplEncryption(impls[0][1].encrypt, impl.decrypt);
226
- });
227
- describe(`${name} -> ${impls[0][0]}`, () => {
228
- checkImplEncryption(impl.encrypt, impls[0][1].decrypt);
105
+ await encryptAad(Buffer.alloc(0), aad2, passphrase);
106
+ }).rejects.toThrow('Invalid AAD size');
229
107
  });
230
- });
231
- });
232
108
 
233
- describe('Encryption impl browser', () => {
234
- describe('should work without crypto subtle', () => {
235
- const { subtle } = crypto;
236
- beforeAll(() => {
237
- Object.defineProperty(crypto, 'subtle', { value: undefined, configurable: true });
238
- });
239
- afterAll(() => {
240
- Object.defineProperty(crypto, 'subtle', { value: subtle, configurable: true });
109
+ it('rejects invalid data', () => {
110
+ const data = Buffer.alloc(10);
111
+ expect(() => extractAad(data)).toThrow('Invalid encrypted data');
241
112
  });
242
- checkModule(createModule(browserImpl));
243
113
  });
244
114
  });
@@ -0,0 +1,30 @@
1
+ import { encryptAad, decryptAad } from '../dist/index.js';
2
+ import { createModule } from '../dist/encryption/module.js';
3
+ import * as nodeImpl from '../dist/encryption/node.js';
4
+ import * as webImpl from '../dist/encryption/web.js';
5
+ import * as wasmImpl from '../dist/encryption/wasm.js';
6
+
7
+ import { checkImplEncryption, checkModule } from './.check.ts';
8
+
9
+ describe('Encryption impl', () => {
10
+ const impls = Object.entries({
11
+ node: nodeImpl,
12
+ web: webImpl,
13
+ wasm: wasmImpl,
14
+ });
15
+ describe('root exports', () => {
16
+ checkModule({ encryptAad, decryptAad });
17
+ });
18
+ describe.each(impls)('impl %s', (name, impl) => {
19
+ const module = createModule(impl);
20
+ checkModule(module);
21
+ });
22
+ describe.each(impls.slice(1))(`cross impl %s/${impls[0][0]}`, (name, impl) => {
23
+ describe(`${impls[0][0]} -> ${name}`, () => {
24
+ checkImplEncryption(impls[0][1].encrypt, impl.decrypt);
25
+ });
26
+ describe(`${name} -> ${impls[0][0]}`, () => {
27
+ checkImplEncryption(impl.encrypt, impls[0][1].decrypt);
28
+ });
29
+ });
30
+ });