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.
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.
User ID (must match the signer's)
Read message as: Signature format:
r (hex)
s (hex)
✓ Signature is VALID
✗ Signature is INVALID
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).
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
sm2p256v1NIST P-256 (secp256r1)
Field size256-bit prime256-bit prime
Curve shapey² = x³ + ax + by² = x³ − 3x + b (a = −3)
Security level≈ 128 bits≈ 128 bits
SignatureSM2 (GB/T 32918.2), SM3-based, user ID bound into ZAECDSA with SHA-256
EncryptionSM2 (GB/T 32918.4), C1C3C2ECIES (ANSI X9.63, not NIST-standardized)
HashSM3 (GB/T 32905)SHA-2 family
Published2010 design, GM/T 0003-2012, GB/T 32918-2016; in ISO/IEC 14888-31999 (SEC 2 / NIST)
TLS supportTLCP (GM/T 386) and TLS 1.3 RFC 8998 suiteseverywhere

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.