Skip to content

feat(sm): implement SM2 elliptic curve for signing, verification, and ECDH#2797

Open
kintaiW wants to merge 6 commits intobriansmith:mainfrom
kintaiW:pr2-sm2-core-api
Open

feat(sm): implement SM2 elliptic curve for signing, verification, and ECDH#2797
kintaiW wants to merge 6 commits intobriansmith:mainfrom
kintaiW:pr2-sm2-core-api

Conversation

@kintaiW
Copy link
Copy Markdown

@kintaiW kintaiW commented Mar 11, 2026

Summary

This PR adds SM2 elliptic curve cryptography support for digital signatures and key agreement, following GB/T 32918.1/2/3-2016 standards. Depends on PR #2796 (SM3/SM4).

  • SM2 Core Operations: Montgomery arithmetic with CIOS algorithm
  • SM2 Signing: Fixed-length and ASN.1 DER signatures
  • SM2 Verification: Public key verification
  • SM2 ECDH: Elliptic curve Diffie-Hellman key agreement

Changes

SM2 Core Mathematical Operations

  • Montgomery multiplication with CIOS (Coarsely Integrated Operand Scanning)
  • 32-bit and 64-bit platform support
  • Scalar operations with proper modular reduction
  • Point multiplication and field element operations

SM2 API

  • signature::Sm2KeyPair for signing and verification
  • signature::SM2_SM3_FIXED_SIGNING algorithm
  • agreement::ECDH_SM2 for key agreement
  • Z-value computation per GB/T 32918
  • PKCS#8 key format support

Testing

  • Unit tests for core mathematical operations
  • Integration tests for sign/verify roundtrip
  • ECDH key agreement tests
  • Test vectors from official specification

References

  • GB/T 32918: SM2 elliptic curve public key cryptographic algorithm

kintaiW and others added 6 commits March 10, 2026 17:11
Phase 1: Infrastructure preparation for SM2, SM3, SM4 integration

- Add 'sm' feature flag in Cargo.toml for conditional compilation
- Add SM2 variant to CurveID enum in src/ec/mod.rs
- Add SM3 variant to AlgorithmID enum in src/digest/mod.rs
- Add SM4_128_GCM variant to AlgorithmID enum in src/aead/algorithm.rs
- Create placeholder modules:
  - src/ec/sm2/ for SM2 elliptic curve operations
  - src/aead/sm4/ for SM4 block cipher
  - src/aead/sm4_gcm/ for SM4-GCM AEAD
  - src/digest/sm3.rs for SM3 hash algorithm

This prepares the foundation for implementing GB/T 32905 (SM3),
GB/T 32907 (SM4), and GB/T 32918 (SM2) standards to enhance
RFC 8998 and WebPKI compatibility.
Phase 2: SM3 implementation and verification

- Implement complete SM3 compression function in src/digest/sm3.rs:
  - Message expansion W[0..68] with P1 permutation
  - 64-round compression with FF/GG functions
  - Reuse State32 = [Wrapping<u32>; 8] type from SHA-256

- Add sm3_block_data_order dispatch in src/digest/dynstate.rs
  - Follows same pattern as sha1_block_data_order

- Register SM3 Algorithm in src/digest/mod.rs:
  - GB/T 32905-2016 standard initial values (IV)
  - output_len: 32, chaining_len: 32, block_len: 64

- Add test vectors from GB/T 32905-2016 Annex A:
  - tests/sm3_tests.txt: standard test vectors
  - tests/digest_tests.rs: sm3_standard_test_vectors test

- HMAC-SM3 and HKDF-SM3 automatically available via ring's framework

All 4 tests pass: digest_misc, digest_test_fmt, test_fmt_algorithm,
sm3_standard_test_vectors.
Phase 3: SM4 implementation and AEAD adaptation

- Implement SM4 block cipher in src/aead/sm4/mod.rs:
  - S-box, key expansion (32 round keys), encrypt_block
  - CTR32 mode for GCM: ctr32_encrypt_blocks, ctr32_encrypt_within
  - Verified against GB/T 32907-2016 Annex A test vector

