Ciphers

ARIA (ECB)

South Korea's standard block cipher from RFC 5794. S-box rounds and a byte mixer on 16-byte blocks under the key sizes of AES. ECB with PKCS#7 padding.
IDaria62 / 72block · substitution-permutation
Cipher / SP network

ARIA (ECB)

Korea's AES sibling, the AES S-box plus one of its own and a mixer that undoes itself.

Keyspace
2^128, 2^192 or 2^256
Decode
same options back
Works on
UTF-8 or hex, hex out
Family
15 in sp network
required 1 / 2

Options

keystring
required
32, 48 or 64 hex digits, a 128, 192 or 256-bit key
bytesstring
default text
What the plain side is: text for UTF-8 text, or hex to read and write hex there, for bytes that are not text

Access

Createcreate("aria")
CLIciphers encode aria 'ATTACK AT DAWN' --key 0123456789abcdeffedcba9876543210
Tryplayground with the sample above
Kinaes, aes-cbc, aes-cfb, aes-ofb +10

ARIA is Korea's answer to AES. Korean cryptographers presented it in 2003. A year later KS X 1213 made it the national standard. RFC 5794 wrote it down in English in 2010. Same 16-byte block as AES. Same keys of 128, 192 or 256 bits. TLS got cipher suites for it in RFC 6209, and OpenSSL ships aria-128-ecb and friends. So a CTF can hand you a key and a hex blob and expect you to know what ARIA is. Now you don't even have to.

Here it runs on its own, in ECB, like camellia and serpent. UTF-8 text in, PKCS#7 padding, hex out.

ts
const aria = create("aria");
const key = "0123456789abcdeffedcba9876543210";
aria.encode("ATTACK AT DAWN", { key }).text; // "e372f8a14e6654bc1f325283f65fea91"
aria.decode("e372f8a14e6654bc1f325283f65fea91", { key }).text; // "ATTACK AT DAWN"

AES with a second S-box

Open the RFC and the first S-box looks familiar. It should. SB1 is the AES S-box, byte for byte. ARIA adds a second one, SB2, and then the inverses of both, SB3 and SB4. Four tables, but only two worth storing. The file keeps SB1 and SB2 as the RFC prints them and turns them inside out for the other two.

An odd round puts the 16 bytes through SB1, SB2, SB3, SB4, SB1, SB2 and so on. An even round uses the same boxes in the other order, SB3, SB4, SB1, SB2. That's the inverse of the odd one. Hold on to that, it comes back.

The mixer

After the S-boxes comes the diffusion layer, A. Each output byte is the XOR of seven input bytes. No multiplication, no polynomials, just XOR. Mix twice and you're back where you started, because A is an involution.

Why does that matter? An even round undoes the S-boxes of an odd one, and A undoes itself. So decryption is the same code as encryption. It just takes the round keys backwards, and all but the outer two go through A first. One function for both directions, and nobody had to write an inverse of anything.

A 128-bit key gets 12 rounds, 192 gets 14 and 256 gets 16. The last round skips A and XORs in one more round key instead.

Keys from 1/π

The key schedule needs three constants of 128 bits. Where do they come from? Together they're the first 384 bits of the fractional part of 1/π. Nothing up anyone's sleeve, just a number everyone can check.

The key is split into KL and KR, with zeros filling KR when the key is short. A tiny three-round Feistel cipher runs over them, the constants as its round keys. Every value in between gets kept. That gives four 128-bit words, W0 to W3. Each round key is one W XORed with the next W, rotated. The rotations go 19 and 31 bits to the right, then 61, 31 and 19 to the left. A few XORs and shifts per key, that's the whole schedule.

Checked against

RFC 5794 Appendix A for 128, 192 and 256-bit keys, both ways. Then every single-bit vector for all three key lengths. One bit set in the key over a zero block, or in the block under a zero key. That's 960 ciphertexts, checked by digest against OpenSSL. UTF-8 text with padding comes from openssl enc -aria-128-ecb and its 192 and 256-bit siblings.

How strong is it

RFC 5794 says the COSIC group at K.U.Leuven analysed it and found no security flaw. The block is 128 bits, so the Sweet32 collisions that hit Blowfish and Triple DES don't apply.

ECB is still ECB, though. Thirty-two As are two equal blocks, and they come out as two equal blocks:

ts
aria.encode("A".repeat(32), { key }).text;
// ea9e6c8c0631542a9cc5a4dc50406a73 ea9e6c8c0631542a9cc5a4dc50406a73 a0b65eafd1671fed1b1a138e5670141b

Spaces added to show the blocks. The last one is only padding.

A key that isn't 32, 48 or 64 hex digits is an InvalidOptionError, a missing one a MissingOptionError. On decode, ciphertext that isn't whole 16-byte blocks of hex is a CipherError. A wrong key almost always breaks the padding, and that's a CipherError too. So are decrypted bytes that aren't UTF-8.

Plain TypeScript, not constant time. Puzzles and learning, not secrets.