Skip to content

SM4 Encrypt & Decrypt Online

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.

No Tracking Runs in Browser Free
Encryption runs entirely in your browser — the key and data you enter never leave this device.
Ciphertext
Equivalent OpenSSL command

Needs OpenSSL 3. The command contains the key you entered.

SM4 test vectors from GB/T 32907-2016

Computed at build time by the engine this page runs — check your own SM4 implementation against them.
Key 0123456789abcdeffedcba9876543210
Plaintext 0123456789abcdeffedcba9876543210
Ciphertext, 1 encryption 681edf34d206965e86b3e94f536e4246
Ciphertext, 1,000,000 encryptions 595298c7c6fd271f0402f804c33d3f66
The SM4 engine is tested against both GB/T 32907-2016 Appendix A vectors and cross-checked with OpenSSL 3 in ECB, CBC, CTR, CFB and OFB. Library defaults were checked by running OpenSSL, Node.js, sm-crypto, gm-crypt, gmssl and two Go libraries, and by reading the Hutool and BouncyCastle source. — Go Tools Security Team · Sep 11, 2026

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.

SM4 quick answers

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.

GB/T 32907 test vector

681edf34d206965e86b3e94f536e4246 With key and plaintext 0123456789abcdeffedcba9876543210, one encryption gives 681edf34d206965e86b3e94f536e4246.

SM4 block size and rounds

32 rounds 16-byte (128-bit) blocks, encrypted in 32 rounds.

Does a wrong IV always cause an error in CBC?

first 16 bytes No. Only the first 16 bytes decrypt wrongly, and the padding in the last block still checks out.

What is SM4?

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

SM4 tool features

Tells you why decryption failed

When decryption fails, the page retries ciphertext encoding, key format, mode, IV, padding and text encoding, and shows the settings that produce readable text.

Library presets for the usual suspects

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.

Five modes, three paddings, UTF-8 or GBK

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.

SM4 key and IV: random, or as hex, text or Base64

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.

GB/T 32907 test vectors on the page

Both Appendix A results are printed in a table and loadable with one click, so you can check any SM4 implementation against the standard.

Equivalent OpenSSL command

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.

Runs entirely in your browser

The SM4 engine runs locally. Keys and data never leave the page, and the tool keeps working offline.

SM4 defaults in common libraries

OpenSSL 3 (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.

Java: Hutool SmUtil.sm4(key)

ECB · PKCS#7

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).

Java: BouncyCastle Cipher.getInstance("SM4")

ECB · PKCS#7

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.

JavaScript: sm-crypto

ECB · hex key

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.

JavaScript: gm-crypt

CBC · text key · Base64

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.

Python: gmssl CryptSM4

PKCS#7 · key cut to 16 bytes

You 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.

Go: tjfoc/gmsm sm4

zero IV by default

Sm4Cbc 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.

SM4 encryption and decryption examples

GB/T 32907 test vector (ECB, no padding)

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.

CBC with PKCS#7: text in, Base64 out

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.

Wrong IV in CBC: only the first 16 bytes break

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.

How to use the SM4 encrypt and decrypt tool

  1. 1

    Pick a library preset, or the mode and padding

    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.

  2. 2

    Enter the key and IV

    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.

  3. 3

    Paste the input

    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.

  4. 4

    Copy the result or check the round trip

    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.

  5. 5

    If decryption fails, read the diagnosis

    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.

Why SM4 decryption fails

Reading a hex key as text

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.

✗ Wrong
Key (text): 0123456789abcdeffedcba9876543210  -> 32 bytes, rejected
✓ Correct
Key (hex):  0123456789abcdeffedcba9876543210  -> 16 bytes

Decrypting CBC ciphertext as ECB

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.

✗ Wrong
encrypt: SM4/CBC/PKCS5Padding
decrypt: SM4/ECB/PKCS5Padding  -> bad decrypt
✓ Correct
encrypt: SM4/CBC/PKCS5Padding
decrypt: SM4/CBC/PKCS5Padding, same IV

Using a different 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.

✗ Wrong
decrypt IV 00000000000000000000000000000000
-> 16 bytes of garbage + ": order 20260911-0042"
✓ Correct
decrypt IV fedcba98765432100123456789abcdef
-> "SM4 interop test: order 20260911-0042"

Treating Base64 ciphertext as hex

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.

✗ Wrong
Wi6BuLpov8RndEfedUyLXFvDRnLMoo7T6O04Q83IzKDuDvPQ2S5clq+cEQXMvy/y  read as hex -> invalid
✓ Correct
Wi6BuLpov8RndEfedUyLXFvDRnLMoo7T6O04Q83IzKDuDvPQ2S5clq+cEQXMvy/y  read as Base64 -> 48 bytes

Zero padding deleting real trailing zeros

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.

