ssh2web 1.0.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 +122 -0
- package/dist/auth/authstate.d.ts +14 -0
- package/dist/auth/authstate.d.ts.map +1 -0
- package/dist/auth/authstate.js +25 -0
- package/dist/auth/certparser.d.ts +9 -0
- package/dist/auth/certparser.d.ts.map +1 -0
- package/dist/auth/certparser.js +13 -0
- package/dist/auth/keys.d.ts +7 -0
- package/dist/auth/keys.d.ts.map +1 -0
- package/dist/auth/keys.js +18 -0
- package/dist/channel/channelstate.d.ts +18 -0
- package/dist/channel/channelstate.d.ts.map +1 -0
- package/dist/channel/channelstate.js +30 -0
- package/dist/connection/connectSSH.d.ts +8 -0
- package/dist/connection/connectSSH.d.ts.map +1 -0
- package/dist/connection/connectSSH.js +516 -0
- package/dist/connection/connectionstate.d.ts +23 -0
- package/dist/connection/connectionstate.d.ts.map +1 -0
- package/dist/connection/connectionstate.js +46 -0
- package/dist/connection/types.d.ts +17 -0
- package/dist/connection/types.d.ts.map +1 -0
- package/dist/connection/types.js +4 -0
- package/dist/crypto/arithmetic.d.ts +7 -0
- package/dist/crypto/arithmetic.d.ts.map +1 -0
- package/dist/crypto/arithmetic.js +34 -0
- package/dist/crypto/cipher.d.ts +9 -0
- package/dist/crypto/cipher.d.ts.map +1 -0
- package/dist/crypto/cipher.js +43 -0
- package/dist/crypto/digest.d.ts +6 -0
- package/dist/crypto/digest.d.ts.map +1 -0
- package/dist/crypto/digest.js +10 -0
- package/dist/crypto/keyexchange.d.ts +11 -0
- package/dist/crypto/keyexchange.d.ts.map +1 -0
- package/dist/crypto/keyexchange.js +35 -0
- package/dist/crypto/keys.d.ts +11 -0
- package/dist/crypto/keys.d.ts.map +1 -0
- package/dist/crypto/keys.js +27 -0
- package/dist/crypto/mac.d.ts +7 -0
- package/dist/crypto/mac.d.ts.map +1 -0
- package/dist/crypto/mac.js +17 -0
- package/dist/debug.d.ts +9 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +19 -0
- package/dist/domain/constants.d.ts +47 -0
- package/dist/domain/constants.d.ts.map +1 -0
- package/dist/domain/constants.js +46 -0
- package/dist/domain/errors.d.ts +25 -0
- package/dist/domain/errors.d.ts.map +1 -0
- package/dist/domain/errors.js +45 -0
- package/dist/domain/models.d.ts +60 -0
- package/dist/domain/models.d.ts.map +1 -0
- package/dist/domain/models.js +10 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/kex/builder.d.ts +2 -0
- package/dist/kex/builder.d.ts.map +1 -0
- package/dist/kex/builder.js +22 -0
- package/dist/kex/kexstate.d.ts +20 -0
- package/dist/kex/kexstate.d.ts.map +1 -0
- package/dist/kex/kexstate.js +35 -0
- package/dist/protocol/codec.d.ts +7 -0
- package/dist/protocol/codec.d.ts.map +1 -0
- package/dist/protocol/codec.js +35 -0
- package/dist/protocol/deserialization.d.ts +19 -0
- package/dist/protocol/deserialization.d.ts.map +1 -0
- package/dist/protocol/deserialization.js +53 -0
- package/dist/protocol/messages.d.ts +5 -0
- package/dist/protocol/messages.d.ts.map +1 -0
- package/dist/protocol/messages.js +33 -0
- package/dist/protocol/serialization.d.ts +11 -0
- package/dist/protocol/serialization.d.ts.map +1 -0
- package/dist/protocol/serialization.js +69 -0
- package/dist/transport/transportcipher.d.ts +25 -0
- package/dist/transport/transportcipher.d.ts.map +1 -0
- package/dist/transport/transportcipher.js +129 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +8 -0
- package/package.json +46 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cipher.d.ts","sourceRoot":"","sources":["../../crypto/cipher.ts"],"names":[],"mappings":"AAiBA,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,UAAU,EACd,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,CAiBzD;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,UAAU,EACd,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC;IAAE,SAAS,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,CAiBxD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AES-128-CTR encryption and decryption.
|
|
3
|
+
* Single responsibility: AES-CTR mode operations.
|
|
4
|
+
*/
|
|
5
|
+
import { AES_BLOCK_SIZE } from "../domain/constants";
|
|
6
|
+
function incrementCounter(iv, count = 1) {
|
|
7
|
+
const result = new Uint8Array(iv);
|
|
8
|
+
let carry = count;
|
|
9
|
+
for (let i = 15; i >= 0 && carry > 0; i--) {
|
|
10
|
+
const sum = result[i] + carry;
|
|
11
|
+
result[i] = sum & 0xff;
|
|
12
|
+
carry = sum >> 8;
|
|
13
|
+
}
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
export async function encryptAES128CTR(key, iv, plaintext) {
|
|
17
|
+
const ciphertext = new Uint8Array(plaintext.length);
|
|
18
|
+
const blocks = Math.ceil(plaintext.length / AES_BLOCK_SIZE);
|
|
19
|
+
let offset = 0;
|
|
20
|
+
let ivCopy = new Uint8Array(iv);
|
|
21
|
+
for (let i = 0; i < blocks; i++) {
|
|
22
|
+
const blockLen = Math.min(AES_BLOCK_SIZE, plaintext.length - offset);
|
|
23
|
+
const enc = await crypto.subtle.encrypt({ name: "AES-CTR", counter: ivCopy, length: 128 }, key, plaintext.subarray(offset, offset + blockLen));
|
|
24
|
+
ciphertext.set(new Uint8Array(enc), offset);
|
|
25
|
+
offset += blockLen;
|
|
26
|
+
ivCopy = incrementCounter(ivCopy, 1);
|
|
27
|
+
}
|
|
28
|
+
return { ciphertext, nextIv: ivCopy };
|
|
29
|
+
}
|
|
30
|
+
export async function decryptAES128CTR(key, iv, ciphertext) {
|
|
31
|
+
const plaintext = new Uint8Array(ciphertext.length);
|
|
32
|
+
const blocks = Math.ceil(ciphertext.length / AES_BLOCK_SIZE);
|
|
33
|
+
let offset = 0;
|
|
34
|
+
let ivCopy = new Uint8Array(iv);
|
|
35
|
+
for (let i = 0; i < blocks; i++) {
|
|
36
|
+
const blockLen = Math.min(AES_BLOCK_SIZE, ciphertext.length - offset);
|
|
37
|
+
const dec = await crypto.subtle.decrypt({ name: "AES-CTR", counter: ivCopy, length: 128 }, key, ciphertext.subarray(offset, offset + blockLen));
|
|
38
|
+
plaintext.set(new Uint8Array(dec), offset);
|
|
39
|
+
offset += blockLen;
|
|
40
|
+
ivCopy = incrementCounter(ivCopy, 1);
|
|
41
|
+
}
|
|
42
|
+
return { plaintext, nextIv: ivCopy };
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../../crypto/digest.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAKzE"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cryptographic hashing operations.
|
|
3
|
+
* Single responsibility: SHA256 hashing via Web Crypto API.
|
|
4
|
+
*/
|
|
5
|
+
export async function computeSHA256(data) {
|
|
6
|
+
const buffer = data.byteOffset === 0 && data.byteLength === data.buffer.byteLength
|
|
7
|
+
? data.buffer
|
|
8
|
+
: data.slice().buffer;
|
|
9
|
+
return new Uint8Array(await crypto.subtle.digest("SHA-256", buffer));
|
|
10
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function generateDHPrivate(): Promise<{
|
|
2
|
+
x: bigint;
|
|
3
|
+
e: bigint;
|
|
4
|
+
}>;
|
|
5
|
+
export declare function computeDHSharedSecret(f: bigint, x: bigint): bigint;
|
|
6
|
+
export declare function generateX25519KeyPair(): Promise<{
|
|
7
|
+
publicKey: Uint8Array;
|
|
8
|
+
privateKey: CryptoKey;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function computeX25519SharedSecret(privateKey: CryptoKey, publicKey: Uint8Array): Promise<Uint8Array>;
|
|
11
|
+
//# sourceMappingURL=keyexchange.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyexchange.d.ts","sourceRoot":"","sources":["../../crypto/keyexchange.ts"],"names":[],"mappings":"AAOA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAW3E;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC;IAAE,SAAS,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,SAAS,CAAA;CAAE,CAAC,CAQvG;AAED,wBAAsB,yBAAyB,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAOjH"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diffie-Hellman key exchange operations.
|
|
3
|
+
* Single responsibility: DH parameter generation and shared secret computation.
|
|
4
|
+
*/
|
|
5
|
+
import { modPow } from "./arithmetic";
|
|
6
|
+
import { DH_GENERATOR, DH_PRIME } from "../domain/constants";
|
|
7
|
+
export async function generateDHPrivate() {
|
|
8
|
+
let x;
|
|
9
|
+
let e;
|
|
10
|
+
do {
|
|
11
|
+
const xBytes = crypto.getRandomValues(new Uint8Array(32));
|
|
12
|
+
x = 0n;
|
|
13
|
+
for (let i = 0; i < xBytes.length; i++)
|
|
14
|
+
x = (x << 8n) | BigInt(xBytes[i]);
|
|
15
|
+
x = x % (DH_PRIME - 2n) + 2n;
|
|
16
|
+
e = modPow(DH_GENERATOR, x, DH_PRIME);
|
|
17
|
+
} while (e <= 1n || e >= DH_PRIME - 1n);
|
|
18
|
+
return { x, e };
|
|
19
|
+
}
|
|
20
|
+
export function computeDHSharedSecret(f, x) {
|
|
21
|
+
return modPow(f, x, DH_PRIME);
|
|
22
|
+
}
|
|
23
|
+
export async function generateX25519KeyPair() {
|
|
24
|
+
const keyPair = (await crypto.subtle.generateKey({ name: "X25519" }, true, ["deriveBits"]));
|
|
25
|
+
const pub = await crypto.subtle.exportKey("raw", keyPair.publicKey);
|
|
26
|
+
return { publicKey: new Uint8Array(pub), privateKey: keyPair.privateKey };
|
|
27
|
+
}
|
|
28
|
+
export async function computeX25519SharedSecret(privateKey, publicKey) {
|
|
29
|
+
const buffer = publicKey.byteOffset === 0 && publicKey.byteLength === publicKey.buffer.byteLength
|
|
30
|
+
? publicKey.buffer
|
|
31
|
+
: publicKey.slice().buffer;
|
|
32
|
+
const pub = await crypto.subtle.importKey("raw", buffer, { name: "X25519" }, false, []);
|
|
33
|
+
const bits = await crypto.subtle.deriveBits({ name: "X25519", public: pub }, privateKey, 256);
|
|
34
|
+
return new Uint8Array(bits);
|
|
35
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface DerivedKeys {
|
|
2
|
+
ivC: Uint8Array;
|
|
3
|
+
keyC: Uint8Array;
|
|
4
|
+
macC: Uint8Array;
|
|
5
|
+
ivS: Uint8Array;
|
|
6
|
+
keyS: Uint8Array;
|
|
7
|
+
macS: Uint8Array;
|
|
8
|
+
}
|
|
9
|
+
export declare function deriveKeys(sharedSecret: Uint8Array, exchangeHash: Uint8Array, sessionId: Uint8Array): Promise<DerivedKeys>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../crypto/keys.ts"],"names":[],"mappings":"AAMA,UAAU,WAAW;IACnB,GAAG,EAAE,UAAU,CAAC;IAChB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,UAAU,CAAC;IAChB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,wBAAsB,UAAU,CAC9B,YAAY,EAAE,UAAU,EACxB,YAAY,EAAE,UAAU,EACxB,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,WAAW,CAAC,CAWtB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key derivation from shared secret to session keys.
|
|
3
|
+
* RFC 4253: derives IVs, encryption keys, and MAC keys.
|
|
4
|
+
*/
|
|
5
|
+
import { computeSHA256 } from "./digest";
|
|
6
|
+
export async function deriveKeys(sharedSecret, exchangeHash, sessionId) {
|
|
7
|
+
const deriveKey = async (id) => {
|
|
8
|
+
return computeSHA256(concat(sharedSecret, exchangeHash, new Uint8Array([id]), sessionId));
|
|
9
|
+
};
|
|
10
|
+
const ivC = (await deriveKey(0x41)).subarray(0, 16);
|
|
11
|
+
const ivS = (await deriveKey(0x42)).subarray(0, 16);
|
|
12
|
+
const keyC = (await deriveKey(0x43)).subarray(0, 16);
|
|
13
|
+
const keyS = (await deriveKey(0x44)).subarray(0, 16);
|
|
14
|
+
const macC = (await deriveKey(0x45)).subarray(0, 32);
|
|
15
|
+
const macS = (await deriveKey(0x46)).subarray(0, 32);
|
|
16
|
+
return { ivC, keyC, macC, ivS, keyS, macS };
|
|
17
|
+
}
|
|
18
|
+
function concat(...arr) {
|
|
19
|
+
const len = arr.reduce((a, b) => a + b.length, 0);
|
|
20
|
+
const out = new Uint8Array(len);
|
|
21
|
+
let off = 0;
|
|
22
|
+
for (const a of arr) {
|
|
23
|
+
out.set(a, off);
|
|
24
|
+
off += a.length;
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HMAC-SHA256 message authentication.
|
|
3
|
+
* Single responsibility: HMAC computation and constant-time comparison.
|
|
4
|
+
*/
|
|
5
|
+
export declare function computeHMACSHA256(key: Uint8Array, data: Uint8Array): Promise<Uint8Array>;
|
|
6
|
+
export declare function constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean;
|
|
7
|
+
//# sourceMappingURL=mac.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mac.d.ts","sourceRoot":"","sources":["../../crypto/mac.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAU9F;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAKvE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HMAC-SHA256 message authentication.
|
|
3
|
+
* Single responsibility: HMAC computation and constant-time comparison.
|
|
4
|
+
*/
|
|
5
|
+
export async function computeHMACSHA256(key, data) {
|
|
6
|
+
const cryptoKey = await crypto.subtle.importKey("raw", key, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
7
|
+
const sig = await crypto.subtle.sign("HMAC", cryptoKey, data);
|
|
8
|
+
return new Uint8Array(sig);
|
|
9
|
+
}
|
|
10
|
+
export function constantTimeEqual(a, b) {
|
|
11
|
+
if (a.length !== b.length)
|
|
12
|
+
return false;
|
|
13
|
+
let diff = 0;
|
|
14
|
+
for (let i = 0; i < a.length; i++)
|
|
15
|
+
diff |= a[i] ^ b[i];
|
|
16
|
+
return diff === 0;
|
|
17
|
+
}
|
package/dist/debug.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug logging utility.
|
|
3
|
+
* Controlled by localStorage.ssh_debug flag.
|
|
4
|
+
*/
|
|
5
|
+
export declare function log(...args: unknown[]): void;
|
|
6
|
+
export declare function logDebug(...args: unknown[]): void;
|
|
7
|
+
export declare function logError(...args: unknown[]): void;
|
|
8
|
+
export declare function logWarn(...args: unknown[]): void;
|
|
9
|
+
//# sourceMappingURL=debug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../debug.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,wBAAgB,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAE5C;AAED,wBAAgB,QAAQ,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAEjD;AAED,wBAAgB,QAAQ,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAEjD;AAED,wBAAgB,OAAO,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAEhD"}
|
package/dist/debug.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug logging utility.
|
|
3
|
+
* Controlled by localStorage.ssh_debug flag.
|
|
4
|
+
*/
|
|
5
|
+
const DEBUG = typeof window === "undefined" || localStorage.getItem("ssh_debug") !== "0";
|
|
6
|
+
export function log(...args) {
|
|
7
|
+
if (DEBUG)
|
|
8
|
+
console.log("[SSH]", ...args);
|
|
9
|
+
}
|
|
10
|
+
export function logDebug(...args) {
|
|
11
|
+
if (DEBUG)
|
|
12
|
+
console.log("[SSH_DEBUG]", ...args);
|
|
13
|
+
}
|
|
14
|
+
export function logError(...args) {
|
|
15
|
+
console.error("[SSH_ERROR]", ...args);
|
|
16
|
+
}
|
|
17
|
+
export function logWarn(...args) {
|
|
18
|
+
console.warn("[SSH_WARN]", ...args);
|
|
19
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSH protocol message type constants.
|
|
3
|
+
*/
|
|
4
|
+
export declare const SSH_MSG_DISCONNECT = 1;
|
|
5
|
+
export declare const SSH_MSG_IGNORE = 2;
|
|
6
|
+
export declare const SSH_MSG_UNIMPLEMENTED = 3;
|
|
7
|
+
export declare const SSH_MSG_DEBUG = 4;
|
|
8
|
+
export declare const SSH_MSG_SERVICE_REQUEST = 5;
|
|
9
|
+
export declare const SSH_MSG_SERVICE_ACCEPT = 6;
|
|
10
|
+
export declare const SSH_MSG_EXT_INFO = 7;
|
|
11
|
+
export declare const SSH_MSG_KEXINIT = 20;
|
|
12
|
+
export declare const SSH_MSG_NEWKEYS = 21;
|
|
13
|
+
export declare const SSH_MSG_KEX_ECDH_INIT = 30;
|
|
14
|
+
export declare const SSH_MSG_KEX_ECDH_REPLY = 31;
|
|
15
|
+
export declare const SSH_MSG_KEXDH_INIT = 30;
|
|
16
|
+
export declare const SSH_MSG_KEXDH_REPLY = 31;
|
|
17
|
+
export declare const SSH_MSG_USERAUTH_REQUEST = 50;
|
|
18
|
+
export declare const SSH_MSG_USERAUTH_FAILURE = 51;
|
|
19
|
+
export declare const SSH_MSG_USERAUTH_SUCCESS = 52;
|
|
20
|
+
export declare const SSH_MSG_USERAUTH_PK_OK = 60;
|
|
21
|
+
export declare const SSH_MSG_GLOBAL_REQUEST = 80;
|
|
22
|
+
export declare const SSH_MSG_REQUEST_SUCCESS = 81;
|
|
23
|
+
export declare const SSH_MSG_REQUEST_FAILURE = 82;
|
|
24
|
+
export declare const SSH_MSG_CHANNEL_OPEN = 90;
|
|
25
|
+
export declare const SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91;
|
|
26
|
+
export declare const SSH_MSG_CHANNEL_REQUEST = 98;
|
|
27
|
+
export declare const SSH_MSG_CHANNEL_DATA = 94;
|
|
28
|
+
export declare const SSH_MSG_CHANNEL_EXTENDED_DATA = 95;
|
|
29
|
+
export declare const SSH_MSG_CHANNEL_SUCCESS = 99;
|
|
30
|
+
export declare const SSH_MSG_CHANNEL_FAILURE = 100;
|
|
31
|
+
export declare const SSH_MSG_CHANNEL_WINDOW_ADJUST = 93;
|
|
32
|
+
export declare const CLIENT_IDENT = "SSH-2.0-agentripper-ssh";
|
|
33
|
+
export declare const PREFERRED_KEX = "diffie-hellman-group14-sha256,curve25519-sha256,curve25519-sha256@libssh.org";
|
|
34
|
+
export declare const PREFERRED_CIPHER = "aes128-ctr";
|
|
35
|
+
export declare const PREFERRED_MAC = "hmac-sha2-256,hmac-sha2-256-etm@openssh.com";
|
|
36
|
+
export declare const DH_GENERATOR = 2n;
|
|
37
|
+
export declare const DH_PRIME: bigint;
|
|
38
|
+
export declare const AES_BLOCK_SIZE = 16;
|
|
39
|
+
export declare const HMAC_SHA256_SIZE = 32;
|
|
40
|
+
export declare const MIN_PADDING = 4;
|
|
41
|
+
export declare const DEFAULT_TERMINAL_TYPE = "xterm-256color";
|
|
42
|
+
export declare const DEFAULT_TERMINAL_COLS = 80;
|
|
43
|
+
export declare const DEFAULT_TERMINAL_ROWS = 24;
|
|
44
|
+
export declare const KEX_TIMEOUT_MS = 8000;
|
|
45
|
+
export declare const MAX_PACKET_SIZE = 35000;
|
|
46
|
+
export declare const DEFAULT_WINDOW_SIZE = 32768;
|
|
47
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../domain/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,iCAAiC,KAAK,CAAC;AACpD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,eAAO,MAAM,YAAY,4BAA4B,CAAC;AACtD,eAAO,MAAM,aAAa,iFAAiF,CAAC;AAC5G,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAC7C,eAAO,MAAM,aAAa,gDAAgD,CAAC;AAE3E,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,QAAQ,QAA+gB,CAAC;AAEriB,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AACtD,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,cAAc,OAAO,CAAC;AACnC,eAAO,MAAM,eAAe,QAAQ,CAAC;AACrC,eAAO,MAAM,mBAAmB,QAAS,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSH protocol message type constants.
|
|
3
|
+
*/
|
|
4
|
+
export const SSH_MSG_DISCONNECT = 1;
|
|
5
|
+
export const SSH_MSG_IGNORE = 2;
|
|
6
|
+
export const SSH_MSG_UNIMPLEMENTED = 3;
|
|
7
|
+
export const SSH_MSG_DEBUG = 4;
|
|
8
|
+
export const SSH_MSG_SERVICE_REQUEST = 5;
|
|
9
|
+
export const SSH_MSG_SERVICE_ACCEPT = 6;
|
|
10
|
+
export const SSH_MSG_EXT_INFO = 7;
|
|
11
|
+
export const SSH_MSG_KEXINIT = 20;
|
|
12
|
+
export const SSH_MSG_NEWKEYS = 21;
|
|
13
|
+
export const SSH_MSG_KEX_ECDH_INIT = 30;
|
|
14
|
+
export const SSH_MSG_KEX_ECDH_REPLY = 31;
|
|
15
|
+
export const SSH_MSG_KEXDH_INIT = 30;
|
|
16
|
+
export const SSH_MSG_KEXDH_REPLY = 31;
|
|
17
|
+
export const SSH_MSG_USERAUTH_REQUEST = 50;
|
|
18
|
+
export const SSH_MSG_USERAUTH_FAILURE = 51;
|
|
19
|
+
export const SSH_MSG_USERAUTH_SUCCESS = 52;
|
|
20
|
+
export const SSH_MSG_USERAUTH_PK_OK = 60;
|
|
21
|
+
export const SSH_MSG_GLOBAL_REQUEST = 80;
|
|
22
|
+
export const SSH_MSG_REQUEST_SUCCESS = 81;
|
|
23
|
+
export const SSH_MSG_REQUEST_FAILURE = 82;
|
|
24
|
+
export const SSH_MSG_CHANNEL_OPEN = 90;
|
|
25
|
+
export const SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91;
|
|
26
|
+
export const SSH_MSG_CHANNEL_REQUEST = 98;
|
|
27
|
+
export const SSH_MSG_CHANNEL_DATA = 94;
|
|
28
|
+
export const SSH_MSG_CHANNEL_EXTENDED_DATA = 95;
|
|
29
|
+
export const SSH_MSG_CHANNEL_SUCCESS = 99;
|
|
30
|
+
export const SSH_MSG_CHANNEL_FAILURE = 100;
|
|
31
|
+
export const SSH_MSG_CHANNEL_WINDOW_ADJUST = 93;
|
|
32
|
+
export const CLIENT_IDENT = "SSH-2.0-agentripper-ssh";
|
|
33
|
+
export const PREFERRED_KEX = "diffie-hellman-group14-sha256,curve25519-sha256,curve25519-sha256@libssh.org";
|
|
34
|
+
export const PREFERRED_CIPHER = "aes128-ctr";
|
|
35
|
+
export const PREFERRED_MAC = "hmac-sha2-256,hmac-sha2-256-etm@openssh.com";
|
|
36
|
+
export const DH_GENERATOR = 2n;
|
|
37
|
+
export const DH_PRIME = BigInt("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF");
|
|
38
|
+
export const AES_BLOCK_SIZE = 16;
|
|
39
|
+
export const HMAC_SHA256_SIZE = 32;
|
|
40
|
+
export const MIN_PADDING = 4;
|
|
41
|
+
export const DEFAULT_TERMINAL_TYPE = "xterm-256color";
|
|
42
|
+
export const DEFAULT_TERMINAL_COLS = 80;
|
|
43
|
+
export const DEFAULT_TERMINAL_ROWS = 24;
|
|
44
|
+
export const KEX_TIMEOUT_MS = 8000;
|
|
45
|
+
export const MAX_PACKET_SIZE = 35000;
|
|
46
|
+
export const DEFAULT_WINDOW_SIZE = 0x8000;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain-specific errors and exception handling.
|
|
3
|
+
*/
|
|
4
|
+
export declare class SSHError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class KEXError extends SSHError {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class AuthenticationError extends SSHError {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class MacVerificationError extends SSHError {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class ProtocolError extends SSHError {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
export declare class ChannelError extends SSHError {
|
|
20
|
+
constructor(message: string);
|
|
21
|
+
}
|
|
22
|
+
export declare class ParseError extends SSHError {
|
|
23
|
+
constructor(message: string);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../domain/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,QAAS,SAAQ,KAAK;gBACrB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,QAAS,SAAQ,QAAQ;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,oBAAqB,SAAQ,QAAQ;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,YAAa,SAAQ,QAAQ;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,UAAW,SAAQ,QAAQ;gBAC1B,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain-specific errors and exception handling.
|
|
3
|
+
*/
|
|
4
|
+
export class SSHError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "SSHError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class KEXError extends SSHError {
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "KEXError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class AuthenticationError extends SSHError {
|
|
17
|
+
constructor(message) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = "AuthenticationError";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class MacVerificationError extends SSHError {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "MacVerificationError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export class ProtocolError extends SSHError {
|
|
29
|
+
constructor(message) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = "ProtocolError";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export class ChannelError extends SSHError {
|
|
35
|
+
constructor(message) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = "ChannelError";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export class ParseError extends SSHError {
|
|
41
|
+
constructor(message) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = "ParseError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain model value objects and entities.
|
|
3
|
+
* These represent core SSH protocol concepts.
|
|
4
|
+
*/
|
|
5
|
+
export interface Credentials {
|
|
6
|
+
username: string;
|
|
7
|
+
certificate: string;
|
|
8
|
+
privateKey: string;
|
|
9
|
+
}
|
|
10
|
+
export interface TerminalConfig {
|
|
11
|
+
cols: number;
|
|
12
|
+
rows: number;
|
|
13
|
+
termType: string;
|
|
14
|
+
}
|
|
15
|
+
export interface SessionId extends Readonly<{
|
|
16
|
+
readonly __brand: unique symbol;
|
|
17
|
+
}> {
|
|
18
|
+
readonly value: Uint8Array;
|
|
19
|
+
}
|
|
20
|
+
export interface ChannelId extends Readonly<{
|
|
21
|
+
readonly __brand: unique symbol;
|
|
22
|
+
}> {
|
|
23
|
+
readonly value: number;
|
|
24
|
+
}
|
|
25
|
+
export interface SequenceNumber extends Readonly<{
|
|
26
|
+
readonly __brand: unique symbol;
|
|
27
|
+
}> {
|
|
28
|
+
readonly value: number;
|
|
29
|
+
}
|
|
30
|
+
export interface EncryptionKey extends Readonly<{
|
|
31
|
+
readonly __brand: unique symbol;
|
|
32
|
+
}> {
|
|
33
|
+
readonly key: CryptoKey;
|
|
34
|
+
}
|
|
35
|
+
export interface MacKey extends Readonly<{
|
|
36
|
+
readonly __brand: unique symbol;
|
|
37
|
+
}> {
|
|
38
|
+
readonly key: Uint8Array;
|
|
39
|
+
}
|
|
40
|
+
export interface InitializationVector extends Readonly<{
|
|
41
|
+
readonly __brand: unique symbol;
|
|
42
|
+
}> {
|
|
43
|
+
readonly value: Uint8Array;
|
|
44
|
+
}
|
|
45
|
+
export type KexAlgorithm = "curve25519-sha256" | "curve25519-sha256@libssh.org" | "diffie-hellman-group14-sha256";
|
|
46
|
+
export type CipherAlgorithm = "aes128-ctr";
|
|
47
|
+
export type MacAlgorithm = "hmac-sha2-256" | "hmac-sha2-256-etm@openssh.com";
|
|
48
|
+
export interface AlgorithmNegotiation {
|
|
49
|
+
kex: KexAlgorithm;
|
|
50
|
+
cipher: CipherAlgorithm;
|
|
51
|
+
mac: MacAlgorithm;
|
|
52
|
+
}
|
|
53
|
+
export type SSHMessageType = number;
|
|
54
|
+
export declare const createSessionId: (data: Uint8Array) => SessionId;
|
|
55
|
+
export declare const createChannelId: (value: number) => ChannelId;
|
|
56
|
+
export declare const createSequenceNumber: (value: number) => SequenceNumber;
|
|
57
|
+
export declare const createEncryptionKey: (key: CryptoKey) => EncryptionKey;
|
|
58
|
+
export declare const createMacKey: (key: Uint8Array) => MacKey;
|
|
59
|
+
export declare const createInitializationVector: (value: Uint8Array) => InitializationVector;
|
|
60
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../domain/models.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAU,SAAQ,QAAQ,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;IAC9E,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B;AAED,MAAM,WAAW,SAAU,SAAQ,QAAQ,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAe,SAAQ,QAAQ,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;IACnF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAc,SAAQ,QAAQ,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;IAClF,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,MAAO,SAAQ,QAAQ,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;IAC3E,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAqB,SAAQ,QAAQ,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;IACzF,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B;AAED,MAAM,MAAM,YAAY,GAAG,mBAAmB,GAAG,8BAA8B,GAAG,+BAA+B,CAAC;AAClH,MAAM,MAAM,eAAe,GAAG,YAAY,CAAC;AAC3C,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,+BAA+B,CAAC;AAE7E,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,eAAe,CAAC;IACxB,GAAG,EAAE,YAAY,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,eAAO,MAAM,eAAe,GAAI,MAAM,UAAU,KAAG,SAA2C,CAAC;AAC/F,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,SAAqC,CAAC;AACtF,eAAO,MAAM,oBAAoB,GAAI,OAAO,MAAM,KAAG,cAA+C,CAAC;AACrG,eAAO,MAAM,mBAAmB,GAAI,KAAK,SAAS,KAAG,aAA2C,CAAC;AACjG,eAAO,MAAM,YAAY,GAAI,KAAK,UAAU,KAAG,MAA6B,CAAC;AAC7E,eAAO,MAAM,0BAA0B,GAAI,OAAO,UAAU,KAAG,oBAA2D,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain model value objects and entities.
|
|
3
|
+
* These represent core SSH protocol concepts.
|
|
4
|
+
*/
|
|
5
|
+
export const createSessionId = (data) => ({ value: data });
|
|
6
|
+
export const createChannelId = (value) => ({ value });
|
|
7
|
+
export const createSequenceNumber = (value) => ({ value });
|
|
8
|
+
export const createEncryptionKey = (key) => ({ key });
|
|
9
|
+
export const createMacKey = (key) => ({ key });
|
|
10
|
+
export const createInitializationVector = (value) => ({ value });
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API barrel export.
|
|
3
|
+
* Architecture: domain, crypto, protocol, transport, state machines (kex/auth/channel/connection), connection orchestrator.
|
|
4
|
+
*/
|
|
5
|
+
export { connectSSH } from "./connection/connectSSH";
|
|
6
|
+
export type { SSHConnection, ConnectSSHOptions, SSHCredentials } from "./connection/types";
|
|
7
|
+
export { SSHError, KEXError, AuthenticationError, MacVerificationError, ProtocolError, ChannelError, ParseError } from "./domain/errors";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API barrel export.
|
|
3
|
+
* Architecture: domain, crypto, protocol, transport, state machines (kex/auth/channel/connection), connection orchestrator.
|
|
4
|
+
*/
|
|
5
|
+
export { connectSSH } from "./connection/connectSSH";
|
|
6
|
+
export { SSHError, KEXError, AuthenticationError, MacVerificationError, ProtocolError, ChannelError, ParseError } from "./domain/errors";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../kex/builder.ts"],"names":[],"mappings":"AAMA,wBAAgB,YAAY,IAAI,UAAU,CAsBzC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds KEXINIT payload for client key exchange.
|
|
3
|
+
*/
|
|
4
|
+
import { writeString, writeUint32, concat } from "../protocol/serialization";
|
|
5
|
+
import { SSH_MSG_KEXINIT, PREFERRED_KEX, PREFERRED_CIPHER, PREFERRED_MAC } from "../domain/constants";
|
|
6
|
+
export function buildKexInit() {
|
|
7
|
+
const cookie = crypto.getRandomValues(new Uint8Array(16));
|
|
8
|
+
const macList = PREFERRED_MAC.split(",").map((s) => s.trim()).filter(Boolean);
|
|
9
|
+
const lists = [
|
|
10
|
+
PREFERRED_KEX,
|
|
11
|
+
"ssh-ed25519",
|
|
12
|
+
PREFERRED_CIPHER,
|
|
13
|
+
PREFERRED_CIPHER,
|
|
14
|
+
macList.join(","),
|
|
15
|
+
macList.join(","),
|
|
16
|
+
"none",
|
|
17
|
+
"none",
|
|
18
|
+
"",
|
|
19
|
+
"",
|
|
20
|
+
];
|
|
21
|
+
return concat(new Uint8Array([SSH_MSG_KEXINIT]), cookie, ...lists.map(writeString), new Uint8Array([0]), writeUint32(0));
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key exchange state machine.
|
|
3
|
+
* Manages KEX negotiation and algorithm selection.
|
|
4
|
+
*/
|
|
5
|
+
import { AlgorithmNegotiation } from "../domain/models";
|
|
6
|
+
export type KexPhase = "init" | "negotiating" | "exchanging" | "complete";
|
|
7
|
+
export interface KexState {
|
|
8
|
+
phase: KexPhase;
|
|
9
|
+
serverKexList: string[];
|
|
10
|
+
serverHostKeyTypes: string[];
|
|
11
|
+
negotiated: AlgorithmNegotiation | null;
|
|
12
|
+
kexInitC: Uint8Array | null;
|
|
13
|
+
kexInitS: Uint8Array | null;
|
|
14
|
+
}
|
|
15
|
+
export declare function createKexState(): KexState;
|
|
16
|
+
export declare function selectAlgorithm(ourList: string[], serverList: string[]): string | null;
|
|
17
|
+
export declare function negotiateAlgorithms(preferredKex: string[], preferredCipher: string[], preferredMac: string[], serverKex: string[], serverCipher: string[], serverMac: string[]): AlgorithmNegotiation | null;
|
|
18
|
+
export declare function isValidKex(kex: string): boolean;
|
|
19
|
+
export declare function transitionKexPhase(current: KexPhase): KexPhase;
|
|
20
|
+
//# sourceMappingURL=kexstate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kexstate.d.ts","sourceRoot":"","sources":["../../kex/kexstate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAA+C,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGrG,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,aAAa,GAAG,YAAY,GAAG,UAAU,CAAC;AAE1E,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,UAAU,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACxC,QAAQ,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,UAAU,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAgB,cAAc,IAAI,QAAQ,CASzC;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,MAAM,EAAE,GACnB,MAAM,GAAG,IAAI,CAEf;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EAAE,EACtB,eAAe,EAAE,MAAM,EAAE,EACzB,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,MAAM,EAAE,EACnB,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,MAAM,EAAE,GAClB,oBAAoB,GAAG,IAAI,CAM7B;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAI/C;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAQ9D"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function createKexState() {
|
|
2
|
+
return {
|
|
3
|
+
phase: "init",
|
|
4
|
+
serverKexList: [],
|
|
5
|
+
serverHostKeyTypes: [],
|
|
6
|
+
negotiated: null,
|
|
7
|
+
kexInitC: null,
|
|
8
|
+
kexInitS: null,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function selectAlgorithm(ourList, serverList) {
|
|
12
|
+
return ourList.find((a) => serverList.includes(a)) ?? null;
|
|
13
|
+
}
|
|
14
|
+
export function negotiateAlgorithms(preferredKex, preferredCipher, preferredMac, serverKex, serverCipher, serverMac) {
|
|
15
|
+
const kex = selectAlgorithm(preferredKex, serverKex);
|
|
16
|
+
const cipher = selectAlgorithm(preferredCipher, serverCipher);
|
|
17
|
+
const mac = selectAlgorithm(preferredMac, serverMac);
|
|
18
|
+
if (!kex || !cipher || !mac)
|
|
19
|
+
return null;
|
|
20
|
+
return { kex, cipher, mac };
|
|
21
|
+
}
|
|
22
|
+
export function isValidKex(kex) {
|
|
23
|
+
return kex === "curve25519-sha256" ||
|
|
24
|
+
kex === "curve25519-sha256@libssh.org" ||
|
|
25
|
+
kex === "diffie-hellman-group14-sha256";
|
|
26
|
+
}
|
|
27
|
+
export function transitionKexPhase(current) {
|
|
28
|
+
const transitions = {
|
|
29
|
+
"init": "negotiating",
|
|
30
|
+
"negotiating": "exchanging",
|
|
31
|
+
"exchanging": "complete",
|
|
32
|
+
"complete": "complete",
|
|
33
|
+
};
|
|
34
|
+
return transitions[current];
|
|
35
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface ParsedPacket {
|
|
2
|
+
payload: Uint8Array;
|
|
3
|
+
consumed: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function buildPacket(payload: Uint8Array, etm?: boolean): Uint8Array;
|
|
6
|
+
export declare function parsePacket(data: Uint8Array): ParsedPacket | null;
|
|
7
|
+
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../protocol/codec.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,UAAQ,GAAG,UAAU,CAUxE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,GAAG,IAAI,CASjE"}
|