文件
PazeSSH/AGENT.MD
T
JGZYES 6da27731b5 实现 TLS 1.2 握手与版本回退,修复 GCM 记录层 RFC 偏差
- tls_handshake12.c: 完整 TLS 1.2 client/server 状态机(ECDHE-RSA/ECDSA/RSA AES-GCM + CHACHA20-POLY1305),支持 1.3 收到 1.2 ServerHello/ClientHello 后回退
- tls_record.c: 修正 TLS 1.2 AEAD-GCM 两处 RFC 偏差: AAD length 字段应为明文长度 ctlen(RFC 5246 6.2.3.3)原为 ct+16; GCMNonce = fixed_iv(4) || explicit_nonce(8)(RFC 5288 3)原顺序相反
- tls_handshake13.c: CV/Finished transcript 处理、1.3 套件记录版本修正、链式证书构造
- x509.c: AttributeTypeAndValue 补 SEQUENCE; validity 2050 年前用 UTCTime
- apps/pazessl: s_client/s_server 增加 -tls1_2
- 新增 build.ps1、build/run_tls_test.ps1、build/run_openssl_interop.ps1

验证: 自测 4/4(1.2/1.3 双向 + 回退); OpenSSL 互操作 4/4(s_client/s_server 双向 1.2/1.3)
2026-08-13 17:30:31 +08:00

24 KiB
原始文件 Blame 文件历史

PazeSSL / PazeSSH 项目代理规范 (AGENT.MD)

