tc_des
DES and EDE Triple DES block ciphers for legacy interoperability, with
table-based and RustCrypto engines. Every engine implements the
tc_block_cipher traits, and a
dispatcher for each algorithm picks the less leaky engine the build provides.
Do not use DES or Triple DES in new designs.
The crate is no_std, needs no allocator and contains no unsafe code. It
depends on tc_block_cipher and tc_zeroize,
and on RustCrypto's des only with the
default-off rustcrypto feature.
Requires Rust 1.85 or later (edition 2024) for the default build. The optional
rustcrypto feature follows the minimum Rust version of the des crate
instead, which is 1.85 for des 0.9.0.
Types
DesEngine— DES on the RustCrypto engine withrustcrypto, otherwise on the table engine; variable time.DesEdeEngine— Triple DES, chosen the same way; variable time.DesTableEngine,DesEdeTableEngine— portable SP-box tables; variable time, with key setup that also branches on key bits.DesRustCryptoEngine,DesEdeRustCryptoEngine(rustcrypto) — RustCrypto'sdes; variable time, with smaller S-boxes and a branch-free key schedule.
DES takes an 8-byte encoded key; Triple DES takes 16 bytes, used as
K1, K2, K1, or 24 bytes. Another length returns InitError::InvalidKeyLength
and keeps the previous key. process_block transforms the first 8 bytes and
returns 8, returning BlockError::NotInitialised before init and
BlockError::BufferTooShort for a buffer shorter than a block, without
touching the output. Parity bits are ignored and weak keys are accepted.
Display writes "DES" or "DESede" without inspecting key material.
The constants DES_ALGO_NAME and DES_EDE_ALGO_NAME hold the two names,
DES_KEY_BYTES and DES_EDE_KEY_BYTES the accepted key lengths, [8] and
[16, 24], EDE2_KEY_BYTES and EDE3_KEY_BYTES the two Triple DES lengths,
and BLOCK_BYTES the block length, 8. Every engine implements Default and
has const fn new.
Features
rustcrypto(off by default) — adds the two RustCrypto engines, which the dispatchers then always use; pulls in thedescrate and its minimum Rust version.
Usage
[]
= "0.1.0"
= "0.1.0"
This example uses the NIST three-key Triple DES vector:
use ;
use ;
let key = ;
let plaintext = ;
let mut engine = new;
engine
.init
.expect;
let mut ciphertext = ;
assert_eq!;
assert_eq!;
The crate and engine documentation carry executable examples for every engine.
Security
Every engine is variable time. Each looks up S-boxes with secret data, so cache timing can leak the key, and the table engines' key setup also branches on key bits. The RustCrypto engines narrow that channel but do not close it; this crate provides no constant-time engine. Use it only where cache-timing leakage is outside the threat model.
Engines keep an expanded key schedule rather than borrowing the caller's key, and wipe it when it is replaced and on drop. Wiping does not reach the caller's key buffer or copies left in registers and on the stack.
This is a block-cipher primitive, not a message-encryption format. It supplies no padding, mode of operation or authentication.
Benchmarks
Key setup and single-block timings for the table and RustCrypto engines, and the commands to reproduce them, are in BENCHES.md.
Validation
The engines are tested against the standard DES vector, the FIPS 81 vector and
a weak-key vector, and against the two-key, three-key and NIST Triple DES
vectors, in both directions. Contract tests cover error state, untouched output
on errors, preserved output tails and ignored parity bits for every engine.
With rustcrypto, the table engines are cross-checked against RustCrypto's
des on pseudorandom keys and blocks, and the RustCrypto engines against the
table engines. A test requires every engine API to document whether it is
constant or variable time.
Missing public documentation and unsafe code are rejected by crate-level
lints.
Run these commands from the workspace root:
cargo test -p tc_des --locked
cargo test -p tc_des --locked --features rustcrypto
cargo clippy -p tc_des --all-targets --all-features --locked -- -D warnings
cargo fmt -p tc_des --check
cargo doc -p tc_des --no-deps --all-features --locked
Before a release, check the archive contents and run publication validation from a committed checkout:
cargo package -p tc_des --list --locked
cargo publish -p tc_des --dry-run --locked
The archive includes both license texts, this README, the changelog, the
benchmark results, the source, the integration tests and the benchmark. It must
not include target/ or other build artifacts.
License
Licensed under either the MIT license or the Apache License, Version 2.0, at your option.