aes-bridge 2.0.0

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/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "aes-bridge",
3
+ "version": "2.0.0",
4
+ "description": "AesBridge is a modern, secure and cross-language AES encryption library",
5
+ "type": "module",
6
+ "main": "dist/aes-bridge.umd.js",
7
+ "module": "dist/aes-bridge.esm.js",
8
+ "exports": {
9
+ "import": "./dist/aes-bridge.esm.js",
10
+ "require": "./dist/aes-bridge.umd.js"
11
+ },
12
+ "scripts": {
13
+ "build": "rollup -c",
14
+ "test": "vitest"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/mervick/aes-bridge-js.git"
19
+ },
20
+ "keywords": [
21
+ "aes",
22
+ "security",
23
+ "cryptography",
24
+ "encryption"
25
+ ],
26
+ "author": {
27
+ "name": "Andrey Izman",
28
+ "email": "izmanw@gmail.com",
29
+ "url": "https://github.com/mervick"
30
+ },
31
+ "license": "MIT",
32
+ "bugs": {
33
+ "url": "https://github.com/mervick/aes-bridge-js/issues"
34
+ },
35
+ "homepage": "https://github.com/mervick/aes-bridge-js",
36
+ "devDependencies": {
37
+ "@rollup/plugin-commonjs": "^28.0.6",
38
+ "@rollup/plugin-json": "^6.1.0",
39
+ "@rollup/plugin-node-resolve": "^16.0.1",
40
+ "@rollup/plugin-terser": "^0.4.4",
41
+ "vitest": "^3.2.4"
42
+ }
43
+ }
@@ -0,0 +1,38 @@
1
+ import json from '@rollup/plugin-json';
2
+ import terser from '@rollup/plugin-terser';
3
+ // import commonjs from '@rollup/plugin-commonjs';
4
+ import { nodeResolve } from '@rollup/plugin-node-resolve';
5
+
6
+ export default [
7
+ {
8
+ input: 'index.js',
9
+ output: [
10
+ {
11
+ file: 'dist/aes-bridge.esm.js',
12
+ format: 'esm',
13
+ sourcemap: true
14
+ },
15
+ {
16
+ file: 'dist/aes-bridge.umd.js',
17
+ format: 'umd',
18
+ name: 'aes_bridge',
19
+ sourcemap: true
20
+ },
21
+ {
22
+ file: 'dist/aes-bridge.cjs.js',
23
+ format: 'cjs',
24
+ sourcemap: true
25
+ }
26
+ ],
27
+ plugins: [
28
+ // commonjs(),
29
+ nodeResolve(),
30
+ json(),
31
+ terser({
32
+ format: {
33
+ comments: false
34
+ }
35
+ })
36
+ ]
37
+ }
38
+ ];
@@ -0,0 +1,124 @@
1
+ import {
2
+ encryptCbc, decryptCbc,
3
+ encryptGcm, decryptGcm,
4
+ encryptLegacy, decryptLegacy
5
+ } from '../index.js';
6
+
7
+ import { readFile } from 'node:fs/promises';
8
+ import { describe, it, expect } from 'vitest';
9
+
10
+ const encoder = new TextEncoder();
11
+ const decoder = new TextDecoder();
12
+
13
+ function fromHex(hex) {
14
+ return Uint8Array.from(hex.match(/.{1,2}/g).map(b => parseInt(b, 16)));
15
+ }
16
+
17
+ function encodeInput(s, mode) {
18
+ return mode === 'hex' ? fromHex(s) : encoder.encode(s);
19
+ }
20
+
21
+ function toUtf8(bytes) {
22
+ return decoder.decode(bytes);
23
+ }
24
+
25
+ describe('AES Bridge Tests', async () => {
26
+
27
+ const raw = await readFile(new URL('./test_data.json', import.meta.url));
28
+ const json = JSON.parse(raw);
29
+
30
+ const cases = [];
31
+
32
+ // Group 1: simple test cases from .testdata.plaintext[]
33
+ for (const [idx, str] of (json.testdata?.plaintext || []).entries()) {
34
+ const value = encoder.encode(str);
35
+
36
+ cases.push({
37
+ id: `plaintext_${idx}`,
38
+ input: value,
39
+ pass: value,
40
+ });
41
+ }
42
+
43
+ // Group 2: hex string testdata
44
+ for (const [idx, hex] of (json.testdata?.hex || []).entries()) {
45
+ const value = fromHex(hex);
46
+
47
+ cases.push({
48
+ id: `hex_${idx}`,
49
+ input: value,
50
+ pass: value,
51
+ });
52
+ }
53
+
54
+ // Group 3: exact expected results from test_data["tests"]
55
+ for (const [idx, test] of (json.tests || []).entries()) {
56
+ const id = test.id || `case_${idx}`;
57
+ const pass = test.passphrase;
58
+
59
+ let input = test.plaintext
60
+ ? encoder.encode(test.plaintext)
61
+ : fromHex(test.hex);
62
+
63
+ if (test['encrypted-cbc']) {
64
+ cases.push({
65
+ id: `cbc_${id}`,
66
+ input,
67
+ pass,
68
+ expected: test['encrypted-cbc'],
69
+ decrypt: decryptCbc
70
+ });
71
+ }
72
+
73
+ if (test['encrypted-gcm']) {
74
+ cases.push({
75
+ id: `gcm_${id}`,
76
+ input,
77
+ pass,
78
+ expected: test['encrypted-gcm'],
79
+ decrypt: decryptGcm
80
+ });
81
+ }
82
+
83
+ if (test['encrypted-legacy']) {
84
+ cases.push({
85
+ id: `legacy_${id}`,
86
+ input,
87
+ pass,
88
+ expected: test['encrypted-legacy'],
89
+ decrypt: decryptLegacy
90
+ });
91
+ }
92
+ }
93
+
94
+ // Define test blocks
95
+ for (const test of cases) {
96
+
97
+ if (test.expected && test.decrypt) {
98
+ const name = `decrypt [${test.id}]`;
99
+ it(name, async () => {
100
+ const result = await test.decrypt(test.expected, test.pass);
101
+ expect(toUtf8(result)).toBe(toUtf8(test.input));
102
+ });
103
+ } else {
104
+ const name = `encrypt/decrypt [${test.id}]`;
105
+ it(`${name} CBC`, async () => {
106
+ const enc = await encryptCbc(test.input, test.pass);
107
+ const dec = await decryptCbc(enc, test.pass);
108
+ expect(toUtf8(dec)).toBe(toUtf8(test.input));
109
+ });
110
+
111
+ it(`${name} GCM`, async () => {
112
+ const enc = await encryptGcm(test.input, test.pass);
113
+ const dec = await decryptGcm(enc, test.pass);
114
+ expect(toUtf8(dec)).toBe(toUtf8(test.input));
115
+ });
116
+
117
+ it(`${name} Legacy`, async () => {
118
+ const enc = await encryptLegacy(test.input, test.pass);
119
+ const dec = await decryptLegacy(enc, test.pass);
120
+ expect(toUtf8(dec)).toBe(toUtf8(test.input));
121
+ });
122
+ }
123
+ }
124
+ });
@@ -0,0 +1,38 @@
1
+ {
2
+ "testdata": {
3
+ "plaintext": [
4
+ "",
5
+ "A",
6
+ "000102030405060708090a0b0c0d0e0f",
7
+ "ABCDEF0123456789",
8
+ "The quick brown fox jumps over the lazy dog.",
9
+ "Съешь ещё этих мягких французских булок, да выпей чаю.",
10
+ "中文测试 — 測試中文字符",
11
+ "𝔗𝔥𝔦𝔰 𝔦𝔰 𝔞 𝔱𝔢𝔵𝔱 𝔴𝔦𝔱𝔥 𝔣𝔯𝔞𝔨𝔱𝔲𝔯 𝔩𝔢𝔱𝔱𝔢𝔯𝔰.",
12
+ "Emoji test: 😉😌😍😘🔥🔥💥"
13
+ ],
14
+ "hex": [
15
+ "5964d4f5bc127ed016cc471ba8250f05f707da12f8e5c85e733a2abe31a705ffd7a72fe5d4c40611aca98396dc123093c37340cd17f926b73be6753e9636e0ea"
16
+ ]
17
+ },
18
+ "tests": [
19
+ {
20
+ "id": "plaintext_utf8",
21
+ "plaintext": "The quick brown fox выпей чаю 中文测试 𝔣𝔯𝔞𝔨𝔱𝔲𝔯 😉😌😍😘",
22
+ "passphrase": "áuhêüÖÕ0H_{³¹ßLè\\8ÉñïäzH`&[BÔͨåg_!±Ýp+ãÏÜì 😍",
23
+ "encrypted-cbc": "JELXLWOrwjopsFKiEV11L68Ta5Mz9adzNNewgyzITPeZ3CQ5a/00FSDTPJ+tbGH9DagB04LNoIriC2o/etpkE1DkFwJZk0jXN12bFGwWJZPZy15T9JxDL/BOHiiycICoTGAToH6XyOuc5vXHsZwFSn/1QL5+xaR2GPbL/wWKnmckDj+W5hhvh2R4Z7V9dQmVc9PSCCYnbn8vymiFLc7deAxcpjg45+6hONn80GJ8fNg=",
24
+ "encrypted-gcm": "W4et1smZeF2JGtYjzkdHbAvaqXb+K1nzzcfY2bTTpgsbPw4TmBFc0I5iwgWoU0hGC9ZuB/UcS1huxOHZe7WqR4Ol/FyNhjDB9bTobZCigAC4Q7GVpjiNCZYwouNfL7R/Nn4GyPjOGLY+E/9QisBv0tyfP4rLzFHzZzRmxb0skuT5IqP2lox/sBI4+YI="
25
+ }, {
26
+ "id": "binary_data",
27
+ "hex": "5964d4f5bc127ed016cc471ba8250f05f707da12f8e5c85e733a2abe31a705ffd7a72fe5d4c40611aca98396dc123093c37340cd17f926b73be6753e9636e0ea",
28
+ "passphrase": "áuhêüÖÕ0H_{³¹ßLè\\8ÉñïäzH`&[BÔͨåg_!±Ýp+ãÏÜì 😍",
29
+ "encrypted-cbc": "MWafJI+DZTNbNRdHmrEZyO42WHVm571+Ub23+hlWp24Wc4iiPJTqJnEt1kILv3eqLJOPcpVstVV1E9Wbxk8y7rcMScQF4FNGTAm+xJ3VrREzr3KAanKjbMTOovx5wuk2flPL+rTNSpYv1bJjQ9HmG8CMHFUk5yi+XzJkAc4RVU7qAbX4fqWsbYxt4Y26idjA",
30
+ "encrypted-gcm": "N8w4J2sO2df2tv1QDSJuQE+ovcfz5YMfYsiFeLghZkPJoXQrQbzDQiG5X7Pyz8RP2kuAx4GBAyZ8wt+FUbk1xl26rQJjDL5lSJXoC+DaJEeiyvmFvTXDOLxymmhvsvWmlLmuL7WTM0tgj6ky"
31
+ }, {
32
+ "id": "legacy_utf8",
33
+ "passphrase": "P@ssw0rd 😄",
34
+ "plaintext": "Привет, мир! こんにちは!Hello, world! 😊 123",
35
+ "encrypted-legacy": "U2FsdGVkX19Fw9R5L9g+UqtDwcYdsvvuf7P+UMgqS5YXi4+gDobFZ8Jl6kFwJJf8EVABC/DK2mJnEVa2MD7oeYEHFHM2F/RKHRVxlFH6cFE="
36
+ }
37
+ ]
38
+ }