✗ Wrong
zero padding: 61 62 00  -> decrypts to 61 62
✓ Correct
PKCS#7:       61 62 00  -> decrypts to 61 62 00

Assuming "SM4" means the same mode everywhere

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.

✗ Wrong
Java:    Cipher.getInstance("SM4")  -> ECB + PKCS#7
OpenSSL: openssl enc -sm4           -> CBC
✓ Correct
Java:    Cipher.getInstance("SM4/CBC/PKCS5Padding")
OpenSSL: openssl enc -sm4-cbc

Encrypting GBK bytes on one side and UTF-8 on the other

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.

✗ Wrong
"国密SM4 test".getBytes()  // GBK on a Chinese Windows JDK <= 17
-> ECB ciphertext 3188d06cf28db70092f8753cbd5ee518
✓ Correct
"国密SM4 test".getBytes(StandardCharsets.UTF_8)
-> ECB ciphertext d830308b0ae4fa7b9a2b5d59f7f65ca5

When you need SM4 encryption online

Match SM4 output between backend and frontend
Your Java service and your web client produce different ciphertext for the same text. Reproduce each side here with its library preset and see which parameter differs.
Debug a failed decryption from a partner system
A partner sends SM4 ciphertext that will not decrypt. Paste it with the agreed key and IV and let the diagnosis find the mode, padding or encoding they actually used.
Verify an SM4 implementation
Run your code against the GB/T 32907 vectors on this page, then compare a CBC round trip, before the implementation goes anywhere near production data.
Prepare test data for a migration to SM4
When a system moves from AES to SM4, generate known key, IV and ciphertext triples here to use as fixtures in the new tests.
See how block cipher modes behave
Encrypt two identical blocks in ECB and CBC, or decrypt with a wrong IV, and watch what changes in the ciphertext and in the output.

How SM4 and its modes work

Block size, key size and rounds
SM4 encrypts 128-bit blocks under a 128-bit key in 32 rounds. Each round applies an 8-bit S-box to a 32-bit word and then a linear transformation that XORs the word with four rotations of itself. Decryption runs the same 32 rounds with the round keys in reverse order.
ECB: every block on its own
ECB encrypts each 16-byte block independently. It needs no IV, but equal plaintext blocks become equal ciphertext blocks, so patterns in the data remain visible. It needs padding unless the input is a multiple of 16 bytes.
CBC: chained blocks and an IV
CBC XORs each plaintext block with the previous ciphertext block before encrypting, and uses the IV for the first block. Because the IV only enters the first block, a wrong IV corrupts exactly the first 16 bytes of the plaintext and leaves the padding in the last block intact, so there is often no error at all.
CTR, CFB and OFB: SM4 as a stream cipher
These modes encrypt a counter or feedback value and XOR the result with the data, so the ciphertext is as long as the plaintext and there is no padding. In CTR the whole 16-byte IV is incremented as one 128-bit big-endian counter, matching OpenSSL. A wrong IV garbles the entire message in CTR and OFB, but only the first block in CFB.
Padding rules
PKCS#7 adds 1 to 16 bytes of value n, so a message that is already a whole number of blocks still gets a full block of padding. Zero padding adds 0x00 bytes only when needed and strips all trailing zeros when decrypting. No padding leaves the data as it is and rejects input that does not fill whole blocks.

SM4 encryption best practices

Do not choose ECB for new designs
ECB leaks which blocks are equal. Use CBC or CTR unless you are matching an existing system that already uses ECB.
Use a fresh random IV for every message
The IV is not secret, but it must not repeat under the same key. Generate it randomly for each message and store or send it next to the ciphertext.
Authenticate the ciphertext
GB/T 17964-2021, the Chinese standard on block cipher modes, states that the modes it describes protect confidentiality, not integrity. In CBC, changing one byte of the IV turns 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.
Write every parameter into the interface spec
"SM4 encrypted" is not a specification. Write down the mode, padding, how the key and IV are encoded, the plaintext character set and whether the ciphertext is hex or Base64.
Keep real keys out of web pages and source code
Use this page with test keys. Production keys belong in a key management system or hardware security module, loaded at run time rather than pasted or committed.

SM4 encryption FAQ