版本: v0.5 (2026-08-13) — TLS 1.2 完成(版本回退 + OpenSSL 互操作 4/4+ X.509 RSA round-trip 修复 + PEM 密钥加载 + 多证书链支持 目标: 用纯 libc + 自底向上 C 语言实现 OpenSSL(平替 PazeSSL) ≤ 100,000 行OpenSSH(平替 PazeSSH) ≤ 30,000 行约束: 仅使用libc 要能在裸机上实现,禁止依赖 OpenSSL / LibreSSL / libcrypto / mbedTLS / libgcrypt / libssh 等外部密码学或协议库。


一、总体架构

┌─────────────────────────────────────────────────────────────────┐
│                        apps/  CLI 层                             │
│   pazessl/     SSH/     sshd/                                    │
│   (s_client/s_server  s_time  verify  x509) (ssh client) (sshd) │
├──────────┬──────────────────────────────────────────────────────┤
│ src/ssl  │ src/ssh                                              │
│ 100k预算 │ 30k预算                                              │
│          │                                                      │
│  tls_bio           │  ssh_packet  (binary packet 二进制包层)    │
│  tls_record        │  ssh_transport (transport layer 传输层)    │
│  tls_transcript    │  ssh_kex       (密钥交换)                  │
│  tls_keys          │  ssh_keys      (主机键/公钥)                │
│  tls_extensions    │  ssh_auth      (用户认证:pw/pk/hostbased)  │
│  tls_handshake13   │  ssh_channel   (会话/shell/exec 通道)      │
│  tls_handshake12   │  ssh_client    (客户端入口)                 │
│  tls_client        │  ssh_server    (sshd 入口)                 │
│  tls_server        │                                              │
│  tls_conn          │                                              │
├──────────┴──────────────────────────────────────────────────────┤
│                       src/crypto  (≈7000 行,已完成)              │
│  hash (SHA1/224/256/384/512, MD5)                                │
│  HMAC / HKDF / PBKDF2                                            │
│  AES-128/256 (ECB/CBC/CTR/GCM)  AEAD                            │
│  ChaCha20 / Poly1305 / ChaCha20-Poly1305 AEAD                    │
│  bignum (Montgomery 模幂 / 模乘 / 模逆,最大 512 limb=2KB)         │
│  RSA  PKCS#1 v1.5 + PSS (加密/解密/签名/验签/CRT私钥/密钥生成)    │
│  X25519 (曲线25519蒙哥马利梯)  Ed25519 (EdDSA)                   │
│  P-256 (secp256r1 Jacobian 点运算, ECDSA)                        │
│  ASN.1 DER 读写器 / PEM 编解码 / Base64 / Hex                     │
│  X.509 v3 (DER/PEM 解析、签名验证、链验证、SAN、自签生成)           │
├─────────────────────────────────────────────────────────────────┤
│  src/util (mem/error/log/version) + include/paze/*.h             │
├─────────────────────────────────────────────────────────────────┤

二、行数预算(严格上限)

层级 / 模块 预算 已完成(2026-08-12) 状态
crypto + util + include ≤ 10,000 6,510 完成(含 fe25519.c)
src/ssl (PazeSSL/TLS) ≤ 60,000 2,328 TLS 1.3 完成 (extensions/handshake13/client/server/conn)
src/ssh (PazeSSH/SSH2) ≤ 25,000 3,779 SSH2 全部模块完成 (packet/transport/kex/keys/auth/channel/client/server/scp/agent)
apps/ ≤ 3,000 1,839 pssh 单可执行(ssh/keygen/keyscan/copy-id/agent/add/sshd/scp) + pazessl
tests/ ≤ 2,000 1,688 paze_kat 统一测试 + 11 个独立 KAT 可执行程序
合计 ≤ 100,000 16,144 83,856 剩余

关键红线:

  • SSL 部分(src/ssl + include/paze/tls.h)绝对不可超过 60,000 行
  • SSH 部分(src/ssh)绝对不可超过 25,000 行
  • 任一模块若超限,必须精简:移除冷门特性、压缩 verbose 日志、合并小函数。

三、TLS 模块设计 (PazeSSL)

3.1 公共 API (include/paze/tls.h, 对外不透明)

typedef struct paze_tls_config paze_tls_config_t;
typedef struct paze_tls paze_tls_t;

// 配置
cfg = paze_tls_config_new(PAZE_TLS_CLIENT | PAZE_TLS_SERVER);
paze_tls_config_set_sni(cfg, "example.com");
paze_tls_config_set_alpn(cfg, {"h2","http/1.1"}, 2);
paze_tls_config_set_cert_chain(cfg, cert_pem, privkey_pem);  // server
paze_tls_config_set_trust_roots(cfg, roots_pem);             // client
paze_tls_config_set_verify(cfg, PAZE_TLS_VERIFY_REQUIRED, verify_cb, ctx);
paze_tls_config_set_versions(cfg, 1, 1);  // 1.3 + 1.2 (默认)
paze_tls_config_free(cfg);

// 连接
tls = paze_tls_new(cfg);
paze_tls_set_bio(tls, (paze_tls_bio_t){ctx, read_fn, write_fn});
paze_status_t s = paze_tls_handshake(tls);       // 阻塞循环调用
int  n = paze_tls_read(tls, buf, buflen);
int  n = paze_tls_write(tls, buf, n);
paze_tls_close(tls);
paze_tls_free(tls);

3.2 内部模块(已完成 + 待办)

文件 状态 说明
tls.h 完成 公共头:类型、cipher suite、常量、API
tls_internal.h 完成 内部头:paze_tls_t 全字段、各模块共享原型
tls_bio.c 完成 BIO read/write 阻塞循环封装
tls_record.c 完成 1.3 AEAD(iv xor seq) + 1.2 AEAD-GCM(explicit nonce+seq)
tls_transcript.c 完成 Transcript hash + HRR 合成 MessageHash
tls_keys.c 完成 HKDF-Expand-Label / Derive-Secret / 1.3 key schedule / 1.2 PRF / cipher_params
tls_extensions.c 完成 SNI/ALPN/key_share/supported_groups/sig_algos/supported_versions/renegotiation_info 编码+解析
tls_handshake13.c 完成 TLS 1.3 client+server 状态机:ClientHello/ServerHello/EncryptedExtensions/Certificate/CertificateVerify/Finished (无 PSK/0-RTT)
tls_handshake12.c 完成 TLS 1.2 client+server 状态机:ServerHello/Certificate/ServerKeyExchange/CKE/CCS/Finished;含 1.3↔1.2 回退
tls_client.c 完成 客户端证书验证辅助:链验证+主机名匹配
tls_server.c 完成 服务端证书有效性检查
tls_conn.c 完成 paze_tls_t 生命周期(new/free/set_bio/read/write/close/handshake)

3.3 TLS 1.3 握手消息(关键编码,必须严格遵循 RFC 8446)

ClientHello
  legacy_version(2)=0x0303, random(32), legacy_session_id(0..32),
  cipher_suites(2+n), legacy_compression_methods(1+{0}), extensions(2+n)
  EXT: supported_versions(客户端 0x0304/0x0303)
  EXT: supported_groups(X25519 + secp256r1)
  EXT: signature_algorithms(ecdsa_secp256r1_sha256 / rsa_pss_rsae_sha256 / rsa_pkcs1_sha256)
  EXT: key_share(2+ (group 2 + len 2 + key_exchange) × N)
  EXT: server_name(host_type=0)
  EXT: application_layer_protocol_negotiation
  EXT: renegotiation_info(空)

ServerHello(1.3):
  legacy_version=0x0303, random, legacy_session_id_echo(同 CH),
  cipher_suite, legacy_compression_method=0, extensions
  EXT: supported_versions(选中 0x0304)
  EXT: key_share(服务器选中的 share)

EncryptedExtensions: extensions(任意非握手相关)
Certificate [Request]:
  request_context(0/1 bytes) + cert_list(证书序列)
  CertificateEntry: cert_data(3+n) + extensions(2+n,含 status_request/OCSP)
CertificateVerify: algorithm(2) + signature(2+n)
  签名内容: "TLS 1.3, server CertificateVerify" + 0x20 × 64 + 0x04 + Transcript-Hash
Finished: verify_data = HMAC(finished_key, Transcript-Hash)

3.4 关键 AEAD / Key Schedule 不变量

  • TLS 1.3 nonce: iv[0..11] XOR (00000000 || seq_be64),不重复使用
  • TLS 1.3 AAD: type || 0x0303 || (plaintext_len+16)
  • TLS 1.2 AAD: seq(8) || type || version || (明文长度),explicit nonce(8) 写在记录 body 开头,nonce = fixed_iv(4) || explicit_nonce(8)(RFC 5288 §3 GCMNonce),fixed_iv=key_material 中 write_IV(4 字节)。
  • Transcript: 每次发送/收到握手消息后,连同 4 字节握手头一并 update。
  • HRR 回退:调用 paze_tls_tr_reset_to_synthetic() 重置 transcript 为 MessageHash(Hash(CH1)),随后 HRR、CH2、SH… 追加其 后。
  • PSS/RSA-PKCS1 签名:由 paze_rsa_pss_sign / paze_rsa_pkcs1_sign 直接产出 signature 字节流。
  • 证书链验证:调用 paze_x509_verify_chain(peer_chain[], chain_len, anchors[], anchor_count, now);之后 paze_x509_match_host(leaf, sni)

四、SSH 模块设计 (PazeSSH, ≤25,000 行)

4.1 协议栈(对应源文件)

┌──────────────────────────────────────────┐
│ apps/ssh  / apps/sshd  (CLI)            │
├──────────────────────────────────────────┤
│ src/ssh/ssh_client.c  /  ssh_server.c   │  ← 入口(connect/listen→accept→loop)
│          └── ssh_auth.c                  │  ← 用户认证(pubkey/password/hostbased)
│          └── ssh_channel.c               │  ← 通道建立(session/shell/exec/pty)
│          └── ssh_kex.c                   │  ← 密钥交换 (curve25519-sha256@libssh.org,ecdh-sha2-nistp256)
│          └── ssh_transport.c             │  ← 二进制包加密/解密、重加密、Mac/压缩、序号
│          └── ssh_packet.c                │  ← 打包:uint32(长度) + padl(1) + payload + padding + mac
│          └── ssh_keys.c                  │  ← 主机键 RSA/Ed25519/ECDSA P256 加载+签名+验签
└──────────────────────────────────────────┘

4.2 密码学兼容性

  • kex methods:curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group14-sha256(仅兼容,不建议启用)
  • host key algorithms:ssh-ed25519,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256
  • encryption:chacha20-poly1305@openssh.com,aes128-gcm@openssh.com,aes256-gcm@openssh.com
  • MAC(非 AEAD):hmac-sha2-256
  • key format:ssh-rsa / ssh-ed25519 / ecdsa-sha2-nistp256 公钥格式 + PEM 私钥
  • packet size:packet.c 中 uint32 block_size 依 cipher 动态设置

4.3 行数分配建议

文件 预算 核心功能 状态
ssh_packet.c 600 uint32 打包解包、padding、AEAD 加密/解密、序列号递增、mac 校验、Factory 函数
ssh_transport.c 1,200 版本交换、KEXINIT 协商、算法名列表解析
ssh_keys.c 1,500 主机键加载(PEM)、公钥 blob 格式、签名 verify/sign (Ed25519/ECDSA/RSA)
ssh_kex.c 1,800 X25519/P-256 ECDH 交换、密钥派生(ChaCha20-Poly1305/256 bit keys)、NEWKEYS
ssh_auth.c 2,000 USERAUTH_REQUEST/FAILURE/SUCCESS; password authentication
ssh_channel.c 2,500 CHANNEL_OPEN/CONFIRM/DATA/REQUEST/CLOSE; session/shell/exec/pty-req
ssh_client.c 1,000 TCP connect → transport_loop → auth → channel shell/exec
ssh_server.c 1,500 listen → accept → transport → auth → channel pty+shell (echo 测试)
小计 ≈ 12,100 全部 8 模块完成

五、密码学原语清单(已完整实现,勿重复)

——哈希
  paze_sha1, paze_sha256, paze_sha384, paze_sha512, paze_md5
  通用描述符: paze_hash_sha256() 等 (含 digest_len/block_len/ctx_size/init/update/final)

——密钥派生
  paze_hmac(alg, key, msg)      / 流式 hmac_init/update/final
  paze_hkdf_extract / expand / paze_hkdf
  paze_pbkdf2

——对称 AEAD
  paze_aes128/256_init + aesgcm_encrypt/decrypt      (12 字节 nonce, 16 字节 tag)
  paze_chacha20poly1305_encrypt/decrypt               (RFC 8439, 12 字节 nonce, 32 字节 key)
  AES ECB/CBC/CTR 模式(低层次,仅特殊场景用)

——椭圆曲线
  curve25519:  paze_curve25519_scalar_mult(pub, priv, basepoint_or_pubkey)
  Ed25519:     paze_ed25519_publickey / sign / verify (RFC 8032, SHA-512)
  P-256:       paze_p256_scalar_mult(R, k, P) / from_affine / to_affine / paze_ecdsa_sign / verify

——大整数 / RSA
  paze_bn_t (最多 PAZE_BN_MAX_LIMBS 个 32-bit limb)  加减乘除 模  Montgomery 模幂 modexp
  RSA: paze_rsa_pub_from_der / priv_from_pem?
       paze_rsa_pkcs1_encrypt/decrypt/sign/verify
       paze_rsa_pss_sign/verify
       paze_rsa_gen(&priv, bits) —— 密钥生成(Miller-Rabin 素性检测)

——ASN.1 + X.509
  paze_asn1_reader_t: enter_seq / read_tl / at_end / 基本类型 ASN1_* tag 常量
  paze_x509_parse_der / parse_pem / free
  paze_x509_verify_signature(cert, issuer)
  paze_x509_verify_chain(chain[], chain_len, anchors[], anchor_count, now_unix_seconds)
  paze_x509_check_validity / match_host(host)      ← SAN dNSName 支持通配?不支持(严格)
  paze_x509_make_self_signed(out, outlen, signer, CN, not_before, not_after)   ← 测试用

——编码
  paze_base64_encode/decode, paze_hex_encode/decode, paze_pem_encode/decode

六、跨平台 Socket + BIO 约定

6.1 apps 层的 BIO 构造(Windows + POSIX 同文件,用 #if _WIN32)

#ifdef _WIN32
#include <winsock2.h>
typedef SOCKET sock_t;
#define INVALID INVALID_SOCKET
#else
#include <unistd.h>
#include <sys/socket.h>
typedef int sock_t;
#define INVALID (-1)
#endif

static int sock_read(void *ctx, uint8_t *buf, size_t n) {
    sock_t s = *(sock_t*)ctx;
    return (int)recv(s, (char*)buf, (int)n, 0);    // WIN/UNIX 同签名
}
static int sock_write(void *ctx, const uint8_t *buf, size_t n) {
    sock_t s = *(sock_t*)ctx;
    return (int)send(s, (char*)buf, (int)n, 0);
}

paze_tls_bio_t bio = { &sock, sock_read, sock_write };
paze_tls_set_bio(tls, bio);

6.2 错误码统一

  • PAZE_ERR_IO(-8): 底层 BIO 出错,不 retry
  • PAZE_ERR_VERIFY(-5): 验签失败 / record MAC 错误 / 证书不可信。
  • PAZE_ERR_PROTOCOL(-10): 协议消息格式错误。
  • 其他负数按 paze_types.h

七、构建系统

顶层 CMakeLists.txt 已规划静态库:

paze_crypto  ← src/crypto + src/util
paze_ssl     ← src/ssl/*.c (链接 paze_crypto)
paze_ssh     ← src/ssh/*.c (链接 paze_crypto)
CLI: pazessl, paze-ssh, paze-sshd
TESTS: paze_kat (tests/kat.c)

构建命令 (Windows MinGW/GCC 或 MinGW-w64 / Unix GCC / Clang)

# Linux / macOS
mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc) && ctest

# Windows (MSVC)
mkdir build && cd build
cmake ..
cmake --build . --config Release && ctest -C Release

八、CLI 工具 (apps/)

pazessl (平替 openssl s_client / s_server / s_time / x509 / verify)

pazessl s_client -connect <host:port> [-CAfile roots.pem] [-servername SNI] [-alpn h2,http1.1]
pazessl s_server  -accept <port>    -cert cert.pem -key key.pem [-CAfile roots.pem]
pazessl verify    -CAfile roots.pem cert.pem
pazessl x509      -in cert.pem      [-text] [-noout]
pazessl s_time    -connect <host:port> [-seconds 10]
pazessl genrsa    -out key.pem  [2048|4096]
pazessl req       -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -subj /CN=test

paze-ssh (平替 ssh)

paze-ssh [-p port] [-i key.pem] [-l user] host [command]

paze-sshd (平替 sshd)

paze-sshd -p 22 -h host_key_ed25519.pem [-h host_key_rsa.pem] \
          -f authorized_keys_dir   # 目录下 $user/.ssh/authorized_keys

九、统一 KAT 测试 (tests/kat.c)

paze_kat 二进制须全部通过,作为 CI 门禁。

int main(void) {
    int ok = 1;
    ok &= test_sha2_vectors();     // NIST 向量
    ok &= test_aes_gcm_vectors();  // NIST SP 800-38D
    ok &= test_chacha20_poly();    // RFC 8439
    ok &= test_rsa_2048_roundtrip();
    ok &= test_ecdsa_p256_kat();
    ok &= test_ed25519_rfc8032();
    ok &= test_x25519_rfc7748();
    ok &= test_hkdf_rfc5869();
    ok &= test_pbkdf2_rfc6070();
    ok &= test_x509_self_rsa();
    ok &= test_x509_self_ecdsa();
    ok &= test_tls13_self_handshake();   // ← 新: 内建回环测试
    ok &= test_ssh_kex_loopback();       // ← 新
    printf("KAT %s\n", ok ? "PASS" : "FAIL");
    return ok ? 0 : 1;
}

十、遗留 TO-DO(完成顺序)

按依赖顺序:TLS extensions → handshake13 → conn → tests → SSH 全部 → CLI → verify

  1. 密码学原语 + X.509
  2. tls.h + tls_internal.h
  3. tls_bio / tls_record / tls_transcript / tls_keys
  4. tls_extensions (write + parse)
  5. tls_handshake13 (客户端 + 服务端状态机,无 PSK/0-RTT/HRR 实际数据)
  6. tls_client / tls_server / tls_conn (握手入口、证书验证、连接 API、应用读写)
  7. SSH 全部 (ssh_packet/transport/kex/keys/auth/channel/client/server)
  8. apps/ (pazessl s_client/s_server/verify/genrsa/req/x509 + paze-ssh + paze-sshd)
  9. tests/kat.c (SHA-256/X25519/Ed25519/RSA/X.509/TLS/SSH 测试)
  10. 全量构建:所有 3 个静态库 + 4 个 CLI 程序 + 12 个测试程序通过编译

遗留问题 (pre-existing, 非本次引入)

  1. tls_handshake12 (TLS 1.2 回退,ECDHE-RSA/ECDSA/RSA AES-GCM + CHACHA20-POLY1305;OpenSSL s_client/s_server 双向 1.2 互操作通过)
  2. 🔶 X.509 self-signed 证书解析 — RSA 部分已修复(X.509 SPKI 外层 SEQUENCE 缺失问题), ECDSA 仍失败(p256_from_affine 曲线点验证不通过)
  3. X25519 ECDH 共享密钥不一致 (RFC 7748 标准测试向量不通过)
  4. SSH 密钥解析 — paze_rsa_priv_from_pem / paze_ecdsa_priv_from_pem 已实现, tls_conn 私钥加载已更新
  5. TLS 1.3 密钥派生重放 (服务端收到 ClientHello 时若 cipher=SHA-384 需要重放 CH 到新 transcript,SHA-256 已覆盖)
  6. 最终验证:全量 cloc/wc -l 统计 + 所有 KAT 通过 + TLS 1.3 对公网 TLS 1.3 服务器握手测试

2026-08-11 新增功能

  1. paze_x509_build_spki 修复:AlgorithmIdentifier + BIT STRING 现包裹在外层 SEQUENCE 中
  2. paze_rsa_priv_from_pem / paze_rsa_pub_from_pem — RSA 密钥 PEM 加载
  3. paze_ecdsa_priv_from_pem / paze_ecdsa_pub_from_pem — ECDSA 密钥 PEM 加载 (RFC 5915)
  4. 多证书链 PEM 加载 (build_cert_chain_from_pem 支持多段)
  5. 多信任锚 PEM 加载 (paze_tls_config_set_trust_roots 支持多根证书)

十一、安全编码原则

  1. 常量时间:
    • 密钥 / IV / padding 比较必须走 paze_memzeropaze_ct_equal
    • RSA PKCS1-v1_5 解密必须用累积 diff 而非早退(已在 rsa.c 中实现)。
  2. 缓冲区边界:每个 memcpy 前必须显式校验长度,不得假设 rlen ≤ MAX_RECORD
  3. 序列号溢出:若 seq == UINT64_MAX - 1(实际上不会到),需发 KeyUpdate 或关连接。
  4. 错误信息:不得泄漏内部状态;对外仅返回状态码,调试信息只写入 paze_log(DEBUG)
  5. 内存清零:所有密钥材料(handshake_secret/master_secret/private keys)使用完毕后 paze_memzero
  6. RSA PKCS1 长度校验:验签前严格重构 expected EM,整段常量时间比较(rsa.c 已如此实现)。

十二、引用

所有代码一定要能移植到裸机上!


十三、构建命令(已验证)

# Windows (Clang/MinGW via CMake):
mkdir build && cd build
cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_C_FLAGS="-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_WINSOCK_DEPRECATED_NO_WARNINGS"
make -j$(nproc)

# 运行测试
./paze_kat.exe
ctest

# Linux / macOS
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc) && ctest

注意: Windows 上需要 -D_CRT_SECURE_NO_WARNINGS 等宏以抑制 MSVC 运行时对 strcpy/strdup/gethostbyname 的废弃警告。

  • src/crypto/fe25519.c 已在 CMakeLists.txt 中(2026-08-11 补充,原遗漏)
  • strcasecmp 在 Windows 上为 _stricmp,已在 tests/bn_check.c 添加 compat 宏

十四、现有代码行数统计 (2026-08-12)

全量统计 src/ + include/ + apps/ + tests/*.c/*.h(93 + 18 = 111 个文件):

目录 行数 说明
src/crypto 4,938 哈希/AES/ChaCha20/曲线/RSA/X.509/ASN.1
src/ssh 3,779 packet/transport/kex/keys/auth/channel/client/server/scp/agent
src/ssl 2,328 TLS 1.3 握手/记录/密钥派生
include/paze 1,453 公共头
src/util 77 mem/error/log/version
include 42 顶层头
apps 1,839 pssh(8 子命令) + pazessl
tests 1,688 KAT 测试
合计 16,144 预算 ≤ 100,000,剩余 83,856

十五、pssh 与 OpenSSH 对比

命令对应

OpenSSH pssh 说明
ssh pssh(默认)/ pssh ssh 远程 shell / 执行命令
scp pssh scp 文件传输(SFTP 子系统优先,兼容 OpenSSH 9.x;回退 legacy SCP)
sftp pssh sshd 子系统 服务端 SFTP 子系统 v3,与 OpenSSH sftp/scp -s 互操作
ssh-keygen pssh keygen 密钥生成(ed25519/rsa/ecdsa)
ssh-keyscan pssh keyscan 主机密钥扫描(known_hosts 格式)
ssh-copy-id pssh copy-id 安装公钥到 authorized_keys
ssh-agent pssh agent agent 守护进程
ssh-add pssh add / pssh ssha agent 密钥管理
sshd pssh sshd SSH 服务器(多用户库 + 权限控制)

认证与加密算法

项目 OpenSSH pssh
密码认证 ✓(交互 * 掩码 / -pwd)
publickey 认证 ✓(-i 私钥 + agent 签名)
agent 代理认证 ✓(Windows 命名管道 \\.\pipe\openssh-ssh-agent)
密钥交换 curve25519/ECDH/DH/sntrup761 等 curve25519-sha256@libssh.org(X25519)
主机密钥 ed25519/rsa/ecdsa/dsa ed25519/rsa/ecdsa
加密算法 chacha20-poly1305、aes*-ctr、aes*-gcm 等 chacha20-poly1305@openssh.comaes128/256-gcm@openssh.com
私钥格式 openssh-key-v1(可 passphrase 加密) openssh-key-v1(无加密)
私钥指纹 SHA256/MD5 SHA256

功能对比

功能 OpenSSH pssh
交互 shell + 方向键历史 ✓(UTF-8 中文正常)
远程执行命令
known_hosts 校验 ✓(yes/no/accept-new) ✓(同)
SCP 协议 legacy + SFTP 模式(9.x 默认) 仅 legacy SCP
递归目录传输 -r
保留时间戳 -p
端口转发 -L/-R ✓(实测 HTTP 200)
动态转发/SOCKS5 -D ✓(实测代理 HTTP 200)
代理跳转 -J ✓(多级跳转 + 退出码透传)
config 文件 ✓(~/.ssh/config) ✓(~/.pssh/config.conf)
服务器端 完整(用户库/子系统/authorized_keys) 多用户库 + 分级权限(guest/user/admin) + authorized_keys 公钥认证
服务器端 exec/shell ✓(真正执行本地命令,stdout/stderr/exit-status 回传)
服务器端 direct-tcpip ✓(出站连接 + 双向中继,需 admin 权限)

主要差距(后续建议)

  1. 私钥 passphrase 加密(openssh-key-v1 AES 加密段)