- Cloudflare Workers + Durable Objects - 自实现 SSH 协议引擎(ECDH-P256 + AES-256-GCM) - 前端:Vite + TypeScript + xterm.js - 支持密码认证、终端渲染、窗口自适应
64 lines
1.7 KiB
TypeScript
64 lines
1.7 KiB
TypeScript
export function concat(...arrays: Uint8Array[]): Uint8Array {
|
|
const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
const result = new Uint8Array(totalLength);
|
|
let offset = 0;
|
|
for (const arr of arrays) {
|
|
result.set(arr, offset);
|
|
offset += arr.length;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
export function readUint32(data: Uint8Array, offset: number): number {
|
|
return (data[offset] << 24) | (data[offset + 1] << 16) |
|
|
(data[offset + 2] << 8) | data[offset + 3];
|
|
}
|
|
|
|
export function encodeUint32(value: number): Uint8Array {
|
|
const buf = new Uint8Array(4);
|
|
new DataView(buf.buffer).setUint32(0, value, false);
|
|
return buf;
|
|
}
|
|
|
|
export function encodeString(input: string | Uint8Array): Uint8Array {
|
|
const encoded = typeof input === 'string'
|
|
? new TextEncoder().encode(input)
|
|
: input;
|
|
const len = encodeUint32(encoded.length);
|
|
return concat(len, encoded);
|
|
}
|
|
|
|
export function toSSHMPInt(bytes: Uint8Array): Uint8Array {
|
|
let start = 0;
|
|
while (start < bytes.length - 1 && bytes[start] === 0) {
|
|
start++;
|
|
}
|
|
let significant = bytes.slice(start);
|
|
|
|
if (significant[0] & 0x80) {
|
|
significant = concat(new Uint8Array([0]), significant);
|
|
}
|
|
|
|
return encodeString(significant);
|
|
}
|
|
|
|
export function extractRawECDHPoint(blob: Uint8Array): Uint8Array {
|
|
let offset = 0;
|
|
|
|
const keyTypeLen = readUint32(blob, offset);
|
|
offset += 4 + keyTypeLen;
|
|
|
|
const curveLen = readUint32(blob, offset);
|
|
offset += 4 + curveLen;
|
|
|
|
const pointLen = readUint32(blob, offset);
|
|
offset += 4;
|
|
|
|
return blob.slice(offset, offset + pointLen);
|
|
}
|
|
|
|
export function encodePrefixedString(str: string): Uint8Array {
|
|
const encoded = new TextEncoder().encode(str);
|
|
return concat(encodeUint32(encoded.length), encoded);
|
|
}
|