SM4 key length
16 bytes Exactly 128 bits: 16 bytes, written as 32 hex digits or 16 ASCII characters. There are no 192- or 256-bit SM4 keys.
Encrypt and decrypt SM4 online. If decryption fails, it finds whether the mode, padding, IV or encoding is wrong and offers the fix. Runs in your browser; nothing is uploaded. ECB, CBC, CTR, CFB, OFB; PKCS#7, zero or no padding.
ECB encrypts equal blocks to equal ciphertext and leaks patterns — use it only to talk to a system that requires it.
CTR, CFB and OFB are stream modes: no padding, and the ciphertext is as long as the plaintext.
Auto-diagnosis
—
Needs OpenSSL 3. The command contains the key you entered.
| Key | 0123456789abcdeffedcba9876543210 |
|---|---|
| Plaintext | 0123456789abcdeffedcba9876543210 |
| Ciphertext, 1 encryption | 681edf34d206965e86b3e94f536e4246 |
| Ciphertext, 1,000,000 encryptions | 595298c7c6fd271f0402f804c33d3f66 |
Written and reviewed by developers who build cryptography tools. Every ciphertext and byte count quoted on this page is computed by the tool's engine and checked by tests.
16 bytes Exactly 128 bits: 16 bytes, written as 32 hex digits or 16 ASCII characters. There are no 192- or 256-bit SM4 keys.
681edf34d206965e86b3e94f536e4246 With key and plaintext 0123456789abcdeffedcba9876543210, one encryption gives 681edf34d206965e86b3e94f536e4246.
32 rounds 16-byte (128-bit) blocks, encrypted in 32 rounds.
first 16 bytes No. Only the first 16 bytes decrypt wrongly, and the padding in the last block still checks out.
SM4 is the block cipher of China's commercial cryptography standards. It was issued as GM/T 0002-2012, became the national standard GB/T 32907-2016 (in force since 1 March 2017), and was added to the international standard ISO/IEC 18033-3 by an amendment in 2021. It is a symmetric cipher: the same 128-bit key encrypts and decrypts, and it works on 128-bit blocks, 16 bytes at a time — the same block size as AES.
Inside, each block is split into four 32-bit words and put through 32 rounds. Every round mixes three of the words with a round key, runs the result through an 8-bit S-box and a linear transformation, and folds it into the fourth word. The 32 round keys are derived from the key with two fixed sets of constants, and decryption is the same computation with the round keys in reverse order.
The block cipher alone can only handle exactly 16 bytes, so real data always goes through a mode of operation. This tool offers the five classic ones: ECB and CBC, which work on whole blocks and need padding, and CTR, CFB and OFB, which turn SM4 into a stream cipher with no padding at all. Most failed decryptions have nothing to do with SM4 itself — they come from the two sides disagreeing about the mode, the padding, the IV, the text encoding or how the key string becomes bytes, and libraries do not even agree on what a bare "SM4" means.
Browsers' built-in Web Crypto API does not include SM4, so this page carries its own implementation and runs it locally. It is tested against the two GB/T 32907 test vectors and cross-checked with OpenSSL 3 in every mode.
// SM4-CBC with PKCS#7 padding using Node.js and its bundled OpenSSL 3.
// Key and IV are both exactly 16 bytes (32 hex digits).
const crypto = require('node:crypto');
const key = Buffer.from('0123456789abcdeffedcba9876543210', 'hex');
const iv = Buffer.from('fedcba98765432100123456789abcdef', 'hex');
const cipher = crypto.createCipheriv('sm4-cbc', key, iv);
const ciphertext = Buffer.concat([cipher.update('hello', 'utf8'), cipher.final()]);
console.log(ciphertext.toString('base64')); // fUQPRg2HAXHGz5ZslzCpSQ==
const decipher = crypto.createDecipheriv('sm4-cbc', key, iv);
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
console.log(plaintext.toString('utf8')); // hello When decryption fails, the page retries ciphertext encoding, key format, mode, IV, padding and text encoding, and shows the settings that produce readable text.
One click sets the defaults of OpenSSL, Hutool, sm-crypto, gm-crypt or tjfoc/gmsm — libraries that do not even agree on whether plain "SM4" means ECB or CBC.
ECB, CBC, CTR, CFB and OFB with PKCS#7, zero padding or no padding. Plaintext can be UTF-8 or GBK, the encoding older Java code produces on Chinese Windows. GCM is not supported.
Generate a random 16-byte key or IV with one click, or enter it the way your code writes it. A live byte counter confirms you have exactly 16 bytes before you start chasing other causes.
Both Appendix A results are printed in a table and loadable with one click, so you can check any SM4 implementation against the standard.
Every result comes with the openssl enc command that reproduces it, so you can confirm it in a terminal or hand it to a colleague.
The SM4 engine runs locally. Keys and data never leave the page, and the tool keeps working offline.
openssl enc)-sm4 = CBC -sm4 is an alias of -sm4-cbc. -K and -iv take hex, PKCS#7 stays on unless you pass -nopad, and output is raw bytes unless you add -base64 -A. A -K of the wrong length is truncated or zero-padded with only a warning.
SmUtil.sm4(key)Hutool passes a bare SM4, which BouncyCastle runs as ECB with PKCS#7 (JCE calls it PKCS5Padding). String methods use UTF-8 and encryptHex prints lowercase hex. For CBC, use new SM4(Mode.CBC, Padding.PKCS5Padding, key, iv).
Cipher.getInstance("SM4")In a mode that needs an IV but gets none, encryption silently generates a random IV and decryption throws no IV set when one expected — so ciphertext encrypted without saving that IV cannot be decrypted anywhere.
sm4.encrypt(data, key) defaults to ECB with PKCS#7, expects the key as a 32-digit hex string and returns lowercase hex. Only mode: 'cbc' changes the mode; any other value silently stays ECB. sm-crypto-v2 behaves the same but uses an all-zero IV when CBC gets no iv.
Defaults to CBC, takes the key and IV as 16-character UTF-8 strings and returns Base64. A key whose bytes are not valid UTF-8 cannot be passed to it at all.
CryptSM4You choose the mode by calling crypt_ecb or crypt_cbc. set_key reads only the first 16 bytes, so a longer key is silently cut, and a wrong key usually returns empty bytes instead of an error.
sm4Sm4Cbc uses a package-level IV that stays all zeros until SetIV is called, pads with PKCS#7 even in CFB and OFB, and discards unpadding errors — a wrong key returns nil without an error.
Key 0123456789abcdeffedcba9876543210, plaintext (hex) 0123456789abcdeffedcba9876543210
681edf34d206965e86b3e94f536e4246
This is example 1 from Appendix A of GB/T 32907-2016: key and plaintext are the same 128-bit value, and one encryption gives 681edf34d206965e86b3e94f536e4246. Encrypting that output again, one million times in total, gives 595298c7c6fd271f0402f804c33d3f66. Both values are printed in the test-vector table on this page, computed by the same engine you are using. The GB/T 32907 test vector button loads the first one.
Key 0123456789abcdeffedcba9876543210, IV fedcba98765432100123456789abcdef, plaintext: SM4 interop test: order 20260911-0042
Wi6BuLpov8RndEfedUyLXFvDRnLMoo7T6O04Q83IzKDuDvPQ2S5clq+cEQXMvy/y
The plaintext is 37 bytes of UTF-8. PKCS#7 pads it to 48 bytes, three 16-byte blocks, which Base64 writes as 64 characters. The Load example button fills in exactly these values, and the OpenSSL panel shows a command that reproduces the same Base64 string in a terminal.
The ciphertext above, decrypted with IV 00000000000000000000000000000000
16 bytes of garbage, then ": order 20260911-0042"
CBC mixes the IV into the first block only, and the PKCS#7 padding sits in the last block, so the padding check still passes and OpenSSL raises no error. This page notices the unreadable first block and tells you the key and mode are right and the IV is the problem — or that the first 16 bytes of the ciphertext are themselves the IV.
If you know the library on the other side, choose it under Match the defaults of. Otherwise select Encrypt or Decrypt and match the mode and padding. Stream modes (CTR, CFB, OFB) have no padding, so the padding selector is disabled for them.
Both are exactly 16 bytes. Pick the format the string is written in — hex, text or Base64 — and watch the byte counter turn green. The Random buttons generate fresh values.
For encryption, type text (UTF-8 or GBK) or paste hex bytes. For decryption, paste the ciphertext and say whether it is Base64 or hex. The result updates as you type.
Copy the output, or click Decrypt this ciphertext to carry it to the decrypt tab with the same key and IV. The OpenSSL panel shows a command that reproduces the result.
The diagnosis lists the settings under which your inputs decrypt to readable text. Apply one with a click, or read the note if only the first 16 bytes fail — that points at the IV.
A 32-character hex string is 16 bytes only when it is decoded as hex. Read as text it is 32 bytes, which SM4 rejects — or, in code that silently cuts or pads keys, a different key altogether.
Key (text): 0123456789abcdeffedcba9876543210 -> 32 bytes, rejected
Key (hex): 0123456789abcdeffedcba9876543210 -> 16 bytes
The two sides must use the same mode. CBC ciphertext decrypted as ECB yields garbage in every block, and usually fails the padding check at the end.
encrypt: SM4/CBC/PKCS5Padding decrypt: SM4/ECB/PKCS5Padding -> bad decrypt
encrypt: SM4/CBC/PKCS5Padding decrypt: SM4/CBC/PKCS5Padding, same IV
In CBC a wrong IV raises no error: the first 16 bytes come out garbled and the rest decrypts normally. If only the start of your plaintext is broken, compare the IVs.
decrypt IV 00000000000000000000000000000000 -> 16 bytes of garbage + ": order 20260911-0042"
decrypt IV fedcba98765432100123456789abcdef -> "SM4 interop test: order 20260911-0042"
Base64 and hex are two ways of writing the same bytes. Reading one as the other gives the cipher the wrong input from the start.
Wi6BuLpov8RndEfedUyLXFvDRnLMoo7T6O04Q83IzKDuDvPQ2S5clq+cEQXMvy/y read as hex -> invalid
Wi6BuLpov8RndEfedUyLXFvDRnLMoo7T6O04Q83IzKDuDvPQ2S5clq+cEQXMvy/y read as Base64 -> 48 bytes
Zero padding cannot tell padding from data, so plaintext that really ends in 0x00 loses those bytes. Use PKCS#7 for anything that is not plain text.
zero padding: 61 62 00 -> decrypts to 61 62
PKCS#7: 61 62 00 -> decrypts to 61 62 00
OpenSSL treats sm4 as CBC. BouncyCastle — and therefore Hutool's SmUtil.sm4(key) — treats SM4 as ECB with PKCS#7. Two systems that both "just use SM4" can disagree on the mode.
Java: Cipher.getInstance("SM4") -> ECB + PKCS#7
OpenSSL: openssl enc -sm4 -> CBC Java: Cipher.getInstance("SM4/CBC/PKCS5Padding")
OpenSSL: openssl enc -sm4-cbc Java's getBytes() without a charset uses the platform default, which is GBK on a Chinese Windows JDK 17 or older. The same Chinese text then encrypts to different ciphertext, and the other side decrypts it to mojibake.
"国密SM4 test".getBytes() // GBK on a Chinese Windows JDK <= 17 -> ECB ciphertext 3188d06cf28db70092f8753cbd5ee518
"国密SM4 test".getBytes(StandardCharsets.UTF_8) -> ECB ciphertext d830308b0ae4fa7b9a2b5d59f7f65ca5
pay=100.00 into pay=900.00 and decryption still succeeds. Compute a MAC over the IV and ciphertext and check it before decrypting, for example with the HMAC generator.0123456789abcdeffedcba9876543210 read as hex is 16 bytes, but the same string read as text is 32 bytes and gets rejected. The format selector and the byte counter next to the key field are there to catch exactly this. PKCS5Padding is the same padding — BouncyCastle sends both names down the same code path. Zero padding appends 0x00 only up to the next block boundary. On decryption Hutool and BouncyCastle strip every trailing 0x00, including zero bytes that were really part of the data, while Python's gmssl strips only one. No padding requires the input to be a whole number of 16-byte blocks. CTR, CFB and OFB are stream modes and never pad. If decrypted text ends in stray spaces, boxes or line breaks, the padding was not removed: PKCS#7 data decrypted with no padding keeps n bytes of value n at the end (0x09, 0x0A and 0x0D show up as tabs and line breaks); switch the output to Hex and look at the last block. getBytes() on a Chinese Windows system — and how the result is printed: Base64, lowercase hex or uppercase hex. With identical settings and a fixed IV, two correct implementations produce identical output. If you suspect one of the tools, check both against the GB/T 32907 test vector first. 0123456789abcdeffedcba9876543210, one encryption must give 681edf34d206965e86b3e94f536e4246 and one million chained encryptions 595298c7c6fd271f0402f804c33d3f66. They test the block cipher only, so next encrypt some text in CBC with a fixed key and IV and compare against this page or the OpenSSL command it shows. The engine behind this page is tested against both vectors and against OpenSSL 3 in all five modes. openssl enc -sm4-cbc -K <32 hex digits> -iv <32 hex digits>: -K takes the raw key in hex, so no password is involved, -nopad turns PKCS#7 off, and -base64 -A reads or writes single-line Base64. Watch out for two things: plain -sm4 means CBC, and a -K value of the wrong length is truncated or zero-padded with only a warning. The OpenSSL panel on this page builds the command from your current settings; openssl enc has no zero padding, so the panel says so instead of printing a command that would not match. SmUtil.sm4(key) passes only the name SM4, and BouncyCastle fills in ECB with PKCS#7 (Java's PKCS5Padding); only a full string such as SM4/CBC/PKCS5Padding means CBC. In JavaScript, sm-crypto also defaults to ECB, takes the key as a 32-digit hex string and prints lowercase hex, while gm-crypt defaults to CBC, takes a 16-character text key and prints Base64. Then check the plaintext charset: Hutool's string methods always use UTF-8, but a bare getBytes() on JDK 17 or earlier on Chinese Windows can mean GBK, which changes the ciphertext. Pick the library under Match the defaults of to set these in one click, or enter them yourself; if one is uncertain, paste the ciphertext anyway and the auto-diagnosis tries the combinations of mode, padding, IV and encoding. Security Tools
Decrypt AES online — GCM/CBC/CTR, passphrase or raw key, auto-detects OpenSSL & CryptoJS "U2FsdGVkX1" format. 100% in-browser, keys never leave the page.
Security Tools
Free online AES encryption — AES-128/192/256, GCM/CBC/CTR, passphrase (PBKDF2) or raw key. Runs 100% in your browser; nothing is uploaded.
Security Tools
Generate and verify bcrypt password hashes online — adjustable cost, $2b$/$2a$/$2y$ prefixes. 100% in your browser; your password is never uploaded.
Security Tools
Paste hex or text and get all 63 CRC-8, CRC-16 and CRC-32 variants at once. Got a checksum you cannot match? Type it in and the tool names the variant — MODBUS, CCITT-FALSE, XMODEM, KERMIT. Runs entirely in your browser.
Security Tools
Free online HMAC generator & verifier — compute or verify HMAC-SHA256/SHA1/384/512 with Text, Hex or Base64 keys and Hex/Base64/Base64URL output. 100% in your browser; your secret key never leaves the page.
Security Tools
Decode JWT tokens online with our free JWT decoder. Instantly inspect header, payload, signature, expiration, algorithm, and claims. 100% browser-based — your token never leaves your device. No signup, no tracking.