SM2 Encrypt / Decrypt / Sign — Chinese National Standard Elliptic Curve Cryptosystem (GB/T 32918-2016)
SM2 Encrypt / Decrypt / Sign
The full SM2 public-key toolbox on the recommended curve
sm2p256v1 (GB/T 32918.5): generate a key pair, sign and verify
with the SM3-based ZA scheme (GB/T 32918.2), and encrypt or decrypt
in the standard C1C3C2 order, the legacy C1C2C3 order, or
ASN.1 DER. Everything runs in your browser; nothing is uploaded.
1. Keys - generate a pair, or paste your own (hex)
Private key (hex, 64 digits — treat like a password)
Public key (hex, 130 digits with 04 prefix or 128 digits x||y)
The private key is used by Sign and Decrypt; the public key by Verify and Encrypt. Keys never leave this page.
User ID (the "distinguishing identifier" mixed into ZA; default is the de-facto standard)
Read message as:Fixed k (advanced):
r (hex)
s (hex)
Signature, ASN.1 DER (SEQUENCE { r INTEGER, s INTEGER } - the format OpenSSL/GmSSL use)
About the fixed-k box: every real signature must use a fresh unpredictable
k — reusing or guessing k leaks the private key (the Sony ECDSA lesson). This page generates
a random k from crypto.getRandomValues whenever the box is empty. Fill the box only to
reproduce a known vector for teaching or testing.
3. Verify - requires the public key
User ID (must match the signer's)
Read message as:Signature format:
r (hex)
s (hex)
✓ Signature is VALID
✗ Signature is INVALID
4. Encrypt - requires the public key; GB/T 32918.4
Read message as:Ciphertext format:Output:
Fixed k (advanced):
Hybrid encryption reminder: SM2 encryption is meant for short secrets
(session keys, PINs), not bulk data — every message pays 96 bytes of C1+C3 overhead and an
elliptic-curve point multiplication. Encrypt a random SM4/AES key with SM2, then the data with
the symmetric cipher (SM4 page / AES page).
5. Decrypt - requires the private key
Read ciphertext as:Order:Write plaintext as:
OpenSSL cross-check — this page's C1C3C2 hex matches
openssl pkeyutl -sm2encrypt -pubin -inkey pub.pem (OpenSSL 3.x with
-pkeyopt ec_scheme:c1c3c2, the default), and GmSSL
gmssl sm2randkey / sm2encrypt tooling; signatures match
openssl dgst -sm3 -sign with the same user ID via
-pkeyopt sm2_userid:1234567812345678. A leading 04 byte
before C1 (as produced by several libraries) is accepted on decrypt.
Compliance note: SM2 is an algorithm choice driven by Chinese
commercial-cryptography compliance and interoperation, with security comparable to
256-bit ECC (NIST P-256). In production, pair it with a real key-management
system or hardware keys — a browser page is a calculator, not a vault.
Self-test
Replays the key-derivation, fixed-k signature and encryption vectors produced by an
independent Python reference implementation (and cross-checked against gmssl), the
DER signature and DER ciphertext roundtrips, random-k sign/verify and encrypt/decrypt
roundtrips, and the negative paths (tampered C3, truncated ciphertext, off-curve
public key, r = 0).
What is SM2?
In one sentence: SM2 is the Chinese national standard public-key
cryptosystem — an elliptic-curve signature and encryption scheme over the
fixed curve sm2p256v1, published as GB/T 32918-2016 (earlier GM/T 0003-2012),
playing the role in the Chinese "SM" suite that ECDSA/ECDH (P-256) play in the NIST world.
ECC in one paragraph (the intuition)
All elliptic-curve crypto rests on one trick: given the base point G on a curve over a
big prime field and the multiple P = d·G, computing d from P means solving the
elliptic-curve discrete logarithm problem, for which no fast algorithm is known. The private
key d is just a 256-bit number; the public key is the point d·G. SM2 is not a new
curve arithmetic — it is a specific way to sign (like ECDSA) and encrypt (like a
miniature ECIES) on one specific curve, hashing with SM3 instead of SHA.
sm2p256v1 vs NIST P-256
sm2p256v1
NIST P-256 (secp256r1)
Field size
256-bit prime
256-bit prime
Curve shape
y² = x³ + ax + b
y² = x³ − 3x + b (a = −3)
Security level
≈ 128 bits
≈ 128 bits
Signature
SM2 (GB/T 32918.2), SM3-based, user ID bound into ZA
ECDSA with SHA-256
Encryption
SM2 (GB/T 32918.4), C1C3C2
ECIES (ANSI X9.63, not NIST-standardized)
Hash
SM3 (GB/T 32905)
SHA-2 family
Published
2010 design, GM/T 0003-2012, GB/T 32918-2016; in ISO/IEC 14888-3
1999 (SEC 2 / NIST)
TLS support
TLCP (GM/T 386) and TLS 1.3 RFC 8998 suites
everywhere
Both curves offer the same concrete security; neither has a practical attack. The choice
between them is regulatory and interoperability, not strength.
The user ID and ZA — what SM2 signs that ECDSA does not
Before hashing, SM2 folds the signer's identity into the digest:
ZA = SM3(ENTL ‖ ID ‖ a ‖ b ‖ xG ‖ yG ‖ xA ‖ yA), where ENTLa is the
ID's bit length, the middle four fields pin the exact curve, and the last two are the
signer's public key. The message is hashed as SM3(ZA ‖ M). Two consequences: a
signature is bound to the claimed identity (a feature), and the verifier must be told the
signer's ID and use the same one (a classic interop pitfall). Nearly the whole ecosystem
settled on the 16-digit default 1234567812345678 — not from the standard
text, but from the appendix examples of GM/T 0003; OpenSSL's default matches it, and so
does this page.
Ciphertext formats: C1C3C2, C1C2C3 and DER
An SM2 ciphertext has three parts: C1 = the ephemeral point kG (64 bytes, x‖y),
C3 = SM3(x2 ‖ M ‖ y2) (32 bytes, integrity), C2 = M ⊕ KDF(x2 ‖ y2) (the masked
message). The 2012 GM/T 0003 text concatenated them C1 ‖ C2 ‖ C3; the 2016
GB/T 32918.4 standard reordered to C1 ‖ C3 ‖ C2, and OpenSSL 1.1.1+ followed.
Old banking and government systems still speak the old order — which is why this page
has both, plus the ASN.1 form (SEQUENCE of INTEGER x1, INTEGER y1, OCTET STRING C3,
OCTET STRING C2) that some libraries emit. When decrypting fails with the other party's
tool, the byte order is the first thing to check.
Common mistakes
Reusing or skimping on k. The nonce k in both signing and encryption must be
fresh and unpredictable per operation. One repeated k across two signatures hands the
private key to anyone who sees both. This page draws k from the browser CSPRNG; the
fixed-k boxes exist only for reproducing known vectors.
Mismatched user IDs. Sign with the default ID, verify with a custom one (or
vice versa) and every valid signature fails. The ID is part of the signed data.
Assuming C1C3C2 everywhere. GM/T 0003-era systems, some smart cards and
older GmSSL builds default to C1C2C3; several tools also prepend an uncompressed-point
04 byte. This page accepts all of these on decrypt.
Encrypting bulk data with SM2. Each ciphertext carries 96 bytes of overhead
and costs two point multiplications. Use SM2 on a key, SM4/AES on the data.
Treating a 04-prefixed public key as 65 raw bytes of key. The 04 is an
encoding marker: the key itself is x ‖ y, 128 hex digits. This page accepts both
spellings.
FAQ
Is this compatible with OpenSSL / GmSSL? Yes. The C1C3C2 hex output matches
openssl pkeyutl -sm2encrypt for the same public key, message and k; DER
signatures match openssl dgst -sm3 -sign output byte for byte (set the user ID
with -pkeyopt sm2_userid:...). Random-k runs of course differ — compare by
decrypting/verifying, not by equality.
Why is there no SM2 key exchange here? GB/T 32918.3 defines an interactive
authenticated key-exchange protocol; it makes no sense as a one-page calculator. Sign and
encrypt cover the non-interactive uses.
Is SM2 in WebCrypto? No — no browser implements it (Chrome ships it only
behind non-standard flags, if at all). This page runs a from-scratch JavaScript
implementation, with the standard's own appendix vectors wired into the self-test above.
Can I use a PEM key from OpenSSL? Export the raw hex instead:
openssl ec -in key.pem -text prints the private scalar and public point.
This page takes hex keys only, on purpose — the PEM/SEC1 machinery lives on the
RSA page where it belongs.
What is SM9 then? A different animal: identity-based cryptography, where any
string (an email address) is the public key and a KGC issues private keys.
See the SM9 overview page.