Skip to main content

ferritls_rustls/
verify.rs

1//! 证书/握手签名验证算法(rustls-webpki 经由
2//! `rustls::crypto::WebPkiSupportedAlgorithms` 消费)。
3//!
4//! 注意:TLS 1.3 对每个 scheme 只取 `mapping` 的**第一个**算法,
5//! TLS 1.2 会尝试全部——当前映射 1:1;若 M8 需要跨曲线容错
6//! (同 scheme 兼容 P-256/P-384 验证器,rustls-rustcrypto 的做法),
7//! 在此扩展即可。
8//!
9//! `public_key_alg_id()` / `signature_alg_id()` 的字节语义(pki-types
10//! 1.15 实测,以 `src/data/alg-*.der` 与 rustls-webpki 的比对逻辑为准):
11//! 返回 **AlgorithmIdentifier 的 SEQUENCE 内容**(即内层 TLV 序列,不带
12//! 外层 `30 xx` 头)——webpki 用 `der::expect_tag` 剥掉外层后逐字节比对。
13//! 注意与 RSA 相关的 NULL 参数是内容的一部分,必须保留:
14//! - EC:公钥 = ecPublicKey OID + 命名曲线 OID;签名 = ecdsa-with-SHA*
15//!   (RFC 5758:不带 NULL 参数);
16//! - Ed25519:公钥/签名同 OID(1.3.101.112,无参数);
17//! - RSA PKCS#1:公钥 = rsaEncryption + NULL;签名 = sha*WithRSA + NULL;
18//! - RSA-PSS:公钥同 RSA;签名 = RSASSA-PSS OID + PSS 参数
19//!   (RFC 4055:hash/MGF1-SHA*/salt=哈希长)。
20//!
21//! `verify_signature` 的 `public_key` 参数语义(rustls-webpki 0.103.x
22//! `signed_data.rs` 实测):webpki 传入的是 **subjectPublicKey 的
23//! BIT STRING 内容(key_value)**——即裸密钥本体(RSA = 裸
24//! `RSAPublicKey` DER;EC = 未压缩 SEC1 点;Ed25519 = 32 字节裸
25//! 公钥),**不含** SPKI/AlgorithmIdentifier 包装。ferritls-core
26//! 的 `VerifyKey` 构造器即按该裸格式定义,此处直接透传。
27
28use rustls::SignatureScheme;
29use rustls::crypto::WebPkiSupportedAlgorithms;
30use rustls::pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm};
31
32use ferritls_core::sign::{ecdsa, ed25519, rsa};
33
34macro_rules! verifier {
35    ($name:ident, $pk_alg_id:expr, $sig_alg_id:expr, $verify:expr, $doc:expr) => {
36        #[doc = $doc]
37        #[derive(Debug)]
38        pub struct $name;
39
40        impl SignatureVerificationAlgorithm for $name {
41            fn verify_signature(
42                &self,
43                public_key: &[u8],
44                message: &[u8],
45                signature: &[u8],
46            ) -> Result<(), InvalidSignature> {
47                $verify(public_key, message, signature).map_err(|_| InvalidSignature)
48            }
49
50            fn public_key_alg_id(&self) -> AlgorithmIdentifier {
51                AlgorithmIdentifier::from_slice($pk_alg_id)
52            }
53
54            fn signature_alg_id(&self) -> AlgorithmIdentifier {
55                AlgorithmIdentifier::from_slice($sig_alg_id)
56            }
57
58            fn fips(&self) -> bool {
59                // 认证前恒 false(lib.rs“fips() 语义”)。
60                false
61            }
62        }
63    };
64}
65
66// ---------------------------------------------------------------------------
67// AlgorithmIdentifier 静态表(均为 SEQUENCE 内容,无外层 30 xx 头;
68// 与 pki-types src/data/alg-*.der 逐字节一致)
69// ---------------------------------------------------------------------------
70
71/// ecPublicKey + prime256v1
72const PK_EC_P256: &[u8] = &[
73    0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
74    0x03, 0x01, 0x07,
75];
76/// ecPublicKey + secp384r1
77const PK_EC_P384: &[u8] = &[
78    0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
79];
80/// ecdsa-with-SHA256(无参数)
81const SIG_ECDSA_SHA256: &[u8] = &[0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02];
82/// ecdsa-with-SHA384(无参数)
83const SIG_ECDSA_SHA384: &[u8] = &[0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03];
84/// Ed25519(公钥/签名同形)
85const ID_ED25519: &[u8] = &[0x06, 0x03, 0x2b, 0x65, 0x70];
86/// rsaEncryption + NULL
87const PK_RSA: &[u8] = &[
88    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
89];
90/// sha256WithRSAEncryption + NULL
91const SIG_RSA_PKCS1_SHA256: &[u8] = &[
92    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
93];
94/// sha384WithRSAEncryption + NULL
95const SIG_RSA_PKCS1_SHA384: &[u8] = &[
96    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00,
97];
98/// sha512WithRSAEncryption + NULL
99const SIG_RSA_PKCS1_SHA512: &[u8] = &[
100    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00,
101];
102/// RSASSA-PSS(SHA-256 / MGF1-SHA256 / salt 32):OID + 参数
103const SIG_RSA_PSS_SHA256: &[u8] = &[
104    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0, 0x0f, 0x30,
105    0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c,
106    0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06,
107    0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01,
108    0x20,
109];
110/// RSASSA-PSS(SHA-384 / MGF1-SHA384 / salt 48)
111const SIG_RSA_PSS_SHA384: &[u8] = &[
112    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0, 0x0f, 0x30,
113    0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa1, 0x1c,
114    0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06,
115    0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01,
116    0x30,
117];
118/// RSASSA-PSS(SHA-512 / MGF1-SHA512 / salt 64)
119const SIG_RSA_PSS_SHA512: &[u8] = &[
120    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0, 0x0f, 0x30,
121    0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa1, 0x1c,
122    0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06,
123    0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01,
124    0x40,
125];
126
127fn v_ecdsa_p256(
128    public_key: &[u8],
129    message: &[u8],
130    signature: &[u8],
131) -> Result<(), ferritls_core::Error> {
132    ecdsa::p256::VerifyKey::from_sec1_point(public_key)?.verify(message, signature)
133}
134
135fn v_ecdsa_p384(
136    public_key: &[u8],
137    message: &[u8],
138    signature: &[u8],
139) -> Result<(), ferritls_core::Error> {
140    ecdsa::p384::VerifyKey::from_sec1_point(public_key)?.verify(message, signature)
141}
142
143fn v_ed25519(
144    public_key: &[u8],
145    message: &[u8],
146    signature: &[u8],
147) -> Result<(), ferritls_core::Error> {
148    ed25519::VerifyKey::from_raw_bytes(public_key)?.verify(message, signature)
149}
150
151/// 解析裸 `RSAPublicKey` DER(webpki 传入的 key_value 格式)。
152/// 解析失败统一归一化为 `InvalidSignature`,不区分密钥格式错误
153/// 与签名验证失败。
154fn v_rsa_pkcs1_256(
155    public_key: &[u8],
156    message: &[u8],
157    signature: &[u8],
158) -> Result<(), ferritls_core::Error> {
159    rsa::VerifyKey::from_rsapublickey_der(public_key)?.verify_pkcs1v15(256, message, signature)
160}
161
162fn v_rsa_pkcs1_384(
163    public_key: &[u8],
164    message: &[u8],
165    signature: &[u8],
166) -> Result<(), ferritls_core::Error> {
167    rsa::VerifyKey::from_rsapublickey_der(public_key)?.verify_pkcs1v15(384, message, signature)
168}
169
170fn v_rsa_pkcs1_512(
171    public_key: &[u8],
172    message: &[u8],
173    signature: &[u8],
174) -> Result<(), ferritls_core::Error> {
175    rsa::VerifyKey::from_rsapublickey_der(public_key)?.verify_pkcs1v15(512, message, signature)
176}
177
178fn v_rsa_pss_256(
179    public_key: &[u8],
180    message: &[u8],
181    signature: &[u8],
182) -> Result<(), ferritls_core::Error> {
183    rsa::VerifyKey::from_rsapublickey_der(public_key)?.verify_pss(256, message, signature)
184}
185
186fn v_rsa_pss_384(
187    public_key: &[u8],
188    message: &[u8],
189    signature: &[u8],
190) -> Result<(), ferritls_core::Error> {
191    rsa::VerifyKey::from_rsapublickey_der(public_key)?.verify_pss(384, message, signature)
192}
193
194fn v_rsa_pss_512(
195    public_key: &[u8],
196    message: &[u8],
197    signature: &[u8],
198) -> Result<(), ferritls_core::Error> {
199    rsa::VerifyKey::from_rsapublickey_der(public_key)?.verify_pss(512, message, signature)
200}
201
202verifier!(
203    EcdsaP256Sha256,
204    PK_EC_P256,
205    SIG_ECDSA_SHA256,
206    v_ecdsa_p256,
207    "ECDSA P-256/SHA-256(批准)。"
208);
209verifier!(
210    EcdsaP384Sha384,
211    PK_EC_P384,
212    SIG_ECDSA_SHA384,
213    v_ecdsa_p384,
214    "ECDSA P-384/SHA-384(批准)。"
215);
216verifier!(
217    Ed25519,
218    ID_ED25519,
219    ID_ED25519,
220    v_ed25519,
221    "Ed25519(非批准)。"
222);
223verifier!(
224    RsaPkcs1Sha256,
225    PK_RSA,
226    SIG_RSA_PKCS1_SHA256,
227    v_rsa_pkcs1_256,
228    "RSA PKCS#1 v1.5/SHA-256(批准;仅证书链验证遗留用途)。"
229);
230verifier!(
231    RsaPkcs1Sha384,
232    PK_RSA,
233    SIG_RSA_PKCS1_SHA384,
234    v_rsa_pkcs1_384,
235    "RSA PKCS#1 v1.5/SHA-384(批准;遗留用途)。"
236);
237verifier!(
238    RsaPkcs1Sha512,
239    PK_RSA,
240    SIG_RSA_PKCS1_SHA512,
241    v_rsa_pkcs1_512,
242    "RSA PKCS#1 v1.5/SHA-512(批准;遗留用途)。"
243);
244verifier!(
245    RsaPssSha256,
246    PK_RSA,
247    SIG_RSA_PSS_SHA256,
248    v_rsa_pss_256,
249    "RSA-PSS/SHA-256(批准)。"
250);
251verifier!(
252    RsaPssSha384,
253    PK_RSA,
254    SIG_RSA_PSS_SHA384,
255    v_rsa_pss_384,
256    "RSA-PSS/SHA-384(批准)。"
257);
258verifier!(
259    RsaPssSha512,
260    PK_RSA,
261    SIG_RSA_PSS_SHA512,
262    v_rsa_pss_512,
263    "RSA-PSS/SHA-512(批准)。"
264);
265
266/// 供 `WebPkiSupportedAlgorithms::all` 使用的完整清单。
267pub static ALL_VERIFIERS: &[&dyn SignatureVerificationAlgorithm] = &[
268    &EcdsaP256Sha256,
269    &EcdsaP384Sha384,
270    &Ed25519,
271    &RsaPkcs1Sha256,
272    &RsaPkcs1Sha384,
273    &RsaPkcs1Sha512,
274    &RsaPssSha256,
275    &RsaPssSha384,
276    &RsaPssSha512,
277];
278
279/// scheme → 验证算法映射(TLS 1.3 只取各组首项)。
280pub static SCHEME_MAP: &[(SignatureScheme, &[&dyn SignatureVerificationAlgorithm])] = &[
281    (SignatureScheme::ECDSA_NISTP256_SHA256, &[&EcdsaP256Sha256]),
282    (SignatureScheme::ECDSA_NISTP384_SHA384, &[&EcdsaP384Sha384]),
283    (SignatureScheme::ED25519, &[&Ed25519]),
284    (SignatureScheme::RSA_PKCS1_SHA256, &[&RsaPkcs1Sha256]),
285    (SignatureScheme::RSA_PKCS1_SHA384, &[&RsaPkcs1Sha384]),
286    (SignatureScheme::RSA_PKCS1_SHA512, &[&RsaPkcs1Sha512]),
287    (SignatureScheme::RSA_PSS_SHA256, &[&RsaPssSha256]),
288    (SignatureScheme::RSA_PSS_SHA384, &[&RsaPssSha384]),
289    (SignatureScheme::RSA_PSS_SHA512, &[&RsaPssSha512]),
290];
291
292/// 默认(非批准模式)的 webpki 验证算法集。
293pub static SUPPORTED_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
294    all: ALL_VERIFIERS,
295    mapping: SCHEME_MAP,
296};
297
298/// 批准模式的 webpki 验证算法集(无 Ed25519)。
299pub static FIPS_SUPPORTED_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
300    all: FIPS_ALL_VERIFIERS,
301    mapping: FIPS_SCHEME_MAP,
302};
303
304static FIPS_ALL_VERIFIERS: &[&dyn SignatureVerificationAlgorithm] = &[
305    &EcdsaP256Sha256,
306    &EcdsaP384Sha384,
307    &RsaPkcs1Sha256,
308    &RsaPkcs1Sha384,
309    &RsaPkcs1Sha512,
310    &RsaPssSha256,
311    &RsaPssSha384,
312    &RsaPssSha512,
313];
314
315static FIPS_SCHEME_MAP: &[(SignatureScheme, &[&dyn SignatureVerificationAlgorithm])] = &[
316    (SignatureScheme::ECDSA_NISTP256_SHA256, &[&EcdsaP256Sha256]),
317    (SignatureScheme::ECDSA_NISTP384_SHA384, &[&EcdsaP384Sha384]),
318    (SignatureScheme::RSA_PKCS1_SHA256, &[&RsaPkcs1Sha256]),
319    (SignatureScheme::RSA_PKCS1_SHA384, &[&RsaPkcs1Sha384]),
320    (SignatureScheme::RSA_PKCS1_SHA512, &[&RsaPkcs1Sha512]),
321    (SignatureScheme::RSA_PSS_SHA256, &[&RsaPssSha256]),
322    (SignatureScheme::RSA_PSS_SHA384, &[&RsaPssSha384]),
323    (SignatureScheme::RSA_PSS_SHA512, &[&RsaPssSha512]),
324];