Camellia (ECB)
Camellia (ECB)
Blocks and keys the size of AES, but Feistel rounds inside and an FL layer every six.
- Keyspace
- 2^128, 2^192 or 2^256
- Decode
- same options back
- Works on
- UTF-8 or hex, hex out
- Family
- 10 in feistel
Options
Access
- Create
create("camellia") - CLI
ciphers encode camellia 'ATTACK AT DAWN' --key 0123456789abcdeffedcba9876543210 - Tryplayground with the sample above
- Kindes, desx, triple-des, triple-des-cbc +5
Camellia is what you get when someone takes the outside of AES and builds a Feistel cipher in it. Same 16-byte block. Same keys of 128, 192 or 256 bits. NTT and Mitsubishi Electric published it in 2000, and RFC 3713 wrote it down in 2004. TLS got cipher suites for it, OpenSSL ships camellia-128-ecb and friends, and OpenPGP has ids for it. So it sits right next to AES in cipher lists. A CTF hands over a key and a hex blob, and now you can try it here.
Here it runs on its own, in ECB, like serpent and cast5. UTF-8 text in, PKCS#7 padding, hex out.
const camellia = create("camellia");
const key = "0123456789abcdeffedcba9876543210";
camellia.encode("ATTACK AT DAWN", { key }).text; // "4fd50f17717460459c4924d6c54d4881"
camellia.decode("4fd50f17717460459c4924d6c54d4881", { key }).text; // "ATTACK AT DAWN"
That key is the one RFC 3713 uses for its own vectors. The plaintext there is the same 16 bytes, which saves some typing.
What a round does
The block splits into two 64-bit halves. Each round takes one half and XORs in a 64-bit subkey. The eight bytes go through the S-boxes and get mixed. The result goes into the other half with another XOR. Classic Feistel.
What isn't classic is the FL layer. Every six rounds the left half goes through FL and the right one through its inverse, FLINV. Both are just AND, OR, XOR and a one-bit rotation under a subkey. Decryption doesn't need its own code for any of it. Same rounds, subkeys in reverse.
A 128-bit key gets 18 rounds and two FL layers. A 192 or 256-bit key gets 24 rounds and three. Before the first round and after the last, 128 bits of subkey get XORed into the block. Edges covered.
One S-box, four views
The RFC lists four S-boxes, but only SBOX1 is a real table. SBOX2 is SBOX1 with its output rotated left by one bit, SBOX3 by seven. SBOX4 rotates the input instead. So the file stores one table of 256 bytes. A script lifted it from the RFC text, and the other three come from it on the fly.
Constants with nothing up their sleeve
The key schedule needs six 64-bit constants, Sigma1 to Sigma6. Where do they come from? Square roots of the first six primes. Take √2 in hex, 1.6a09e667f3bcc908b.... Skip the first digit after the point, and the next sixteen are Sigma1, a09e667f3bcc908b. Same for 3, 5, 7, 11 and 13.
If 6a09e667 looks familiar, it should. That's the first word SHA-256 starts from, cut from the same √2 one digit earlier. Two designs, one square root.
The key itself is KL, plus KR for a longer one. The schedule runs them through four Feistel rounds, the first four constants as round keys. Out comes a new 128-bit value, KA. A longer key takes two more rounds over KA and KR for one more, KB. Every subkey is then KL, KR, KA or KB rotated and cut in half.
A 192-bit key has a funny detail. Its last 64 bits get the bitwise complement of themselves glued on, to fill out a second 128-bit half. So the 192-bit key runs the 256-bit schedule with a padding nobody had to choose.
Checked against
RFC 3713 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 -camellia-128-ecb and its 192 and 256-bit siblings.
How strong is it
RFC 3713 says the designers found no differential or linear characteristic with a probability above 2^-128. Not a proof, but that's a very small number. The block is 128 bits, so the Sweet32 collisions that hit Blowfish and Triple DES aren't a problem here either.
ECB is still ECB, though. Thirty-two As are two equal blocks, and they come out as two equal blocks:
camellia.encode("A".repeat(32), { key }).text;
// 8f10832469f75a47e01e38ea2ad51c70 8f10832469f75a47e01e38ea2ad51c70 06adf69db3fcae972cfbf7e49b799450
Spaces added to show the blocks. The last one is only padding.
Got a PGP message encrypted with Camellia? Hand it to openpgp. All three key sizes open there. So does the OCB kind from gpg --force-ocb.
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.