Files
CloudSSH/src/ssh/utils.ts
T
IT b95635bdd5 feat: 纯 Cloudflare 架构 Web SSH 工具
- Cloudflare Workers + Durable Objects
- 自实现 SSH 协议引擎(ECDH-P256 + AES-256-GCM)
- 前端:Vite + TypeScript + xterm.js
- 支持密码认证、终端渲染、窗口自适应
2026-06-12 15:09:29 +08:00

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);
}