文件
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

500 行
24 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# 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`, 对外不透明)
```c
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`)
```c
#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](file:///F:/TLS-SSH/include/paze/paze_types.h)。
---
## 七、构建系统
顶层 [CMakeLists.txt](file:///F:/TLS-SSH/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)
```bash
# 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 门禁。
```c
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, 非本次引入)
11. ✅ tls_handshake12 (TLS 1.2 回退,ECDHE-RSA/ECDSA/RSA AES-GCM + CHACHA20-POLY1305;OpenSSL s_client/s_server 双向 1.2 互操作通过)
12. 🔶 X.509 self-signed 证书解析 — RSA 部分已修复(X.509 SPKI 外层 SEQUENCE 缺失问题), ECDSA 仍失败(p256_from_affine 曲线点验证不通过)
13. ⬜ X25519 ECDH 共享密钥不一致 (RFC 7748 标准测试向量不通过)
14. ✅ SSH 密钥解析 — paze_rsa_priv_from_pem / paze_ecdsa_priv_from_pem 已实现, tls_conn 私钥加载已更新
15. ⬜ TLS 1.3 密钥派生重放 (服务端收到 ClientHello 时若 cipher=SHA-384 需要重放 CH 到新 transcript,SHA-256 已覆盖)
16. ⬜ 最终验证:全量 `cloc`/`wc -l` 统计 + 所有 KAT 通过 + TLS 1.3 对公网 TLS 1.3 服务器握手测试
### 2026-08-11 新增功能
17. ✅ paze_x509_build_spki 修复:AlgorithmIdentifier + BIT STRING 现包裹在外层 SEQUENCE 中
18. ✅ paze_rsa_priv_from_pem / paze_rsa_pub_from_pem — RSA 密钥 PEM 加载
19. ✅ paze_ecdsa_priv_from_pem / paze_ecdsa_pub_from_pem — ECDSA 密钥 PEM 加载 (RFC 5915)
20. ✅ 多证书链 PEM 加载 (build_cert_chain_from_pem 支持多段)
21. ✅ 多信任锚 PEM 加载 (paze_tls_config_set_trust_roots 支持多根证书)
---
## 十一、安全编码原则
1. **常量时间**:
- 密钥 / IV / padding 比较必须走 `paze_memzero``paze_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 已如此实现)。
---
## 十二、引用
- TLS 1.3 — [RFC 8446](https://www.rfc-editor.org/rfc/rfc8446)
- TLS 1.2 — [RFC 5246](https://www.rfc-editor.org/rfc/rfc5246)
- AES-GCM — [NIST SP 800-38D](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf)
- ChaCha20-Poly1305 — [RFC 8439](https://www.rfc-editor.org/rfc/rfc8439)
- HKDF — [RFC 5869](https://www.rfc-editor.org/rfc/rfc5869)
- X.509 & PKIX — [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280)
- SSH 协议族 — [RFC 4250~4256](https://www.rfc-editor.org/rfc/rfc4250)
所有代码一定要能移植到裸机上!
---
## 十三、构建命令(已验证)
```bash
# 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.com、aes128/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 加密段)