ddan-js 2.6.37 → 2.6.39
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/bin/ddan-js.esm.js +1 -1
- package/bin/ddan-js.js +1 -1
- package/bin/lib/modules/browser/ecdh.js +71 -29
- package/bin/lib/modules/convert/index.js +15 -0
- package/bin/lib/modules/node/ecdh-web.js +11 -0
- package/bin/lib/modules/node/ecdh.js +66 -21
- package/bin/lib/modules/node/index.js +2 -2
- package/bin/lib/modules/qs/index.js +2 -1
- package/bin/types/index.d.ts +7 -4
- package/bin/types/modules/browser/ecdh.d.ts +15 -11
- package/bin/types/modules/convert/index.d.ts +2 -1
- package/bin/types/modules/node/ecdh-web.d.ts +4 -0
- package/bin/types/modules/node/ecdh.d.ts +7 -8
- package/bin/types/modules/node/index.d.ts +2 -2
- package/package.json +1 -1
- package/bin/lib/modules/node/ecdh-spki.js +0 -76
- package/bin/types/modules/node/ecdh-spki.d.ts +0 -19
|
@@ -3,72 +3,114 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const convert_1 = require("../convert");
|
|
4
4
|
class Ecdh {
|
|
5
5
|
publicKey = '';
|
|
6
|
+
privateKey = '';
|
|
6
7
|
iv = '';
|
|
7
|
-
|
|
8
|
+
__privateCryptoKey;
|
|
8
9
|
__sharedSecret;
|
|
9
10
|
__curve;
|
|
10
|
-
|
|
11
|
+
__keyFormat;
|
|
12
|
+
__subtle;
|
|
13
|
+
constructor(curve = 'P-256', keyFormat = 'raw') {
|
|
11
14
|
this.__curve = curve;
|
|
15
|
+
this.__keyFormat = keyFormat || 'raw';
|
|
16
|
+
if (typeof window !== 'undefined')
|
|
17
|
+
this.__subtle = window.crypto.subtle;
|
|
18
|
+
else
|
|
19
|
+
this.__subtle = {};
|
|
12
20
|
}
|
|
13
|
-
async generateKeys(
|
|
14
|
-
const keyPair = await
|
|
21
|
+
async generateKeys() {
|
|
22
|
+
const keyPair = await this.__subtle.generateKey({
|
|
15
23
|
name: 'ECDH',
|
|
16
24
|
namedCurve: this.__curve, // 使用 P-256 椭圆曲线
|
|
17
25
|
}, true, // 可以导出
|
|
18
26
|
['deriveKey', 'deriveBits']);
|
|
19
|
-
this.
|
|
20
|
-
this.publicKey = await this.
|
|
21
|
-
this.
|
|
27
|
+
this.__privateCryptoKey = keyPair.privateKey;
|
|
28
|
+
this.publicKey = await this.exportKey(keyPair.publicKey);
|
|
29
|
+
this.privateKey = await this.exportKey(keyPair.privateKey, 'pkcs8');
|
|
22
30
|
return this;
|
|
23
31
|
}
|
|
24
|
-
async
|
|
25
|
-
const exportKey = await
|
|
26
|
-
cryptoKey);
|
|
32
|
+
async exportKey(cryptoKey, keyFormat = 'raw') {
|
|
33
|
+
const exportKey = await this.__subtle.exportKey(keyFormat || this.__keyFormat, cryptoKey);
|
|
27
34
|
return convert_1.default.ab2str(exportKey, true);
|
|
28
35
|
}
|
|
29
|
-
async
|
|
36
|
+
async importKey(keyBase64, keyFormat = 'raw', usages = []) {
|
|
30
37
|
const bytes = convert_1.default.base64ToBytes(keyBase64);
|
|
31
|
-
const publicKey = await
|
|
38
|
+
const publicKey = await this.__subtle.importKey(keyFormat || this.__keyFormat || 'raw', bytes, {
|
|
32
39
|
name: 'ECDH',
|
|
33
40
|
namedCurve: this.__curve,
|
|
34
|
-
}, true,
|
|
41
|
+
}, true, usages);
|
|
35
42
|
return publicKey;
|
|
36
43
|
}
|
|
37
|
-
async
|
|
38
|
-
if (!
|
|
39
|
-
return
|
|
40
|
-
const
|
|
41
|
-
|
|
44
|
+
async setPrivateKey(privateBase64) {
|
|
45
|
+
if (!privateBase64)
|
|
46
|
+
return false;
|
|
47
|
+
const cryptoKey = await this.importKey(privateBase64, 'pkcs8', ['deriveKey', 'deriveBits']);
|
|
48
|
+
this.privateKey = await this.exportKey(cryptoKey, 'pkcs8');
|
|
49
|
+
this.__privateCryptoKey = cryptoKey;
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
async deriveSharedSecret(publicKeyBase64, iv) {
|
|
53
|
+
if (!this.__privateCryptoKey)
|
|
54
|
+
return false;
|
|
55
|
+
this.iv = iv;
|
|
56
|
+
const cryptoKey = await this.importKey(publicKeyBase64);
|
|
57
|
+
const sharedSecret = await this.__subtle.deriveKey({
|
|
42
58
|
name: 'ECDH',
|
|
43
|
-
public:
|
|
44
|
-
}, this.
|
|
59
|
+
public: cryptoKey, // 对方的公钥
|
|
60
|
+
}, this.__privateCryptoKey, // 自己的私钥
|
|
45
61
|
{ name: 'AES-GCM', length: 256 }, // 派生出的共享密钥用于 AES 加密
|
|
46
62
|
true, // 可以导出
|
|
47
63
|
['encrypt', 'decrypt'] // 用于加密和解密
|
|
48
64
|
);
|
|
49
65
|
this.__sharedSecret = sharedSecret;
|
|
50
|
-
return
|
|
66
|
+
return true;
|
|
51
67
|
}
|
|
52
68
|
async encode(data) {
|
|
53
69
|
if (!this.__sharedSecret || !this.iv)
|
|
54
|
-
return
|
|
70
|
+
return '';
|
|
55
71
|
const bytes = convert_1.default.textEncode(data);
|
|
56
|
-
const encrypted = await
|
|
72
|
+
const encrypted = await this.__subtle.encrypt({
|
|
57
73
|
name: 'AES-GCM',
|
|
58
74
|
iv: convert_1.default.base64ToBytes(this.iv),
|
|
59
75
|
}, this.__sharedSecret, bytes);
|
|
60
|
-
|
|
61
|
-
|
|
76
|
+
return convert_1.default.ab2str(encrypted, true);
|
|
77
|
+
}
|
|
78
|
+
async encodeiv(data) {
|
|
79
|
+
if (!this.__sharedSecret || !this.iv)
|
|
80
|
+
return '';
|
|
81
|
+
const dataBytes = convert_1.default.textEncode(data);
|
|
82
|
+
const ivBytes = convert_1.default.base64ToBytes(this.iv);
|
|
83
|
+
const encrypted = await this.__subtle.encrypt({
|
|
84
|
+
name: 'AES-GCM',
|
|
85
|
+
iv: ivBytes,
|
|
86
|
+
}, this.__sharedSecret, dataBytes);
|
|
87
|
+
const bytes = convert_1.default.concatBytes(new Uint8Array(encrypted), ivBytes);
|
|
88
|
+
return convert_1.default.bytesToBase64(bytes);
|
|
62
89
|
}
|
|
63
90
|
async decode(encrypted, iv) {
|
|
64
|
-
if (!this.__sharedSecret
|
|
91
|
+
if (!this.__sharedSecret)
|
|
65
92
|
return '';
|
|
66
|
-
const
|
|
67
|
-
const
|
|
93
|
+
const _iv = iv || this.iv;
|
|
94
|
+
const bytes = convert_1.default.base64ToBytes(encrypted);
|
|
95
|
+
const decrypted = await this.__subtle.decrypt({
|
|
68
96
|
name: 'AES-GCM',
|
|
69
|
-
iv: convert_1.default.base64ToBytes(
|
|
97
|
+
iv: convert_1.default.base64ToBytes(_iv),
|
|
70
98
|
}, this.__sharedSecret, bytes);
|
|
71
99
|
return convert_1.default.textDecode(decrypted);
|
|
72
100
|
}
|
|
101
|
+
async decodeiv(encrypted) {
|
|
102
|
+
if (!this.__sharedSecret)
|
|
103
|
+
return '';
|
|
104
|
+
const bytes = convert_1.default.base64ToBytes(encrypted);
|
|
105
|
+
if (bytes.length < 12)
|
|
106
|
+
return '';
|
|
107
|
+
const ivBytes = bytes.slice(bytes.length - 12);
|
|
108
|
+
const dataBytes = bytes.slice(0, bytes.length - 12);
|
|
109
|
+
const decrypted = await this.__subtle.decrypt({
|
|
110
|
+
name: 'AES-GCM',
|
|
111
|
+
iv: ivBytes,
|
|
112
|
+
}, this.__sharedSecret, dataBytes);
|
|
113
|
+
return convert_1.default.textDecode(decrypted);
|
|
114
|
+
}
|
|
73
115
|
}
|
|
74
116
|
exports.default = Ecdh;
|
|
@@ -107,6 +107,20 @@ const toDataUrl = (textOrBuf, contentType = 'text/plain') => {
|
|
|
107
107
|
}
|
|
108
108
|
return '';
|
|
109
109
|
};
|
|
110
|
+
const concatBytes = (...args) => {
|
|
111
|
+
// 计算所有 Uint8Array 的总长度
|
|
112
|
+
const totalLength = args.reduce((sum, arr) => sum + arr.length, 0);
|
|
113
|
+
// 创建一个新的 Uint8Array
|
|
114
|
+
const combined = new Uint8Array(totalLength);
|
|
115
|
+
// 当前写入的位置
|
|
116
|
+
let offset = 0;
|
|
117
|
+
// 将每个 Uint8Array 复制到新的数组中
|
|
118
|
+
for (const arr of args) {
|
|
119
|
+
combined.set(arr, offset);
|
|
120
|
+
offset += arr.length;
|
|
121
|
+
}
|
|
122
|
+
return combined;
|
|
123
|
+
};
|
|
110
124
|
exports.default = {
|
|
111
125
|
...utf8_1.default,
|
|
112
126
|
...base64_1.default,
|
|
@@ -122,4 +136,5 @@ exports.default = {
|
|
|
122
136
|
textEncode,
|
|
123
137
|
textDecode,
|
|
124
138
|
toDataUrl,
|
|
139
|
+
concatBytes,
|
|
125
140
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_crypto_1 = require("node:crypto");
|
|
4
|
+
const ecdh_1 = require("../browser/ecdh");
|
|
5
|
+
class EcdhWeb extends ecdh_1.default {
|
|
6
|
+
constructor(curve = "P-256", keyFormat = "raw") {
|
|
7
|
+
super(curve, keyFormat);
|
|
8
|
+
this.__subtle = node_crypto_1.default.webcrypto.subtle;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.default = EcdhWeb;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const node_crypto_1 = require("node:crypto");
|
|
4
3
|
const convert_1 = require("../convert");
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
5
|
class Ecdh {
|
|
6
6
|
publicKey = '';
|
|
7
7
|
privateKey = '';
|
|
8
8
|
sharedSecret;
|
|
9
|
-
iv;
|
|
9
|
+
iv = '';
|
|
10
10
|
_curve;
|
|
11
11
|
_algorithm;
|
|
12
12
|
_ecdh;
|
|
@@ -17,7 +17,7 @@ class Ecdh {
|
|
|
17
17
|
}
|
|
18
18
|
generateKey() {
|
|
19
19
|
// 使用 P-256 曲线
|
|
20
|
-
const ecdh = node_crypto_1.default.createECDH(
|
|
20
|
+
const ecdh = node_crypto_1.default.createECDH('prime256v1');
|
|
21
21
|
ecdh.generateKeys();
|
|
22
22
|
// 公钥以 base64 格式导出
|
|
23
23
|
this.publicKey = ecdh.getPublicKey('base64');
|
|
@@ -26,32 +26,77 @@ class Ecdh {
|
|
|
26
26
|
this._ecdh = ecdh;
|
|
27
27
|
}
|
|
28
28
|
deriveSharedSecret(otherPublicKey, iv) {
|
|
29
|
-
if (!otherPublicKey)
|
|
30
|
-
return
|
|
29
|
+
if (!otherPublicKey || !iv)
|
|
30
|
+
return false;
|
|
31
31
|
this.sharedSecret = this._ecdh.computeSecret(otherPublicKey, 'base64').toString('base64');
|
|
32
32
|
this.iv = iv;
|
|
33
|
-
return
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
setPrivateKey(privateBase64) {
|
|
36
|
+
if (!privateBase64)
|
|
37
|
+
return false;
|
|
38
|
+
if (!this._ecdh)
|
|
39
|
+
return false;
|
|
40
|
+
this._ecdh.setPrivateKey(privateBase64, 'base64');
|
|
41
|
+
this.publicKey = this._ecdh.getPublicKey('base64');
|
|
42
|
+
return true;
|
|
34
43
|
}
|
|
35
44
|
encode(data) {
|
|
36
45
|
if (!this.sharedSecret || !this.iv)
|
|
37
|
-
return
|
|
46
|
+
return '';
|
|
38
47
|
const cipher = node_crypto_1.default.createCipheriv('aes-256-gcm', convert_1.default.base64ToBytes(this.sharedSecret), convert_1.default.base64ToBytes(this.iv));
|
|
39
|
-
const encrypted =
|
|
48
|
+
const encrypted = Buffer.concat([
|
|
49
|
+
new Uint8Array(cipher.update(data, 'utf8')),
|
|
50
|
+
new Uint8Array(cipher.final()),
|
|
51
|
+
]);
|
|
52
|
+
const tagBuf = cipher.getAuthTag();
|
|
53
|
+
const combined = Buffer.concat([new Uint8Array(encrypted), new Uint8Array(tagBuf)]);
|
|
54
|
+
return combined.toString('base64');
|
|
55
|
+
}
|
|
56
|
+
encodeiv(data) {
|
|
57
|
+
if (!this.sharedSecret || !this.iv)
|
|
58
|
+
return '';
|
|
59
|
+
const ivBytes = convert_1.default.base64ToBytes(this.iv);
|
|
60
|
+
const cipher = node_crypto_1.default.createCipheriv('aes-256-gcm', convert_1.default.base64ToBytes(this.sharedSecret), ivBytes);
|
|
61
|
+
const encrypted = Buffer.concat([
|
|
62
|
+
new Uint8Array(cipher.update(data, 'utf8')),
|
|
63
|
+
new Uint8Array(cipher.final()),
|
|
64
|
+
]);
|
|
40
65
|
const authTagBuf = cipher.getAuthTag();
|
|
41
|
-
const
|
|
42
|
-
return
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
66
|
+
const combined = Buffer.concat([new Uint8Array(encrypted), new Uint8Array(authTagBuf), ivBytes]);
|
|
67
|
+
return combined.toString('base64');
|
|
68
|
+
}
|
|
69
|
+
decode(encrypted, iv) {
|
|
70
|
+
if (!encrypted || !this.sharedSecret)
|
|
71
|
+
return '';
|
|
72
|
+
const _iv = iv || this.iv;
|
|
73
|
+
const decipher = node_crypto_1.default.createDecipheriv('aes-256-gcm', convert_1.default.base64ToBytes(this.sharedSecret), convert_1.default.base64ToBytes(_iv));
|
|
74
|
+
const allBytes = convert_1.default.base64ToBytes(encrypted);
|
|
75
|
+
const authTagBytes = allBytes.slice(allBytes.length - 16);
|
|
76
|
+
decipher.setAuthTag(authTagBytes);
|
|
77
|
+
const encryptedBytes = allBytes.slice(0, allBytes.length - 16);
|
|
78
|
+
const decrypted = Buffer.concat([
|
|
79
|
+
new Uint8Array(decipher.update(encryptedBytes)),
|
|
80
|
+
new Uint8Array(decipher.final()),
|
|
81
|
+
]);
|
|
82
|
+
return decrypted.toString('utf-8');
|
|
83
|
+
}
|
|
84
|
+
decodeiv(encrypted) {
|
|
85
|
+
if (!encrypted || !this.sharedSecret)
|
|
86
|
+
return '';
|
|
87
|
+
const allBytes = convert_1.default.base64ToBytes(encrypted);
|
|
88
|
+
if (allBytes.length < 28)
|
|
50
89
|
return '';
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
90
|
+
const ivBytes = allBytes.slice(allBytes.length - 12);
|
|
91
|
+
const tagBytes = allBytes.slice(allBytes.length - 28, allBytes.length - 12);
|
|
92
|
+
const decipher = node_crypto_1.default.createDecipheriv('aes-256-gcm', convert_1.default.base64ToBytes(this.sharedSecret), ivBytes);
|
|
93
|
+
decipher.setAuthTag(tagBytes);
|
|
94
|
+
const encryptedBytes = allBytes.slice(0, allBytes.length - 28);
|
|
95
|
+
const decrypted = Buffer.concat([
|
|
96
|
+
new Uint8Array(decipher.update(encryptedBytes)),
|
|
97
|
+
new Uint8Array(decipher.final()),
|
|
98
|
+
]);
|
|
99
|
+
return decrypted.toString('utf-8');
|
|
55
100
|
}
|
|
56
101
|
}
|
|
57
102
|
exports.default = Ecdh;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const brotli_1 = require("./brotli");
|
|
4
4
|
const ecdh_1 = require("./ecdh");
|
|
5
|
-
const ecdh_spki_1 = require("./ecdh-spki");
|
|
6
5
|
const socks5_1 = require("./socks5");
|
|
7
6
|
const child_1 = require("./child");
|
|
8
7
|
const proxy_1 = require("./proxy");
|
|
9
|
-
|
|
8
|
+
const ecdh_web_1 = require("./ecdh-web");
|
|
9
|
+
exports.default = { ...brotli_1.default, ...child_1.default, ...proxy_1.default, Ecdh: ecdh_1.default, EcdhWeb: ecdh_web_1.default, Socks5: socks5_1.Socks5 };
|
|
@@ -88,7 +88,8 @@ const shExpMatch = (text, pattern) => {
|
|
|
88
88
|
.replace(/\./g, '\\.') // 转义 .
|
|
89
89
|
.replace(/\*/g, '.*') // 将 * 转换为 .*
|
|
90
90
|
.replace(/\?/g, '.'); // 将 ? 转换为 .
|
|
91
|
-
const regex = new RegExp(regexPattern)
|
|
91
|
+
// const regex = new RegExp(regexPattern)
|
|
92
|
+
const regex = new RegExp('^' + regexPattern + '$');
|
|
92
93
|
return regex.test(text);
|
|
93
94
|
};
|
|
94
95
|
exports.default = {
|
package/bin/types/index.d.ts
CHANGED
|
@@ -72,7 +72,7 @@ declare const dUtil: {
|
|
|
72
72
|
keyChars: string;
|
|
73
73
|
str2Hex: (str: string) => string;
|
|
74
74
|
hex2Str: (hexstr: string) => string;
|
|
75
|
-
str2ab: (content?: string, base64?: boolean) =>
|
|
75
|
+
str2ab: (content?: string, base64?: boolean) => ArrayBuffer;
|
|
76
76
|
ab2str: (data: ArrayBuffer, base64?: boolean) => string;
|
|
77
77
|
bytesToStr: (bytes: Uint8Array) => string;
|
|
78
78
|
strToBytes: (str?: string) => Uint8Array;
|
|
@@ -82,6 +82,7 @@ declare const dUtil: {
|
|
|
82
82
|
textEncode: (text: string) => Uint8Array;
|
|
83
83
|
textDecode: (buf: ArrayBuffer) => string;
|
|
84
84
|
toDataUrl: (textOrBuf: string | ArrayBuffer, contentType?: string) => string;
|
|
85
|
+
concatBytes: (...args: Uint8Array[]) => Uint8Array;
|
|
85
86
|
toBase64: (input?: string) => string;
|
|
86
87
|
fromBase64: (input?: string) => string;
|
|
87
88
|
bytesToBase64: (bytes: Uint8Array) => string;
|
|
@@ -294,7 +295,7 @@ declare const dHook: {
|
|
|
294
295
|
keyChars: string;
|
|
295
296
|
str2Hex: (str: string) => string;
|
|
296
297
|
hex2Str: (hexstr: string) => string;
|
|
297
|
-
str2ab: (content?: string, base64?: boolean) =>
|
|
298
|
+
str2ab: (content?: string, base64?: boolean) => ArrayBuffer;
|
|
298
299
|
ab2str: (data: ArrayBuffer, base64?: boolean) => string;
|
|
299
300
|
bytesToStr: (bytes: Uint8Array) => string;
|
|
300
301
|
strToBytes: (str?: string) => Uint8Array;
|
|
@@ -304,6 +305,7 @@ declare const dHook: {
|
|
|
304
305
|
textEncode: (text: string) => Uint8Array;
|
|
305
306
|
textDecode: (buf: ArrayBuffer) => string;
|
|
306
307
|
toDataUrl: (textOrBuf: string | ArrayBuffer, contentType?: string) => string;
|
|
308
|
+
concatBytes: (...args: Uint8Array[]) => Uint8Array;
|
|
307
309
|
toBase64: (input?: string) => string;
|
|
308
310
|
fromBase64: (input?: string) => string;
|
|
309
311
|
bytesToBase64: (bytes: Uint8Array) => string;
|
|
@@ -559,7 +561,7 @@ declare const dWeb: {
|
|
|
559
561
|
};
|
|
560
562
|
declare const dNode: {
|
|
561
563
|
Ecdh: typeof import("./modules/node/ecdh").default;
|
|
562
|
-
|
|
564
|
+
EcdhWeb: typeof import("./modules/node/ecdh-web").default;
|
|
563
565
|
Socks5: typeof import("./modules/node/socks5").Socks5;
|
|
564
566
|
getSystemProxy: () => Promise<{
|
|
565
567
|
ipaddress: string;
|
|
@@ -894,7 +896,7 @@ declare const _default: {
|
|
|
894
896
|
convert: {
|
|
895
897
|
str2Hex: (str: string) => string;
|
|
896
898
|
hex2Str: (hexstr: string) => string;
|
|
897
|
-
str2ab: (content?: string, base64?: boolean) =>
|
|
899
|
+
str2ab: (content?: string, base64?: boolean) => ArrayBuffer;
|
|
898
900
|
ab2str: (data: ArrayBuffer, base64?: boolean) => string;
|
|
899
901
|
bytesToStr: (bytes: Uint8Array) => string;
|
|
900
902
|
strToBytes: (str?: string) => Uint8Array;
|
|
@@ -904,6 +906,7 @@ declare const _default: {
|
|
|
904
906
|
textEncode: (text: string) => Uint8Array;
|
|
905
907
|
textDecode: (buf: ArrayBuffer) => string;
|
|
906
908
|
toDataUrl: (textOrBuf: string | ArrayBuffer, contentType?: string) => string;
|
|
909
|
+
concatBytes: (...args: Uint8Array[]) => Uint8Array;
|
|
907
910
|
toBase64: (input?: string) => string;
|
|
908
911
|
fromBase64: (input?: string) => string;
|
|
909
912
|
bytesToBase64: (bytes: Uint8Array) => string;
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
export type TKeyFormat = 'raw' | 'pkcs8' | 'spki';
|
|
1
2
|
export default class Ecdh {
|
|
2
3
|
publicKey: string;
|
|
4
|
+
privateKey: string;
|
|
3
5
|
iv: string;
|
|
4
|
-
|
|
6
|
+
__privateCryptoKey: CryptoKey | undefined;
|
|
5
7
|
__sharedSecret: CryptoKey | undefined;
|
|
6
8
|
__curve: string;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
__keyFormat: TKeyFormat;
|
|
10
|
+
__subtle: SubtleCrypto;
|
|
11
|
+
constructor(curve?: string, keyFormat?: TKeyFormat);
|
|
12
|
+
generateKeys(): Promise<this>;
|
|
13
|
+
exportKey(cryptoKey: CryptoKey, keyFormat?: TKeyFormat): Promise<string>;
|
|
14
|
+
importKey(keyBase64: string, keyFormat?: TKeyFormat, usages?: KeyUsage[]): Promise<CryptoKey>;
|
|
15
|
+
setPrivateKey(privateBase64: string): Promise<boolean>;
|
|
16
|
+
deriveSharedSecret(publicKeyBase64: string, iv: string): Promise<boolean>;
|
|
17
|
+
encode(data: string): Promise<string>;
|
|
18
|
+
encodeiv(data: string): Promise<string>;
|
|
19
|
+
decode(encrypted: string, iv?: string): Promise<string>;
|
|
20
|
+
decodeiv(encrypted: string): Promise<string>;
|
|
17
21
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
2
|
str2Hex: (str: string) => string;
|
|
3
3
|
hex2Str: (hexstr: string) => string;
|
|
4
|
-
str2ab: (content?: string, base64?: boolean) =>
|
|
4
|
+
str2ab: (content?: string, base64?: boolean) => ArrayBuffer;
|
|
5
5
|
ab2str: (data: ArrayBuffer, base64?: boolean) => string;
|
|
6
6
|
bytesToStr: (bytes: Uint8Array) => string;
|
|
7
7
|
strToBytes: (str?: string) => Uint8Array;
|
|
@@ -11,6 +11,7 @@ declare const _default: {
|
|
|
11
11
|
textEncode: (text: string) => Uint8Array;
|
|
12
12
|
textDecode: (buf: ArrayBuffer) => string;
|
|
13
13
|
toDataUrl: (textOrBuf: string | ArrayBuffer, contentType?: string) => string;
|
|
14
|
+
concatBytes: (...args: Uint8Array[]) => Uint8Array;
|
|
14
15
|
toBase64: (input?: string) => string;
|
|
15
16
|
fromBase64: (input?: string) => string;
|
|
16
17
|
bytesToBase64: (bytes: Uint8Array) => string;
|
|
@@ -4,17 +4,16 @@ export default class Ecdh {
|
|
|
4
4
|
publicKey: string;
|
|
5
5
|
privateKey: string;
|
|
6
6
|
sharedSecret: string | undefined;
|
|
7
|
-
iv: string
|
|
7
|
+
iv: string;
|
|
8
8
|
_curve: string;
|
|
9
9
|
_algorithm: string;
|
|
10
10
|
_ecdh: crypto.ECDH | undefined;
|
|
11
11
|
constructor(curve?: string, algorithm?: string);
|
|
12
12
|
generateKey(): void;
|
|
13
|
-
deriveSharedSecret(otherPublicKey: string, iv: string):
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
decode(encrypted: string, authTag: string, iv: string): string;
|
|
13
|
+
deriveSharedSecret(otherPublicKey: string, iv: string): boolean;
|
|
14
|
+
setPrivateKey(privateBase64: string): boolean;
|
|
15
|
+
encode(data: string): string;
|
|
16
|
+
encodeiv(data: string): string;
|
|
17
|
+
decode(encrypted: string, iv?: string): string;
|
|
18
|
+
decodeiv(encrypted: string): string;
|
|
20
19
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import Ecdh from './ecdh';
|
|
2
|
-
import EcdhSpki from './ecdh-spki';
|
|
3
2
|
import { Socks5 } from './socks5';
|
|
3
|
+
import EcdhWeb from './ecdh-web';
|
|
4
4
|
declare const _default: {
|
|
5
5
|
Ecdh: typeof Ecdh;
|
|
6
|
-
|
|
6
|
+
EcdhWeb: typeof EcdhWeb;
|
|
7
7
|
Socks5: typeof Socks5;
|
|
8
8
|
getSystemProxy: () => Promise<{
|
|
9
9
|
ipaddress: string;
|
package/package.json
CHANGED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const convert_1 = require("../convert");
|
|
4
|
-
const node_crypto_1 = require("node:crypto");
|
|
5
|
-
const subtle = node_crypto_1.default?.webcrypto?.subtle;
|
|
6
|
-
class EcdhSpki {
|
|
7
|
-
publicKey = '';
|
|
8
|
-
iv = '';
|
|
9
|
-
__keyPair;
|
|
10
|
-
__sharedSecret;
|
|
11
|
-
__curve;
|
|
12
|
-
constructor(curve = 'P-256') {
|
|
13
|
-
this.__curve = curve;
|
|
14
|
-
}
|
|
15
|
-
async generateKeys(iv) {
|
|
16
|
-
const keyPair = await subtle.generateKey({
|
|
17
|
-
name: 'ECDH',
|
|
18
|
-
namedCurve: this.__curve, // 使用 P-256 椭圆曲线
|
|
19
|
-
}, true, // 可以导出
|
|
20
|
-
['deriveKey', 'deriveBits']);
|
|
21
|
-
this.__keyPair = keyPair;
|
|
22
|
-
this.publicKey = await this.exportSpkiKey(keyPair.publicKey);
|
|
23
|
-
this.iv = iv;
|
|
24
|
-
return this;
|
|
25
|
-
}
|
|
26
|
-
async exportSpkiKey(cryptoKey) {
|
|
27
|
-
const exportKey = await subtle.exportKey('spki', // 公钥的格式(适合交换的标准格式)
|
|
28
|
-
cryptoKey);
|
|
29
|
-
return convert_1.default.ab2str(exportKey, true);
|
|
30
|
-
}
|
|
31
|
-
async importSpkiKey(keyBase64) {
|
|
32
|
-
const bytes = convert_1.default.base64ToBytes(keyBase64);
|
|
33
|
-
const publicKey = await subtle.importKey('spki', bytes, {
|
|
34
|
-
name: 'ECDH',
|
|
35
|
-
namedCurve: this.__curve,
|
|
36
|
-
}, true, []);
|
|
37
|
-
return publicKey;
|
|
38
|
-
}
|
|
39
|
-
async deriveSharedSecret(publicKeyBase64) {
|
|
40
|
-
if (!this.__keyPair)
|
|
41
|
-
return this;
|
|
42
|
-
const publicKey = await this.importSpkiKey(publicKeyBase64);
|
|
43
|
-
const sharedSecret = await subtle.deriveKey({
|
|
44
|
-
name: 'ECDH',
|
|
45
|
-
public: publicKey, // 对方的公钥
|
|
46
|
-
}, this.__keyPair.privateKey, // 自己的私钥
|
|
47
|
-
{ name: 'AES-GCM', length: 256 }, // 派生出的共享密钥用于 AES 加密
|
|
48
|
-
true, // 可以导出
|
|
49
|
-
['encrypt', 'decrypt'] // 用于加密和解密
|
|
50
|
-
);
|
|
51
|
-
this.__sharedSecret = sharedSecret;
|
|
52
|
-
return this;
|
|
53
|
-
}
|
|
54
|
-
async encode(data) {
|
|
55
|
-
if (!this.__sharedSecret || !this.iv)
|
|
56
|
-
return { text: '', iv: '' };
|
|
57
|
-
const bytes = convert_1.default.textEncode(data);
|
|
58
|
-
const encrypted = await subtle.encrypt({
|
|
59
|
-
name: 'AES-GCM',
|
|
60
|
-
iv: convert_1.default.base64ToBytes(this.iv),
|
|
61
|
-
}, this.__sharedSecret, bytes);
|
|
62
|
-
const b64 = convert_1.default.ab2str(encrypted, true);
|
|
63
|
-
return { iv: this.iv, text: b64 };
|
|
64
|
-
}
|
|
65
|
-
async decode(encrypted, iv) {
|
|
66
|
-
if (!this.__sharedSecret || !iv)
|
|
67
|
-
return '';
|
|
68
|
-
const bytes = convert_1.default.str2ab(encrypted, true);
|
|
69
|
-
const decrypted = await subtle.decrypt({
|
|
70
|
-
name: 'AES-GCM',
|
|
71
|
-
iv: convert_1.default.base64ToBytes(iv),
|
|
72
|
-
}, this.__sharedSecret, bytes);
|
|
73
|
-
return convert_1.default.textDecode(decrypted);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
exports.default = EcdhSpki;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import crypto from "node:crypto";
|
|
3
|
-
export default class EcdhSpki {
|
|
4
|
-
publicKey: string;
|
|
5
|
-
iv: string;
|
|
6
|
-
__keyPair: CryptoKeyPair | undefined;
|
|
7
|
-
__sharedSecret: CryptoKey | undefined;
|
|
8
|
-
__curve: string;
|
|
9
|
-
constructor(curve?: string);
|
|
10
|
-
generateKeys(iv: string): Promise<this>;
|
|
11
|
-
exportSpkiKey(cryptoKey: CryptoKey): Promise<string>;
|
|
12
|
-
importSpkiKey(keyBase64: string): Promise<crypto.webcrypto.CryptoKey>;
|
|
13
|
-
deriveSharedSecret(publicKeyBase64: string): Promise<this>;
|
|
14
|
-
encode(data: string): Promise<{
|
|
15
|
-
text: string;
|
|
16
|
-
iv: string;
|
|
17
|
-
}>;
|
|
18
|
-
decode(encrypted: string, iv: string): Promise<string>;
|
|
19
|
-
}
|