DES (ECB)
- create
- create("des")
- family
- Feistel
- options
- --key
- self-inverse
- no
- keyspace
- 2^56 keys (the 8 parity bits of the 64-bit key do nothing)
- try it
- ciphers des "ATTACK AT DAWN" --key 0123456789abcdef
DES came out of IBM, got picked by the US National Bureau of Standards and went out as FIPS 46 in 1977. For twenty years it was the cipher. The block is 64 bits and so is the key, but the last bit of every key byte is parity and nothing reads it. That leaves 56 bits. The key here is 16 hex digits, case doesn't matter and spaces are ignored.
Text goes in as UTF-8 with PKCS#7 padding, ciphertext comes out as lowercase hex, and decode wants hex back. The mode is ECB, same as Triple DES.
const des = create("des");
const key = "0123456789abcdef";
des.encode("ATTACK AT DAWN", { key }).text; // "66e43480bc9810be67812271f1ee04a0"
des.decode("66e43480bc9810be67812271f1ee04a0", { key }).text; // "ATTACK AT DAWN"
OpenSSL agrees, but since 3.0 single DES lives in the legacy provider:
printf %s "ATTACK AT DAWN" | openssl enc -des-ecb -provider legacy -provider default -K 0123456789abcdef | xxd -p
The tests start from the ECB example in FIPS 81, Now is the time for all under this same key, three blocks. Then Grabbe's walkthrough from "The DES Algorithm Illustrated" and a few known answers from NIST SP 800-17.
One DES, three DES
This is the same DES that Triple DES runs three times. Give Triple DES one key three times and the middle decryption undoes the first encryption, so what's left is this:
des.encode("ATTACK AT DAWN", { key: "133457799bbcdff1" }).text;
// "1739739759a5caa5b6544c0af3cad197"
create("triple-des").encode("ATTACK AT DAWN", { key: "133457799bbcdff1".repeat(3) }).text;
// "1739739759a5caa5b6544c0af3cad197"
Weak keys
A few keys make all 16 round keys the same. 0101010101010101 is one of them. Under such a key the rounds read the same forwards and backwards, so encrypting twice gives the text back. FIPS 74 lists four of these and twelve semi-weak ones that come in pairs. Nothing here rejects them, so they're good for poking at.
Why ECB leaks
Sixteen As are two equal blocks, and they come out as two equal blocks:
des.encode("A".repeat(16), { key }).text;
// a827de10956a609d a827de10956a609d 086f9a1d74c94d4e
Spaces added to show the blocks. The last one is only padding.
A key that isn't 16 hex digits is an InvalidOptionError, a missing one a MissingOptionError. On decode, ciphertext that isn't whole 8-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.
The cipher itself held up well. Differential and linear cryptanalysis both beat brute force on paper, but they want an unrealistic pile of chosen or known plaintexts. The key is what gave out. In 1998 the EFF built Deep Crack and found a DES key in 56 hours. A year later, together with distributed.net, it took 22 hours and 15 minutes. NIST withdrew FIPS 46-3 in 2005. This one is plain TypeScript over bit arrays, slow and not constant time. Puzzles and learning, not secrets.