1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//! Constant-time-designed pure-Rust SM2 / SM3 / SM4 primitives.
//!
//! See the workspace `README.md` for scope, threat model, and the honest
//! framing of the in-CI `dudect`-based timing-leak regression harness.
//!
//! # Modules
//!
//! - [`sm2`] — SM2 elliptic-curve sign / verify / encrypt / decrypt
//! (GB/T 32918). Comb-table fixed-base scalar mult (v0.3 W6). The
//! opt-in `sm2-key-exchange` feature (v1.1) adds
//! `sm2::key_exchange` — GM/T 0003.3 key agreement with key
//! confirmation (`Sm2KxInitiator` / `Sm2KxResponder` role
//! state-machines).
//! - [`sm3`] — SM3 hash (GB/T 32905) with streaming `new/update/finalize`.
//! - `x509` (the module appears with the feature of the same name, v1.3) —
//! X.509-with-SM2 LEAF certificate parse + SM2-with-SM3 signature verify
//! over the exact wire `tbsCertificate` bytes. **No trust decisions**
//! (no chains / time checks / extension interpretation / revocation).
//! - [`sm4`] — SM4 block cipher (GB/T 32907) + CBC and CTR modes
//! (single-shot and streaming). The opt-in `sm4-aead` feature adds
//! SM4-GCM (single-shot + incremental-input buffered) and SM4-CCM;
//! the opt-in `sm4-xts` feature adds SM4-XTS (GB/T 17964-2021,
//! single-shot + in-place multi-sector). v0.4 W3 adds an opt-in
//! bitsliced (table-less, gate-only) S-box behind the
//! `sm4-bitsliced` feature.
//! - [`hmac`] — HMAC-SM3 (RFC 2104), single-shot + v0.3 W5 streaming.
//! - [`kdf`] — PBKDF2-HMAC-SM3 (RFC 8018 §5.2).
//! - [`asn1`] — strict-canonical DER reader / writer / OID constants
//! (v0.3 W1); GM/T 0009 SM2 ciphertext SEQUENCE; RFC 3279 SM2
//! signature SEQUENCE.
//! - [`pem`] — RFC 7468 PEM codec (v0.3 W2; hand-rolled, `no_std`).
//! - [`spki`] — RFC 5280 `SubjectPublicKeyInfo` for SM2 (v0.3 W2).
//! - [`sec1`] — RFC 5915 `ECPrivateKey` + SEC1 uncompressed point (v0.3 W2).
//! - [`pkcs8`] — RFC 5958 `OneAsymmetricKey` + RFC 8018 PBES2 (v0.3 W2).
//! - [`traits`] — in-crate `Hash` / `Mac` / `BlockCipher` traits
//! (v0.3 W5). v0.4 W2 adds RustCrypto-trait fit (`digest::Digest`,
//! `digest::Mac`, `cipher::BlockCipherEncrypt`/`BlockCipherDecrypt`)
//! behind the opt-in `digest-traits` / `cipher-traits` features
//! (migrated to `digest 0.11` / `cipher 0.5` in v0.11).
//!
//! # Crate features
//!
//! - `default` — `no_std`, `alloc`-only. No optional dependencies.
//! - `digest-traits` — opt-in (v0.4 W2). Implements `digest::Digest` for
//! [`sm3::Sm3`] and `digest::Mac` for [`hmac::HmacSm3`]. Pulls
//! `digest = "0.11"` — a pre-1.0 ecosystem crate, so a breaking `digest`
//! release is **not** covered by `gmcrypto-core`'s `SemVer` (bump your own).
//! - `cipher-traits` — opt-in (v0.4 W2). Implements
//! `cipher::{BlockCipherEncrypt, BlockCipherDecrypt, BlockSizeUser,
//! KeySizeUser, KeyInit}` for [`sm4::Sm4Cipher`]. Pulls `cipher = "0.5"` —
//! a pre-1.0 ecosystem crate, so a breaking `cipher` release is **not**
//! covered by `gmcrypto-core`'s `SemVer` (bump your own).
//! - `sm4-bitsliced` — opt-in (v0.4 W3). Routes the SM4 S-box through
//! a bitsliced (table-less, gate-only) Itoh-Tsujii inversion in
//! GF(2^8). Byte-identical output to the default linear-scan path;
//! constant-time by construction (no table lookups, no branches on
//! secret bits).
//! - `sm4-bitsliced-simd` — opt-in (v0.5 W4 scaffolding; AVX2 / NEON
//! intrinsic implementations land in v0.5.x). Implies
//! `sm4-bitsliced`. Default-off.
//! - `crypto-bigint-scalar` — opt-in (v0.5 W5). Exposes
//! [`sm2::Sm2PrivateKey::from_scalar`] which takes a
//! `crypto_bigint::U256` directly. Default-off; the always-on
//! `from_bytes_be` constructor is the recommended path for callers
//! who don't want a transitive `crypto-bigint` dep.
//! - `sm4-aead` — opt-in (v0.8). SM4-GCM (`sm4::mode_gcm`, plus the
//! v0.9 incremental-input buffered `sm4::gcm_streaming`) and
//! SM4-CCM (`sm4::mode_ccm`) authenticated encryption. Pulls the
//! workspace-internal `gmcrypto-simd` for the GHASH primitive
//! (CLMUL / PMULL / constant-time software fallback).
//! - `sm4-xts` — opt-in (v0.12). SM4-XTS tweakable disk/sector mode
//! (`sm4::mode_xts`; GB/T 17964-2021, bit-reflected α-doubling —
//! **not** IEEE 1619), single-shot + the v0.15 in-place
//! multi-sector helpers. Pure-core, no new dependency.
//! Confidentiality only — XTS does not authenticate.
//! - `sm2-key-exchange` — opt-in (v1.1). GM/T 0003.3 ≡ GB/T
//! 32918.3-2016 key agreement with mandatory key confirmation
//! (`sm2::key_exchange`): consume-on-transition role state-machines,
//! single-use ephemerals, commit-on-confirm key release,
//! `ZeroizeOnDrop` agreed key. Pure-core, no new dependency;
//! byte-identical to the GM/T 0003.5 recommended-curve worked
//! example. The C ABI projection ships in `gmcrypto-c` (v1.2).
//! - `x509` — opt-in (v1.3). X.509-with-SM2 leaf certificate parse +
//! signature verify (GM/T 0015 profile): strict in-repo DER, v3-only,
//! `sm2-sign-with-sm3` outer==inner, SPKI delegated to [`spki`].
//! Pure-core, no new dependency, public inputs only (no constant-time
//! obligations arise). NO trust decisions — see the module docs.
//!
//! # `wasm32-unknown-unknown`
//!
//! Builds clean as of v0.4 W1. The crate is `no_std + alloc` only and
//! does NOT pull `getrandom`'s `wasm_js` backend or `wasm-bindgen` /
//! `js-sys` into its default dep graph. Wasm callers wire their own
//! `rand_core::Rng` impl — see the workspace `README.md`.
extern crate alloc;
// v1.3 — X.509-with-SM2 leaf certificate parse + signature verify. Opt-in
// via the `x509` feature; default builds are byte-identical. NO trust
// decisions. See docs/v1.3-x509-sm2-design.md.
// Not public API / not SemVer — low-level in-crate trait surface kept pub for internal cross-module + dev-crate use; the public trait fit is the opt-in RustCrypto digest/cipher impls.
/// Internal helper: canonical 32-byte big-endian encoding of a `U256`.
///
/// `crypto-bigint`'s `Encoding::to_be_bytes` returns an `EncodedUint`
/// wrapper, not a `[u8; 32]`. v0.22 reshaped the byte-adjacent public
/// types (`asn1::sig` signatures, `asn1::ciphertext::Sm2Ciphertext`) to
/// `[u8; 32]` so the public API names no `crypto-bigint` type; this pins
/// the conversion in one place for the internal producers (sign / encrypt /
/// raw-ciphertext). Not part of the public API.
pub
/// Workspace-wide failure type (v0.5 W5).
///
/// Every fallible public surface in `gmcrypto-core` that does not
/// return `Option` / `bool` / `subtle::CtOption` returns
/// `Result<_, Error>`. The single `Failed` variant is deliberate per
/// the **failure-mode invariant** (see `SECURITY.md`): distinguishing
/// failure modes leaks information to padding-oracle / invalid-curve /
/// password-oracle attackers.
///
/// Per-module aliases keep the established import paths working:
/// `sm2::Error`, `pem::Error`, `pkcs8::Error` are type aliases for
/// this one type. Prior to v0.5 these were separate per-module enums
/// (`SignError`, `EncryptError`, `DecryptError`, `pem::Error`,
/// `pkcs8::Error`) all with a single `Failed` variant; v0.5 unifies
/// them per Q5.16 in `docs/v0.5-scope.md`.