Why does my SM4 decryption fail with a padding error or garbled text?
Decryption only works when everything matches the encrypting side: the key bytes, the mode, the IV, the padding, and how the ciphertext was written down (hex or Base64). The error you get — "bad decrypt", a padding exception, or a screen of garbage — does not say which one is off, and some libraries return empty output instead of any error. Paste the ciphertext, key and IV here anyway. When decryption fails, the page retries every combination of ciphertext encoding, key format, mode, IV and padding — including keys a library silently cut to 16 bytes and plaintext encoded as GBK — and lists the readings that produce readable text, marking those whose PKCS#7 padding checked out. If only the first 16 bytes come out wrong, the key and mode are right and the IV is not.
How long is an SM4 key, and can it be 256 bits?
An SM4 key is exactly 128 bits, or 16 bytes — the same size as the block. GB/T 32907 defines only this one key length; there is no 192- or 256-bit SM4. If someone asks for a 256-bit SM4 key, check whether a 32-digit hex string was counted as 32 characters of 8 bits each. Sixteen bytes can be written as 32 hex digits or as 16 ASCII characters, and mixing the two up is the most common key error: 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.
What is the SM4 IV, and how long must it be?
The IV (initialization vector) is a 16-byte value mixed into the first block in CBC, CTR, CFB and OFB; ECB does not use one. It must be exactly 16 bytes — 32 hex digits or 16 ASCII characters — so if you get an IV length error, check whether a 32-digit hex string was read as 32 bytes of text. The IV is not secret, but it must not repeat under the same key: generate it randomly and send it with the ciphertext, often in front of it. A wrong IV in CBC usually raises no error and only garbles the first 16 bytes. Some libraries silently use an all-zero IV when none is given (sm-crypto-v2, Go's tjfoc/gmsm), while Java's BouncyCastle generates a random one — if that IV is not stored with the ciphertext, nobody can decrypt it.
What is the difference between SM4 ECB and CBC, and which should I use?
Use CBC (or CTR) with a fresh random IV for every message. ECB encrypts equal 16-byte blocks to equal ciphertext blocks, so repeated structure in the data shows through in the ciphertext. Choose ECB only to talk to a system that already uses it. Note that neither mode detects tampering: if that matters, send a MAC over the IV and ciphertext as well, for example with the HMAC generator.
Which SM4 padding should I use: PKCS5Padding, PKCS#7, zero padding or no padding?
PKCS#7 always appends 1 to 16 bytes, each holding the number of bytes added, so the receiver can strip it without ambiguity. For a 16-byte block cipher like SM4, Java's 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.
How long is SM4 ciphertext, and can I tell the mode from it?
Count in bytes. With PKCS#7 in ECB or CBC, the plaintext is rounded up to the next multiple of 16, and a message that is already a multiple of 16 gets one more full block — 5 or 15 bytes become 16, and 16 bytes become 32. Zero padding only fills to the next multiple of 16, no padding keeps the length, and CTR, CFB and OFB ciphertext is exactly as long as the plaintext. Hex doubles the byte count; Base64 takes 4 × ⌈bytes / 3⌉ characters, so 16 bytes are 24 characters, 32 are 44 and 64 are 88. Add 16 bytes if the IV is carried in front. The ciphertext alone does not reveal the mode, but two clues help: a length that is not a multiple of 16 all but rules out padded ECB or CBC, and two identical 16-byte blocks point to ECB. If unsure, paste it into the decrypt tab and the auto-diagnosis tries the modes for you.
Does SM4 give the same ciphertext every time, and why does another tool's differ?
ECB — or any mode with a fixed IV — gives the same ciphertext every time for the same key and plaintext; with a fresh random IV each run, the output changes every time, as it should. Beyond that, compare the mode, the padding, whether the key was read as hex or text, how the plaintext was encoded — UTF-8 in most code, but GBK when older Java code calls 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.
How can I check that my own SM4 implementation is correct?
Start with the two vectors from GB/T 32907-2016 Appendix A. With key and plaintext both 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.
Can OpenSSL encrypt and decrypt SM4?
Yes. OpenSSL 3 includes SM4 in ECB, CBC, CFB, OFB and CTR. Use 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.
How do I decrypt SM4 ciphertext from Java (Hutool) or JavaScript (sm-crypto)?
First find out which mode and padding the other side really uses — often the code never says. Hutool's 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.
Is SM4 secure, and is my data uploaded?
As an algorithm, SM4 uses a 128-bit key and 32 rounds; RFC 8998 (2021) states that at the time of writing no weak keys or security issues were known for SM4. The practical risks come from how it is used: ECB leaks patterns and CBC does not detect tampering. As for this page, nothing is uploaded. Browsers do not ship SM4, so this page carries its own SM4 implementation and runs it locally; you can open the network panel and watch no request go out, or disconnect and keep using the tool. That makes it fine for test data, debugging and learning. It does not make a web page the right place for production keys: those belong in a key management system or hardware module, not in a text box on any website.
What is the difference between SM4 and AES?
Both are block ciphers with 128-bit blocks, and the modes and padding work the same way for both — which is why SM4 interoperability bugs look exactly like AES ones. SM4 runs 32 rounds and has a single key size of 128 bits; AES-128 runs 10 rounds, and AES also has 192- and 256-bit keys. SM4 is China's national standard GB/T 32907-2016 and, since 2021, part of the international standard ISO/IEC 18033-3 next to AES; it is used where Chinese commercial cryptography is required. AES is the NIST standard FIPS 197. For AES, use the AES encryption tool.

Related Tools

View all tools →