Skip to content

ssh-cipher: consolidate aes feature; extract Aes type#530

Merged
tarcieri merged 1 commit into
masterfrom
ssh-cipher/dynamic-aes-key-size
May 22, 2026
Merged

ssh-cipher: consolidate aes feature; extract Aes type#530
tarcieri merged 1 commit into
masterfrom
ssh-cipher/dynamic-aes-key-size

Conversation

@tarcieri

Copy link
Copy Markdown
Member

Combines the aes-cbc, aes-ctr, and aes-gcm features into a single aes feature which provides them all.

Additionally refactors the internals of Encryptor and Decryptor around a new Aes type which provides an enum over the 128-bit, 192-bit, and 256-bit key sizes, and dynamically selects which one based on the provided key size.

This type impls the BlockCipherDecrypt, BlockCipherEncrypt, and BlockSizeUser traits which delegate to the inner cipher, since once initialized with a key the API provided by the cipher is the same. These delegate to the respective AES implementations for various key sizes.

Because it impls these traits, we're able to use it directly with types like cbc::{Encryptor, Decryptor} and Ctr128BE, collapsing the combinatorial explosion of key sizes and block modes down to just one enum variant per block mode.

@tarcieri tarcieri requested a review from newpavlov May 22, 2026 15:16
@tarcieri

Copy link
Copy Markdown
Member Author

Note: I think this approach can be further continued by making ssh_cipher::{Encryptor, Decryptor} generic around the underlying block cipher, which would make it possible for those types to impl BlockModeEncrypt and BlockModeDecrypt respectively, but I've deferred those for a followup.

Comment thread ssh-cipher/src/aes.rs
Comment on lines +9 to +16
/// Advanced Encryption Standard (AES) low-level block cipher.
///
/// Supports 128-bit, 192-bit, and 256-bit key sizes.
pub(crate) enum Aes {
Aes128(Aes128),
Aes192(Aes192),
Aes256(Aes256),
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@newpavlov I wonder if something like this would be useful in the aes crate itself (or perhaps a single type that supports all three key sizes and can dynamically select which one at runtime without having to monomorphize the full code three times)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could try it, but on the first glance it's likely to be a pretty annoying addition implementation-wise.

@tarcieri tarcieri May 25, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could use this enum-based implementation for now. It's simple enough.

The version on master hides it inside a wrapper struct, which would futureproof a possible conversion to support dynamic key sizes in the future while making it possible to support them today:

https://github.com/RustCrypto/SSH/blob/master/ssh-cipher/src/block_cipher/aes.rs

One drawback is we don't really have a trait like KeyInit that supports dynamic key sizes like this. It'd basically be KeyInit::new_from_slice split out into its own trait so there's no bound on KeySizeUser. Though I suppose TryFrom<&[u8], Error = InvalidLength> could probably get the job done for now.

@newpavlov newpavlov May 27, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just use 256 bits as the default key size, since we usually use the largest supported key size for ciphers which support variable key sizes.

But looking at the code, I am not sure that the Aes enum is a good solution, personally I prefer the old enum with separate Aes128/192/256Cbc variants. It branches only ones, while with Aes you can potentially have multiple unnecessary branches while dealing with the mode.

Combines the `aes-cbc`, `aes-ctr`, and `aes-gcm` features into a single
`aes` feature which provides them all.

Additionally refactors the internals of `Encryptor` and `Decryptor`
around a new `Aes` type which provides an enum over the 128-bit,
192-bit, and 256-bit key sizes, and dynamically selects which one based
on the provided key size.

This type impls the `BlockCipherDecrypt`, `BlockCipherEncrypt`, and
`BlockSizeUser` traits which delegate to the inner cipher, since once
initialized with a key the API provided by the cipher is the same. These
delegate to the respective AES implementations for various key sizes.

Because it impls these traits, we're able to use it directly with types
like `cbc::{Encryptor, Decryptor}` and `Ctr128BE`, collapsing the
combinatorial explosion of key sizes and block modes down to just one
enum variant per block mode.
@tarcieri tarcieri force-pushed the ssh-cipher/dynamic-aes-key-size branch from 408527f to ba022d6 Compare May 22, 2026 15:21
@tarcieri tarcieri merged commit 7b98c13 into master May 22, 2026
22 checks passed
@tarcieri tarcieri deleted the ssh-cipher/dynamic-aes-key-size branch May 22, 2026 16:15
@tarcieri tarcieri mentioned this pull request Jun 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants