Skip to content

Feature/sm3 impl - #89

Open
dghgit wants to merge 6 commits into
release/0.1.3alphafrom
feature/sm3-impl
Open

Feature/sm3 impl#89
dghgit wants to merge 6 commits into
release/0.1.3alphafrom
feature/sm3-impl

Conversation

@dghgit

@dghgit dghgit commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Chinese SM3 Digest, including HMAC. Implementation supports partial bytes, may need to ask around at OpenSSL about getting some test vectors though.

@ounsworth

Copy link
Copy Markdown
Contributor

Thanks David!
On a 2-minute scroll-through, this code looks great, style-wise.
But to review this PR properly, including checking that the tests cover all the edge-cases that they need to cover, I would need to first read the SM3 spec cover-to-cover. Is there a public English version available?

So I think this PR will need to sit until I or someone else has time to review it deeply. Or maybe we could merge it into an experimental/ folder instead of the crypto/ folder with a readme about the review and testing needed before moving it to crypto/, disconnect it from the CLI and Factory, etc.

Thoughts?

@ounsworth

Copy link
Copy Markdown
Contributor

wycheproof has test vectors for sm4, but not sm3, so I'm also not sure where to get a good set of vectors.

@dghgit

dghgit commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

English version of the spec is here:

http://www.gmbz.org.cn/upload/2024-11-18/1731899426565012428.pdf

Sadly all the examples are octet aligned.

There's also this:

https://datatracker.ietf.org/doc/draft-sca-cfrg-sm3/01/

For some unknown reason all the GM related standards submitted to the IETF ran out of puff. Attempts to contact the authors resulted in failure. I think one of the examples in the draft might have a typo in it as well, but BC's original implementation was based on the IETF draft.

If it's any further help, the SM3 implementation is based on BC's. The Rust implementation has also been tested against OpenSSL's, although note neither of these implementations support partial bytes. Both BC's and OpenSSL's implementations of SM3 have had extensive use at this point. I think we'll need to talk to the OpenSSL team concerning test vectors for non-byte aligned data. The implementation seems to be coherent with the spec, section 5.2 of the document shows the padding mechanism that's used.

dghgit added a commit that referenced this pull request Aug 27, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dghgit and others added 6 commits August 27, 2026 13:57
New crate crypto/sm3 following the sha2 conventions:
- SM3 implements Hash, Algorithm, HashAlgParams, AlgorithmOID
  (1.2.156.10197.1.401) and Suspendable, with a single spec-commented
  finalize() shared by do_final_out and do_final_partial_bits_out.
  Bit-oriented messages return HashError::InvalidInput rather than panic.
- Round constants T_j <<< (j mod 32) are computed at compile time; the
  chaining value and input buffer live in Secret<>. Compression is a free
  function over the chaining value (no unsafe, no data-dependent branches).
- Crate docs with Usage Examples, Memory Usage (112 B object, 108 B
  suspended state, 272 B message schedule) and Security Considerations.
- Tests: core-test-framework Hash suite, GB/T 32905-2016 Appendix A vectors,
  bc-java SM3DigestTest vectors, openssl-generated DUMMY_SEED and padding
  boundary (55/56/63/64/65/119/128 byte) vectors incl. byte-at-a-time
  streaming, constants/OID/strength checks, and Suspendable round-trip with
  corrupt-state rejection.
- criterion bench (16KiB throughput), matching sha2_benches.
- Registered in HashFactory ("SM3"), the bouncycastle umbrella crate
  (bouncycastle::sm3), and the bc-rust CLI (`bc-rust sm3 [-x]`, streaming
  stdin -> stdout). Factory test added.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- bouncycastle-hmac: `HMAC_SM3 = HMAC<SM3, 64>` type alias with Algorithm
  ("HMAC-SM3", 128-bit), AlgorithmOID (1.2.156.10197.1.401.2), keygen(),
  and SUSPENDED_HMAC_SM3_STATE_LEN. Tests: known answers generated with
  `openssl dgst -sm3 -mac HMAC` over the RFC 4231 case 1/2/6 keys and
  messages (incl. an over-block-size key) plus a zero-length key, and the
  existing alias / algorithm-name / keygen / suspend-resume suites extended
  to cover it. Criterion bench added alongside the SHA-256/512 ones.
- MACFactory: HMAC_SM3 variant, constructible as "HMAC-SM3"; factory test.
- CLI: `bc-rust hmac-sm3 [--key HEX | -k FILE] [-v MAC] [-x]`, same
  streaming behaviour as hmac-sha256/512.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All SM3 DUMMY_SEED / padding-boundary digests and all HMAC-SM3 known answers
were recomputed with bc-java (SM3Digest, HMac(new SM3Digest())) and match
the openssl-generated values used in the tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…905-2016 s. 5.2

Replaces the InvalidInput error path with a real implementation, so every
HashFactory variant now supports non-byte-aligned input.

- finalize(partial_byte, num_partial_bits, output): the num_partial_bits
  least significant bits of partial_byte are placed MSB-first in the final
  message byte, immediately followed by the "1" pad bit, and the 64-bit
  length field is (byte_count << 3) | num_partial_bits. do_final_out is the
  zero-bit case.
- do_final_partial_bits_out validates num_partial_bits <= 7 (InvalidLength)
  and delegates; nothing panics.
- Crate docs: partial-bits usage example replaces the "not supported" note.

Tests: core-test-framework partial-input tests enabled; `partial_bits`
checks 0-bit equivalence, range validation, low-bit-only influence and
second-block spill; `partial_bits_known_answers` holds 6 bit-length digests
from an independent pure-Python GB/T 32905-2016 reference (validated against
openssl dgst -sm3 on byte-aligned inputs; neither openssl nor bc-java expose
a bit-length SM3 API).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hubot
hubot force-pushed the feature/sm3-impl branch from 8d20170 to 409b918 Compare August 27, 2026 04:19
@dghgit
dghgit changed the base branch from main to release/0.1.3alpha August 27, 2026 04:57
@hubot
hubot force-pushed the feature/sm3-impl branch from 409b918 to 3ecdaac Compare August 27, 2026 05:07
@kriskwiatkowski

Copy link
Copy Markdown

FWIW: I've implemented it long time ago also, in Go, should you wish to test against some other implementation. The code has some test vectors too:
https://github.com/kriskwiatkowski/nobs/blob/master/hash/sm3/sm3_test.go

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.

3 participants