dsh-remote-plugin 0.4.9 → 0.5.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/README.md +4 -4
- package/apk/dsh-remote.apk +0 -0
- package/gateway.cjs +132 -7
- package/index.mjs +4 -2
- package/package.json +1 -1
- package/public/admin.html +14 -0
- package/public/admin.js +65 -1
- package/public/app.js +287 -60
- package/public/index.html +9 -0
- package/public/qrcode.min.js +2297 -0
- package/public/sha256.js +119 -0
- package/public/styles.css +2 -0
- package/public/update.json +3 -3
- package/public/version.json +1 -1
package/public/sha256.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* 纯 JS SHA-256(零依赖,二进制安全)
|
|
2
|
+
* 上传大文件时逐块喂入 4MB slice,最后与网关计算的 SHA-256 比对,防坏包。
|
|
3
|
+
*/
|
|
4
|
+
'use strict'
|
|
5
|
+
|
|
6
|
+
function SHA256() {
|
|
7
|
+
this.h = new Uint32Array([
|
|
8
|
+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
|
9
|
+
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
|
10
|
+
])
|
|
11
|
+
this.buf = new Uint8Array(64)
|
|
12
|
+
this.bufLen = 0
|
|
13
|
+
this.total = 0
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
SHA256.prototype._process = function (block) {
|
|
17
|
+
const w = new Uint32Array(64)
|
|
18
|
+
for (let i = 0; i < 16; i++) {
|
|
19
|
+
w[i] = (block[i * 4] << 24) | (block[i * 4 + 1] << 16) | (block[i * 4 + 2] << 8) | block[i * 4 + 3]
|
|
20
|
+
}
|
|
21
|
+
for (let i = 16; i < 64; i++) {
|
|
22
|
+
const s0 = ((w[i - 15] >>> 7) | (w[i - 15] << 25)) ^ ((w[i - 15] >>> 18) | (w[i - 15] << 14)) ^ (w[i - 15] >>> 3)
|
|
23
|
+
const s1 = ((w[i - 2] >>> 17) | (w[i - 2] << 15)) ^ ((w[i - 2] >>> 19) | (w[i - 2] << 13)) ^ (w[i - 2] >>> 10)
|
|
24
|
+
w[i] = (w[i - 16] + s0 + w[i - 7] + s1) >>> 0
|
|
25
|
+
}
|
|
26
|
+
let a = this.h[0], b = this.h[1], c = this.h[2], d = this.h[3]
|
|
27
|
+
let e = this.h[4], f = this.h[5], g = this.h[6], h = this.h[7]
|
|
28
|
+
for (let i = 0; i < 64; i++) {
|
|
29
|
+
const S1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7))
|
|
30
|
+
const ch = (e & f) ^ (~e & g)
|
|
31
|
+
const t1 = (h + S1 + ch + K[i] + w[i]) >>> 0
|
|
32
|
+
const S0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10))
|
|
33
|
+
const maj = (a & b) ^ (a & c) ^ (b & c)
|
|
34
|
+
const t2 = (S0 + maj) >>> 0
|
|
35
|
+
h = g; g = f; f = e; e = (d + t1) >>> 0
|
|
36
|
+
d = c; c = b; b = a; a = (t1 + t2) >>> 0
|
|
37
|
+
}
|
|
38
|
+
this.h[0] = (this.h[0] + a) >>> 0
|
|
39
|
+
this.h[1] = (this.h[1] + b) >>> 0
|
|
40
|
+
this.h[2] = (this.h[2] + c) >>> 0
|
|
41
|
+
this.h[3] = (this.h[3] + d) >>> 0
|
|
42
|
+
this.h[4] = (this.h[4] + e) >>> 0
|
|
43
|
+
this.h[5] = (this.h[5] + f) >>> 0
|
|
44
|
+
this.h[6] = (this.h[6] + g) >>> 0
|
|
45
|
+
this.h[7] = (this.h[7] + h) >>> 0
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
SHA256.prototype.update = function (bytes) {
|
|
49
|
+
const data = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)
|
|
50
|
+
this.total += data.length
|
|
51
|
+
let i = 0
|
|
52
|
+
if (this.bufLen > 0) {
|
|
53
|
+
const need = 64 - this.bufLen
|
|
54
|
+
const n = Math.min(need, data.length)
|
|
55
|
+
this.buf.set(data.subarray(0, n), this.bufLen)
|
|
56
|
+
this.bufLen += n
|
|
57
|
+
i = n
|
|
58
|
+
if (this.bufLen === 64) {
|
|
59
|
+
this._process(this.buf)
|
|
60
|
+
this.bufLen = 0
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
while (i + 64 <= data.length) {
|
|
64
|
+
this._process(data.subarray(i, i + 64))
|
|
65
|
+
i += 64
|
|
66
|
+
}
|
|
67
|
+
if (i < data.length) {
|
|
68
|
+
this.buf.set(data.subarray(i), 0)
|
|
69
|
+
this.bufLen = data.length - i
|
|
70
|
+
}
|
|
71
|
+
return this
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
SHA256.prototype.clone = function () {
|
|
75
|
+
const c = new SHA256()
|
|
76
|
+
c.h.set(this.h)
|
|
77
|
+
c.buf.set(this.buf)
|
|
78
|
+
c.bufLen = this.bufLen
|
|
79
|
+
c.total = this.total
|
|
80
|
+
return c
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
SHA256.prototype.hex = function () {
|
|
84
|
+
const lenBits = this.total * 8
|
|
85
|
+
const pad = new Uint8Array(72)
|
|
86
|
+
pad[0] = 0x80
|
|
87
|
+
const tail = (this.total + 9) % 64
|
|
88
|
+
const zero = tail === 0 ? 0 : 64 - tail
|
|
89
|
+
const padLen = 1 + zero + 8
|
|
90
|
+
// 长度 64 位大端: 高位 32 位 + 低位 32 位
|
|
91
|
+
const hi = Math.floor(lenBits / 0x100000000)
|
|
92
|
+
const lo = lenBits >>> 0
|
|
93
|
+
pad[padLen - 8] = (hi >>> 24) & 0xff
|
|
94
|
+
pad[padLen - 7] = (hi >>> 16) & 0xff
|
|
95
|
+
pad[padLen - 6] = (hi >>> 8) & 0xff
|
|
96
|
+
pad[padLen - 5] = hi & 0xff
|
|
97
|
+
pad[padLen - 4] = (lo >>> 24) & 0xff
|
|
98
|
+
pad[padLen - 3] = (lo >>> 16) & 0xff
|
|
99
|
+
pad[padLen - 2] = (lo >>> 8) & 0xff
|
|
100
|
+
pad[padLen - 1] = lo & 0xff
|
|
101
|
+
this.update(pad.subarray(0, padLen))
|
|
102
|
+
const out = []
|
|
103
|
+
for (let i = 0; i < 8; i++) {
|
|
104
|
+
const v = this.h[i]
|
|
105
|
+
out.push((v >>> 24).toString(16).padStart(2, '0'), ((v >>> 16) & 0xff).toString(16).padStart(2, '0'), ((v >>> 8) & 0xff).toString(16).padStart(2, '0'), (v & 0xff).toString(16).padStart(2, '0'))
|
|
106
|
+
}
|
|
107
|
+
return out.join('')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const K = new Uint32Array([
|
|
111
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
112
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
113
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
114
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
115
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
116
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
117
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
118
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
119
|
+
])
|
package/public/styles.css
CHANGED
|
@@ -328,6 +328,8 @@ body.in-session .main { padding-bottom: 84px; }
|
|
|
328
328
|
transition: width .15s ease;
|
|
329
329
|
}
|
|
330
330
|
.fs-progress-text { flex-shrink: 0; min-width: 112px; text-align: right; }
|
|
331
|
+
.fs-progress-actions { flex-shrink: 0; display: flex; gap: 6px; }
|
|
332
|
+
.fs-progress-actions .mini-btn { padding: 4px 10px; font-size: 12px; }
|
|
331
333
|
.fs-pull {
|
|
332
334
|
height: 0; overflow: hidden; text-align: center; font-size: 12px; color: var(--cyan);
|
|
333
335
|
transition: height .12s ease; line-height: 26px;
|
package/public/update.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.5.0",
|
|
3
3
|
"apkUrl": "dsh-remote.apk",
|
|
4
|
-
"releasedAt": "2026-08-
|
|
5
|
-
"notes": "
|
|
4
|
+
"releasedAt": "2026-08-16T04:01:50.533Z",
|
|
5
|
+
"notes": "上传支持暂停/取消与 SHA-256 完整性校验; 网关管理页一键生成令牌二维码+轮换令牌, 手机 App 扫码自动配对; Release 自动附 changelog 与 SHA256SUMS"
|
|
6
6
|
}
|
package/public/version.json
CHANGED