- 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)
500 行
24 KiB
Markdown
500 行
24 KiB
Markdown
# 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 加密段) |