Skip to main content

encryption/
contract.rs

1// Copyright (c) 2026 erik <erik@erik.xyz> — https://erik.xyz
2
3//! 能力契约(trait):业务层唯一需要依赖的东西。
4//!
5//! 对应 PHP 版的 `Contract/` 命名空间。PHP 里 `EncryptorInterface` 是
6//! `SymmetricCipherInterface` 的别名,Rust 侧只保留一个 [`SymmetricCipher`]。
7
8use crate::error::Result;
9
10/// 任何可注册进注册表的能力都带一个稳定标识(如 `aes-256-gcm`)。
11pub trait Identified {
12    fn identifier(&self) -> &str;
13}
14
15impl<T: Identified + ?Sized> Identified for Box<T> {
16    fn identifier(&self) -> &str {
17        (**self).identifier()
18    }
19}
20
21/// 对称加密:同一实例绑定固定密钥,对二进制载荷加解密。
22pub trait SymmetricCipher: Identified + Send + Sync {
23    fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>>;
24
25    fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>>;
26}
27
28/// 非对称加密:每次调用传入密钥材料(十六进制,格式由实现决定,如 SM2)。
29pub trait AsymmetricCipher: Identified + Send + Sync {
30    /// 返回十六进制密文。
31    fn encrypt(&self, plaintext: &[u8], public_key_hex: &str) -> Result<String>;
32
33    fn decrypt(&self, ciphertext_hex: &str, private_key_hex: &str) -> Result<Vec<u8>>;
34}
35
36/// 哈希:单向摘要,无密钥。
37pub trait Hasher: Identified + Send + Sync {
38    fn digest(&self, data: &[u8]) -> Result<Vec<u8>>;
39
40    /// 十六进制摘要;实现只需要实现 [`Hasher::digest`]。
41    fn digest_hex(&self, data: &[u8]) -> Result<String> {
42        Ok(crate::internal::hex_encode(&self.digest(data)?))
43    }
44}
45
46/// 基于密钥材料的派生(典型为 HKDF):从 IKM + salt + info 得到任意长度输出。
47pub trait KeyDerivation: Identified + Send + Sync {
48    /// `ikm`:输入密钥材料(如主密钥、DH 共享秘密);
49    /// `salt`:盐值(可为空,但建议非空随机);
50    /// `info`:可选上下文信息(如协议标签)。
51    fn derive(&self, ikm: &[u8], salt: &[u8], length: usize, info: &[u8]) -> Result<Vec<u8>>;
52}
53
54/// 基于口令的密钥派生(典型为 PBKDF2):从人类可读口令得到固定长度密钥。
55pub trait PasswordBasedKdf: Identified + Send + Sync {
56    /// `salt`:随机盐(建议每用户 / 每密钥唯一)。
57    fn derive_from_password(&self, password: &[u8], salt: &[u8], length: usize) -> Result<Vec<u8>>;
58}
59
60/// 签名:消息签名与验签。密钥与签名均为十六进制,格式由实现决定
61/// (本项目内统一:ECDSA / SM2 为定长 `r‖s`,Ed25519 为 64 字节定长)。
62pub trait Signer: Identified + Send + Sync {
63    /// 对消息签名,返回十六进制签名(失败不为原因分类)。
64    fn sign(&self, message: &[u8], private_key_hex: &str) -> Result<String>;
65
66    /// 验签;失败与格式错误一律 [`crate::error::Error::VerificationFailed`](不区分原因)。
67    fn verify(&self, message: &[u8], signature_hex: &str, public_key_hex: &str) -> Result<()>;
68}
69
70/// 密钥协商:以己方私钥与对方公钥导出共享秘密(ECDH / X25519)。
71pub trait KeyAgreement: Identified + Send + Sync {
72    /// 返回定长共享秘密的十六进制(长度由实现决定,如 X25519 为 64 位十六进制)。
73    ///
74    /// 共享秘密是**原始 DH 输出**,不应直接当密钥使用:请先经 KDF 派生
75    /// (本库自带 [`KeyDerivation`] / HKDF)。
76    fn agree(&self, private_key_hex: &str, peer_public_key_hex: &str) -> Result<String>;
77}
78
79/// 密钥封装(KEM,FIPS 203 ML-KEM):公钥封装 → (密文, 共享密钥);私钥解封装。
80/// 公钥、私钥、密文与共享密钥均为十六进制。
81pub trait KeyEncapsulation: Identified + Send + Sync {
82    /// 生成密钥对,返回 `(公钥 hex, 私钥 hex)`。
83    fn generate(&self) -> Result<(String, String)>;
84
85    /// 用公钥封装,返回 `(密文 hex, 共享密钥 hex)`。
86    fn encapsulate(&self, public_key_hex: &str) -> Result<(String, String)>;
87
88    /// 用私钥解封装,返回共享密钥 hex。
89    /// 注意:ML-KEM 对非法密文执行隐式拒绝(不报错,返回与封装端不同的
90    /// 伪随机密钥),这是标准行为,不视为错误。
91    fn decapsulate(&self, ciphertext_hex: &str, private_key_hex: &str) -> Result<String>;
92}