SM2 Encryption Guide: Keys, Decryption & Signatures
What Is SM2?
SM2 is an asymmetric encryption algorithm published by China's State Cryptography Administration. Based on elliptic curve cryptography (ECC), it replaces RSA as the Chinese national (GM) standard.
| Comparison | SM2 | RSA 2048 |
|---|---|---|
| Key length | 256 bit | 2048 bit |
| Security strength | 128 bit | 112 bit |
| Signing speed | ~0.5ms | ~3ms |
| Verification speed | ~1ms | ~0.1ms |
| Relative key size | 1 | 8 |
| Standard | GM/T 0003 | PKCS#1 |
SM2 achieves RSA-2048-level security with a 256-bit key — shorter keys and faster performance.
Three Uses of SM2
| Use | Description | Tool |
|---|---|---|
| Encrypt/Decrypt | Encrypt with the public key, decrypt with the private key | SM2 Encryption |
| Digital Signature | Sign with the private key, verify with the public key | SM2 Signing |
| Key Agreement | Two parties negotiate a shared secret | ECDH protocol |
Step 1: Generate an SM2 Key Pair
Generate with ToolsKu
- Open the SM2 Encryption tool
- Click "Generate Key Pair"
- Get your public and private keys
Generate from the Command Line
# Install gmssl
brew install gmssl # macOS
# Or download from https://github.com/guanzhi/GmSSL/releases
# Generate an SM2 key pair
gmssl sm2 -genkey -out sm2.key
# Inspect the key
gmssl sm2 -in sm2.key -text
Generate with JavaScript
import { sm2 } from 'sm-crypto';
// Generate a key pair
const keyPair = sm2.generateKeyPairHex();
// keyPair.privateKey → private key (64 hex chars)
// keyPair.publicKey → public key (128 hex chars, 04 + X + Y)
console.log('Private key:', keyPair.privateKey);
console.log('Public key:', keyPair.publicKey);
Key Format Explained
SM2 public key format:
04 || X (32 bytes) || Y (32 bytes)
↓
04 + 64 hex chars of X + 64 hex chars of Y
Total length: 130 hex characters (65 bytes)
SM2 private key format:
32-byte random number
Total length: 64 hex characters (32 bytes)
Step 2: SM2 Encryption and Decryption
Encryption Flow
Plaintext → SM2 encrypt (public key) → Ciphertext (C1 || C3 || C2)
- C1: Elliptic curve point (65 bytes)
- C3: SM3 Hash value (32 bytes)
- C2: Ciphertext data
Encrypt with ToolsKu
- Open the SM2 Encryption tool
- Paste the public key
- Enter the plaintext to encrypt
- Choose the ciphertext format (C1C3C2 or C1C2C3)
- Click "Encrypt" to get the ciphertext
Encrypt with JavaScript
import { sm2 } from 'sm-crypto';
const publicKey = '04...'; // 130 hex chars
const privateKey = '...'; // 64 hex chars
// Encrypt (defaults to C1C3C2 format)
const cipherText = sm2.doEncrypt('Hello 国密', publicKey, 1);
// Parameter 1 = C1C3C2 format (recommended by the national standard)
// Parameter 0 = C1C2C3 format (legacy compatibility)
console.log('Ciphertext:', cipherText);
// Decrypt
const plainText = sm2.doDecrypt(cipherText, privateKey, 1);
console.log('Plaintext:', plainText); // "Hello 国密"
Ciphertext Encoding Formats
| Format | Description | Use Case |
|---|---|---|
| C1C3C2 | Recommended by the national standard | New projects (default) |
| C1C2C3 | Legacy format | Compatibility with older systems |
| ASN.1 | DER encoding | Java/C# interoperability |
Step 3: SM2 Digital Signatures
Signing Flow
Message → SM3 hash → SM2 sign (private key) → Signature (r, s)
Sign with ToolsKu
- Open the SM2 Encryption tool
- Switch to the "Sign" tab
- Enter the private key and the message to sign
- Click "Sign" to get the signature
Sign with JavaScript
import { sm2 } from 'sm-crypto';
const privateKey = '...';
const publicKey = '04...';
// Sign (automatically applies SM3 hash to the message)
const signature = sm2.doSignature('Message to sign', privateKey);
console.log('Signature:', signature);
// Verify the signature
const verified = sm2.doVerifySignature(
'Message to sign',
signature,
publicKey
);
console.log('Verification result:', verified); // true
Signing with a User ID
SM2 signing uses the default user ID 1234567812345678 (the national standard default), which you can customize:
// Specify a user ID when signing
const sig = sm2.doSignature('Message', privateKey, {
userId: 'customUserId'
});
// Use the same user ID when verifying
const valid = sm2.doVerifySignature('Message', sig, publicKey, {
userId: 'customUserId'
});
SM2 vs RSA: When to Choose Which?
| Scenario | Recommended | Reason |
|---|---|---|
| Chinese government systems | SM2 | GM compliance requirements |
| Chinese financial systems | SM2 | UnionPay/PBOC requirements |
| International standard systems | RSA | International compatibility |
| Mobile encryption | SM2 | Shorter keys, faster computation |
| Cross-border data exchange | RSA | Universally accepted |
The GM Trio: SM2 + SM3 + SM4
| Algorithm | Type | Purpose | Tool |
|---|---|---|---|
| SM2 | Asymmetric | Encryption/signing/key agreement | SM2 Tool |
| SM3 | Hash | Message digest (similar to SHA-256) | SM3 Tool |
| SM4 | Symmetric | Data encryption (similar to AES-128) | SM4 Tool |
Typical Combination: SM2 + SM4 Hybrid Encryption
1. Generate a random SM4 key
2. Encrypt large data with SM4 (fast)
3. Encrypt the SM4 key with the SM2 public key (secure transport)
4. Send: SM2(SM4 key) + SM4(data)
import { sm2, sm4 } from 'sm-crypto';
// 1. Generate a random SM4 key
const sm4Key = crypto.getRandomValues(new Uint8Array(16));
const sm4KeyHex = Array.from(sm4Key).map(b => b.toString(16).padStart(2, '0')).join('');
// 2. Encrypt data with SM4
const encryptedData = sm4.encrypt(plainText, sm4KeyHex);
// 3. Encrypt the SM4 key with SM2
const encryptedKey = sm2.doEncrypt(sm4KeyHex, sm2PublicKey, 1);
// Send: encryptedKey + encryptedData
FAQ
Why Is SM2 Ciphertext Much Longer Than the Plaintext?
SM2 ciphertext = C1 (65 bytes) + C3 (32 bytes) + C2 (plaintext length), so the ciphertext is 97 bytes longer than the plaintext. This is inherent to asymmetric encryption — for large data, use SM2+SM4 hybrid encryption.
What's the Difference Between SM2 and ECDSA?
SM2 uses the GM-specified elliptic curve (sm2p256v1), while ECDSA uses NIST curves (P-256). The algorithm logic is similar, but the curve parameters differ — they are not compatible.
How Do I Use SM2 in Java?
// Use Bouncy Castle with the GM extension
Security.addProvider(new BouncyCastleProvider());
// Generate a key pair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg.initialize(new ECParameterSpec(...)); // SM2 curve parameters
KeyPair kp = kpg.generateKeyPair();
Summary
SM2 is the core asymmetric encryption algorithm of the GM system, achieving RSA-2048-level security with just a 256-bit key. Master the three core operations — key generation, encryption/decryption, and digital signatures — and combine them with SM3 hashing and SM4 symmetric encryption to meet GM compliance requirements. ToolsKu provides three online tools — SM2, SM3, and SM4 — all processed locally in your browser with zero data upload.