mc-tunnel 0.2.0 → 0.2.2
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/cjs/constants.js +1 -1
- package/dist/cjs/passphrase.js +13 -7
- package/dist/cjs/passphrase.js.map +1 -1
- package/dist/esm/constants.js +1 -1
- package/dist/esm/passphrase.js +13 -7
- package/dist/esm/passphrase.js.map +1 -1
- package/dist/types/constants.d.ts +1 -1
- package/dist/types/passphrase.d.ts +4 -2
- package/docs/USAGE.md +4 -1
- package/package.json +66 -66
package/dist/cjs/constants.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.MC_WATCH_INTERVAL_MS = exports.HEARTBEAT_INTERVAL_MS = exports.DEFAULT_MOTD = exports.DEFAULT_COORD_PORT = exports.HOST_VIRTUAL_IP = exports.VERSION = void 0;
|
|
5
5
|
/** 与 package.json 的 version 保持一致(发布前请同步)。 */
|
|
6
|
-
exports.VERSION = '0.2.
|
|
6
|
+
exports.VERSION = '0.2.2';
|
|
7
7
|
/**
|
|
8
8
|
* 房主在虚拟网络中的固定地址。
|
|
9
9
|
* 10.144.144.0/24 是 EasyTier 的默认虚拟网段,固定 .1 可以让客人无需任何发现协议
|
package/dist/cjs/passphrase.js
CHANGED
|
@@ -27,15 +27,17 @@ const PASSPHRASE_LABEL = 'mc-tunnel/v1/passphrase';
|
|
|
27
27
|
const SEED_MASK = (1n << 64n) - 1n;
|
|
28
28
|
/**
|
|
29
29
|
* 口令归一化,让「同一个口令的不同写法」落到同一个种子:
|
|
30
|
-
* - NFKC:全角字符折成半角(`ABC` → `ABC`,`123` → `123
|
|
31
|
-
* -
|
|
30
|
+
* - NFKC:全角字符折成半角(`ABC` → `ABC`,`123` → `123`,全角空格 → 半角空格)
|
|
31
|
+
* - **所有空白一律删除**:中文短语里的空格、换行、制表符只是排版噪音,
|
|
32
|
+
* 「为理云鬓 为簪银钩」与「为理云鬓为簪银钩」视为同一口令;
|
|
33
|
+
* 英文里 `hello world` 与 `helloworld` 同理等价
|
|
32
34
|
* - 统一小写(英文大小写不敏感,对中文无影响)
|
|
33
35
|
*/
|
|
34
36
|
function normalizePassphrase(input) {
|
|
35
37
|
if (typeof input !== 'string') {
|
|
36
38
|
return '';
|
|
37
39
|
}
|
|
38
|
-
return input.normalize('NFKC').
|
|
40
|
+
return input.normalize('NFKC').replace(/\s+/g, '').toLowerCase();
|
|
39
41
|
}
|
|
40
42
|
/**
|
|
41
43
|
* 口令 → 64 bit 种子。
|
|
@@ -65,13 +67,17 @@ function roomCodeFromPassphrase(passphrase) {
|
|
|
65
67
|
* 真实强度约等于其「猜测难度」,这里只给一个可读的分档。
|
|
66
68
|
*/
|
|
67
69
|
function passphraseStrength(passphrase) {
|
|
68
|
-
|
|
70
|
+
// 空白只起分隔作用,不计入长度(否则「彩蛋口令 演示」会被当成 7 个字符而误判为弱)
|
|
71
|
+
const text = normalizePassphrase(passphrase).replace(/\s/g, '');
|
|
69
72
|
const chars = Array.from(text);
|
|
70
73
|
const length = chars.length;
|
|
74
|
+
if (length === 0) {
|
|
75
|
+
return 'weak';
|
|
76
|
+
}
|
|
71
77
|
const cjk = chars.filter((char) => /[\u3400-\u9fff]/.test(char)).length;
|
|
72
|
-
//
|
|
73
|
-
const
|
|
74
|
-
if (
|
|
78
|
+
// 单个汉字的选择空间远大于英文字母,以汉字为主的口令用更短的阈值,避免被误判为弱
|
|
79
|
+
const mostlyCJK = cjk / length >= 0.6;
|
|
80
|
+
if (mostlyCJK) {
|
|
75
81
|
if (length < 4) {
|
|
76
82
|
return 'weak';
|
|
77
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passphrase.js","sourceRoot":"","sources":["../../src/passphrase.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"passphrase.js","sourceRoot":"","sources":["../../src/passphrase.ts"],"names":[],"mappings":";;AAgCA,kDAMC;AAMD,gDAUC;AAQD,wDAEC;AAQD,gDAiCC;AAzGD;;;;;;;;;;;;;GAaG;AACH,6CAAyC;AACzC,2CAA0C;AAC1C,iDAAkD;AAElD,mCAAmC;AACnC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAEnD,mBAAmB;AACnB,MAAM,SAAS,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;AAEnC;;;;;;;GAOG;AACH,SAAgB,mBAAmB,CAAC,KAAa;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACnE,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,UAAkB;IACnD,MAAM,IAAI,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAE7C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,uBAAW,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,wBAAU,EAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;IAEpF,OAAO,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;AAC/C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,UAAkB;IACvD,OAAO,IAAA,+BAAgB,EAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,UAAkB;IACnD,6CAA6C;IAC7C,MAAM,IAAI,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAE5B,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IACxE,0CAA0C;IAC1C,MAAM,SAAS,GAAG,GAAG,GAAG,MAAM,IAAI,GAAG,CAAC;IAEtC,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACf,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,OAAO,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IACvC,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAExF,IAAI,MAAM,IAAI,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC;QACnD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/esm/constants.js
CHANGED
package/dist/esm/passphrase.js
CHANGED
|
@@ -21,15 +21,17 @@ const PASSPHRASE_LABEL = 'mc-tunnel/v1/passphrase';
|
|
|
21
21
|
const SEED_MASK = (1n << 64n) - 1n;
|
|
22
22
|
/**
|
|
23
23
|
* 口令归一化,让「同一个口令的不同写法」落到同一个种子:
|
|
24
|
-
* - NFKC:全角字符折成半角(`ABC` → `ABC`,`123` → `123
|
|
25
|
-
* -
|
|
24
|
+
* - NFKC:全角字符折成半角(`ABC` → `ABC`,`123` → `123`,全角空格 → 半角空格)
|
|
25
|
+
* - **所有空白一律删除**:中文短语里的空格、换行、制表符只是排版噪音,
|
|
26
|
+
* 「为理云鬓 为簪银钩」与「为理云鬓为簪银钩」视为同一口令;
|
|
27
|
+
* 英文里 `hello world` 与 `helloworld` 同理等价
|
|
26
28
|
* - 统一小写(英文大小写不敏感,对中文无影响)
|
|
27
29
|
*/
|
|
28
30
|
export function normalizePassphrase(input) {
|
|
29
31
|
if (typeof input !== 'string') {
|
|
30
32
|
return '';
|
|
31
33
|
}
|
|
32
|
-
return input.normalize('NFKC').
|
|
34
|
+
return input.normalize('NFKC').replace(/\s+/g, '').toLowerCase();
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* 口令 → 64 bit 种子。
|
|
@@ -59,13 +61,17 @@ export function roomCodeFromPassphrase(passphrase) {
|
|
|
59
61
|
* 真实强度约等于其「猜测难度」,这里只给一个可读的分档。
|
|
60
62
|
*/
|
|
61
63
|
export function passphraseStrength(passphrase) {
|
|
62
|
-
|
|
64
|
+
// 空白只起分隔作用,不计入长度(否则「彩蛋口令 演示」会被当成 7 个字符而误判为弱)
|
|
65
|
+
const text = normalizePassphrase(passphrase).replace(/\s/g, '');
|
|
63
66
|
const chars = Array.from(text);
|
|
64
67
|
const length = chars.length;
|
|
68
|
+
if (length === 0) {
|
|
69
|
+
return 'weak';
|
|
70
|
+
}
|
|
65
71
|
const cjk = chars.filter((char) => /[\u3400-\u9fff]/.test(char)).length;
|
|
66
|
-
//
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
72
|
+
// 单个汉字的选择空间远大于英文字母,以汉字为主的口令用更短的阈值,避免被误判为弱
|
|
73
|
+
const mostlyCJK = cjk / length >= 0.6;
|
|
74
|
+
if (mostlyCJK) {
|
|
69
75
|
if (length < 4) {
|
|
70
76
|
return 'weak';
|
|
71
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passphrase.js","sourceRoot":"","sources":["../../src/passphrase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,mCAAmC;AACnC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAEnD,mBAAmB;AACnB,MAAM,SAAS,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;AAEnC
|
|
1
|
+
{"version":3,"file":"passphrase.js","sourceRoot":"","sources":["../../src/passphrase.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 口令归一化,让「同一个口令的不同写法」落到同一个种子:
|
|
3
|
-
* - NFKC:全角字符折成半角(`ABC` → `ABC`,`123` → `123
|
|
4
|
-
* -
|
|
3
|
+
* - NFKC:全角字符折成半角(`ABC` → `ABC`,`123` → `123`,全角空格 → 半角空格)
|
|
4
|
+
* - **所有空白一律删除**:中文短语里的空格、换行、制表符只是排版噪音,
|
|
5
|
+
* 「为理云鬓 为簪银钩」与「为理云鬓为簪银钩」视为同一口令;
|
|
6
|
+
* 英文里 `hello world` 与 `helloworld` 同理等价
|
|
5
7
|
* - 统一小写(英文大小写不敏感,对中文无影响)
|
|
6
8
|
*/
|
|
7
9
|
export declare function normalizePassphrase(input: string): string;
|
package/docs/USAGE.md
CHANGED
|
@@ -602,11 +602,14 @@ const guest = await createGuest({ passphrase: ' 彩蛋口令 演示 ' });
|
|
|
602
602
|
原理:
|
|
603
603
|
|
|
604
604
|
```
|
|
605
|
-
口令 → NFKC 归一化 →
|
|
605
|
+
口令 → NFKC 归一化 → 删除所有空白 → 小写
|
|
606
606
|
→ HMAC-SHA256('mc-tunnel/v1/passphrase', 口令) 前 8 字节 = 64 bit 种子
|
|
607
607
|
→ 与随机房间码走**完全相同**的派生链(网络名 / 网络密钥 / probe / token)
|
|
608
608
|
```
|
|
609
609
|
|
|
610
|
+
空白是**完全忽略**的(不是折叠成一个空格):`为理云鬓 为簪银钩` 与 `为理云鬓为簪银钩`
|
|
611
|
+
等价,`hello world` 与 `helloworld` 也等价——这样从聊天记录、换行、全角空格里复制粘贴都不会出错。
|
|
612
|
+
|
|
610
613
|
因此「口令」和「房间码」是同一个种子的两种表达方式,两者可互换:
|
|
611
614
|
|
|
612
615
|
```ts
|
package/package.json
CHANGED
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mc-tunnel",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "面向 Electron / Node.js 的 Minecraft 局域网联机模块:房间码一键组网,基于 EasyTier 的 P2P 隧道(Minecraft LAN tunnel)",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"main": "./dist/cjs/index.js",
|
|
8
|
-
"module": "./dist/esm/index.js",
|
|
9
|
-
"types": "./dist/types/index.d.ts",
|
|
10
|
-
"exports": {
|
|
11
|
-
".": {
|
|
12
|
-
"types": "./dist/types/index.d.ts",
|
|
13
|
-
"import": "./dist/esm/index.js",
|
|
14
|
-
"require": "./dist/cjs/index.js"
|
|
15
|
-
},
|
|
16
|
-
"./electron": {
|
|
17
|
-
"types": "./dist/types/electron.d.ts",
|
|
18
|
-
"import": "./dist/esm/electron.js",
|
|
19
|
-
"require": "./dist/cjs/electron.js"
|
|
20
|
-
},
|
|
21
|
-
"./zh": {
|
|
22
|
-
"types": "./dist/types/chinese-code.d.ts",
|
|
23
|
-
"import": "./dist/esm/chinese-code.js",
|
|
24
|
-
"require": "./dist/cjs/chinese-code.js"
|
|
25
|
-
},
|
|
26
|
-
"./package.json": "./package.json"
|
|
27
|
-
},
|
|
28
|
-
"files": [
|
|
29
|
-
"dist",
|
|
30
|
-
"docs",
|
|
31
|
-
"README.md",
|
|
32
|
-
"LICENSE",
|
|
33
|
-
"THIRD_PARTY_NOTICES.md"
|
|
34
|
-
],
|
|
35
|
-
"engines": {
|
|
36
|
-
"node": ">=18.17"
|
|
37
|
-
},
|
|
38
|
-
"publishConfig": {
|
|
39
|
-
"registry": "https://registry.npmjs.org/",
|
|
40
|
-
"access": "public"
|
|
41
|
-
},
|
|
42
|
-
"keywords": [
|
|
43
|
-
"minecraft",
|
|
44
|
-
"lan",
|
|
45
|
-
"tunnel",
|
|
46
|
-
"p2p",
|
|
47
|
-
"easytier",
|
|
48
|
-
"electron",
|
|
49
|
-
"我的世界",
|
|
50
|
-
"联机",
|
|
51
|
-
"局域网"
|
|
52
|
-
],
|
|
53
|
-
"scripts": {
|
|
54
|
-
"clean": "node scripts/clean.mjs",
|
|
55
|
-
"build": "npm run clean && tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json && tsc -p tsconfig.types.json && node scripts/postbuild.mjs",
|
|
56
|
-
"typecheck": "tsc -p tsconfig.esm.json --noEmit",
|
|
57
|
-
"test": "node --test \"test/**/*.test.mjs\"",
|
|
58
|
-
"prepack": "npm run build",
|
|
59
|
-
"release": "npm publish",
|
|
60
|
-
"release:mirror": "node scripts/sync-mirror.mjs"
|
|
61
|
-
},
|
|
62
|
-
"devDependencies": {
|
|
63
|
-
"@types/node": "^22.10.0",
|
|
64
|
-
"typescript": "^5.7.0"
|
|
65
|
-
}
|
|
66
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "mc-tunnel",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "面向 Electron / Node.js 的 Minecraft 局域网联机模块:房间码一键组网,基于 EasyTier 的 P2P 隧道(Minecraft LAN tunnel)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/cjs/index.js",
|
|
8
|
+
"module": "./dist/esm/index.js",
|
|
9
|
+
"types": "./dist/types/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/types/index.d.ts",
|
|
13
|
+
"import": "./dist/esm/index.js",
|
|
14
|
+
"require": "./dist/cjs/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./electron": {
|
|
17
|
+
"types": "./dist/types/electron.d.ts",
|
|
18
|
+
"import": "./dist/esm/electron.js",
|
|
19
|
+
"require": "./dist/cjs/electron.js"
|
|
20
|
+
},
|
|
21
|
+
"./zh": {
|
|
22
|
+
"types": "./dist/types/chinese-code.d.ts",
|
|
23
|
+
"import": "./dist/esm/chinese-code.js",
|
|
24
|
+
"require": "./dist/cjs/chinese-code.js"
|
|
25
|
+
},
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"docs",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE",
|
|
33
|
+
"THIRD_PARTY_NOTICES.md"
|
|
34
|
+
],
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.17"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"registry": "https://registry.npmjs.org/",
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"minecraft",
|
|
44
|
+
"lan",
|
|
45
|
+
"tunnel",
|
|
46
|
+
"p2p",
|
|
47
|
+
"easytier",
|
|
48
|
+
"electron",
|
|
49
|
+
"我的世界",
|
|
50
|
+
"联机",
|
|
51
|
+
"局域网"
|
|
52
|
+
],
|
|
53
|
+
"scripts": {
|
|
54
|
+
"clean": "node scripts/clean.mjs",
|
|
55
|
+
"build": "npm run clean && tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json && tsc -p tsconfig.types.json && node scripts/postbuild.mjs",
|
|
56
|
+
"typecheck": "tsc -p tsconfig.esm.json --noEmit",
|
|
57
|
+
"test": "node --test \"test/**/*.test.mjs\"",
|
|
58
|
+
"prepack": "npm run build",
|
|
59
|
+
"release": "npm publish",
|
|
60
|
+
"release:mirror": "node scripts/sync-mirror.mjs"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/node": "^22.10.0",
|
|
64
|
+
"typescript": "^5.7.0"
|
|
65
|
+
}
|
|
66
|
+
}
|