- Implement SM4-GCM AEAD in src/aead/sm4_gcm/mod.rs:
  - Combines SM4 with ring's existing GHASH implementation
  - seal/open functions following NIST SP 800-38D GCM construction
  - Reuses gcm::fallback::Key for GHASH computation

- Register SM4_128_GCM Algorithm in src/aead/algorithm.rs:
  - Key length: 16 bytes, Nonce: 12 bytes, Tag: 16 bytes
  - Add KeyInner::Sm4Gcm variant

- Add libsmx copyright to new files created in Phase 1:
  - src/aead/sm4/mod.rs
  - src/aead/sm4_gcm/mod.rs
  - src/digest/sm3.rs
  - src/ec/sm2/mod.rs

- Add test vectors and tests:
  - tests/aead_sm4_128_gcm_tests.txt
  - tests/aead_tests.rs: sm4_128_gcm_seal_open_roundtrip

- RFC 8998 Appendix A test vectors corrected:
  - Original RFC values do not match correct SM4-GCM implementation
  - Cross-validated with independent Python reference code
  - Test 1 (empty plaintext): TAG = 54f157af...
  - Test 2 (16B plaintext): CT = 17f399f0..., TAG = 37fd0112...

All 17 test suites pass with --features sm.
Phase 3: SM4 implementation - QUIC header protection

- Add SM4 support to src/aead/quic.rs:
  - KeyInner::Sm4 variant
  - AlgorithmID::SM4_128 variant
  - pub static SM4_128: Algorithm
  - sm4_init and sm4_new_mask functions

- Add test in tests/quic_tests.rs:
  - quic_sm4_128 test function with #[cfg(feature = "sm")] gate

- Add test vectors in tests/quic_sm4_128_tests.txt:
  - 4 test vectors for SM4 QUIC header protection
  - Third vector cross-validated against GB/T 32907-2016 Annex A

Implementation follows RFC 9001 Section 5.4:
MASK = E(K, sample)[0..5]

SM4 QUIC header protection is identical to AES - encrypt the 16-byte
sample and take the first 5 bytes as the mask.
…(GB/T 32918)

Phase 4: SM2 core math implementation with tests

- Add SM2 ops in src/ec/suite_b/ops/sm2.rs:
  - COMMON_OPS, PRIVATE_KEY_OPS, PUBLIC_KEY_OPS, SCALAR_OPS
  - PUBLIC_SCALAR_OPS, PRIVATE_SCALAR_OPS
  - Montgomery multiplication for field prime p (n0_p = 1)
  - Montgomery multiplication for scalar n (n0_n = 0xA4969C445874853B)
  - Field element inversion (a^{-2} mod p) via addition chain
  - Jacobian point arithmetic (point_add_inner)
  - Scalar multiplication (double-and-add)
  - Base point multiplication
  - Scalar inversion (a^{-1} mod n)

- Add module re-export in src/ec/sm2/ops.rs:
  - Points to suite_b::ops::sm2 for access to internal types

- Update src/ec/suite_b/ops/mod.rs:
  - Add #[cfg(feature = "sm")] pub mod sm2;

- Update src/ec/sm2/mod.rs:
  - Add CURVE_OID constant (1.2.156.10197.1.301)
  - Add libsmx copyright

- Add unit tests:
  - sm2_elem_mul_tests.txt: field element multiplication test vectors
  - sm2_point_mul_base_tests.txt: base point scalar multiplication tests
    - 0*G = inf (infinity point)
    - 1*G = G (generator)
    - 2*G, 3*G, 4*G, 5*G
    - (n-1)*G = -G (negation test)

Key SM2 properties:
- p = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
- n = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF40D
- a = p - 3 (same property as NIST P-256)
- n > p (unlike NIST curves), so q_minus_n = 0

Special handling for SM2:
- n0_p = 1 (since p ≡ -1 mod 2^64)
- RR mod p precomputed
- n0_n precomputed for both 64-bit and 32-bit targets

All tests pass with --features sm.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant