Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help idiots like me better find cbc crate. #387

Closed
EvanCarroll opened this issue Sep 27, 2023 · 11 comments
Closed

Help idiots like me better find cbc crate. #387

EvanCarroll opened this issue Sep 27, 2023 · 11 comments

Comments

@EvanCarroll
Copy link

EvanCarroll commented Sep 27, 2023

There isn't a full example of a

  • pain text--> ciphertext
  • ciphertext to plaintext

Anywhere in this code base. The whole use of GenericArray is amazingly confusing. And it's inconsistent, the aes_gcm create uses array slices -- also in Rust Crypto. aes128 uses GenericArray, and there isn't a From implemented for Array slices. How do you take an array of bytes and get it to and from GenericArray? Please put some use cases in the code or in a testing suite or something.

It's not just me either,

https://stackoverflow.com/questions/69096150/how-to-decrypt-a-message-using-aes128cbc-rust

Even the most basic things with this module are incredibly complex

@tarcieri
Copy link
Member

There isn't a full example of a

pain text--> ciphertext
ciphertext to plaintext

It's right here: https://docs.rs/aes-gcm/latest/aes_gcm/#usage

The whole use of GenericArray is amazingly confusing.

We're migrating to hybrid-array in the next release. Do you have any more specific feedback on what you found confusing?

And it's inconsistent, the aes_gcm create uses array slices

Huh? Everything uses trait-based APIs. Arrays and slices are two different types, there's no such thing as an "array slice".

also in Rust Crypto. aes128 uses GenericArray, and there isn't a From implemented for Array slices.

Honestly your complaints are so vague I can't help you. Please look at the documentation I linked.

If you have more specific, non-vague criticisms, we can follow up.

@tarcieri tarcieri closed this as not planned Won't fix, can't repro, duplicate, stale Sep 27, 2023
@EvanCarroll
Copy link
Author

EvanCarroll commented Sep 27, 2023

I told you explicitly,

The whole use of GenericArray is amazingly confusing. And it's inconsistent, the aes_gcm create uses array slices -- also in Rust Crypto. aes128 uses GenericArray, and there isn't a From implemented for Array slices. How do you take an array of bytes and get it to and from GenericArray?

You provided a link to aes_gcm which does NOT use GenericArray, and uses slices. That's easy.

// ciphertext = &[u8];
let cipher = Aes128::new_from_slice(&get_key()).unwrap();


// code

cipher.<something>(cipertext, plaintext);

println!("ciphertext {:?}, plaintext {:?}", ciphertext, plaintext);

How do you decode that to a new array, plaintext? That seems very very simple. Where is this documented?

@tarcieri
Copy link
Member

tarcieri commented Sep 27, 2023

I think perhaps what's confusing you are the different requirements of an AEAD over a raw block cipher.

Block ciphers have fixed-sized inputs and outputs which are identical in size.

AEAD modes work on variable-sized inputs and outputs and have outputs which are larger than their inputs: they add an authentication tag which is typically 16 bytes.

The "inconsistency" you are complaining about is actually a discrepancy between the interfaces of the underlying cryptographic primitives: fixed-sized versus variable-sized inputs, which is why the aead crate doesn't have an array-based interface for its messages.

We express the additional overhead of the authentication tag using traits, however it is not possible on stable Rust to use associated constants of traits to determine the size of an array, far less perform arithmetic on it to compute the size of the output buffer with the added overhead of the authentication tag.

We do provide "detached" APIs which handle the authentication tag out-of-band and are more amenable for using a raw array as your input/output buffer. There isn't documentation for those as they are rarely used, but you can find them here:

https://docs.rs/aead/latest/aead/trait.AeadInPlace.html#tymethod.encrypt_in_place_detached

Can you explain why it's so critically important that you use a core array as your buffer? If you're merely on a heapless target, I would suggest reading the documentation for using heapless::Vec:

https://docs.rs/aes-gcm/latest/aes_gcm/#in-place-usage-eliminates-alloc-requirement

@EvanCarroll
Copy link
Author

EvanCarroll commented Sep 27, 2023

Can you explain why it's so critically important that you use a core array as your buffer? If you're merely on a heapless target, I would suggest reading the documentation for using heapless::Vec:

It's not at all important never mind "critically important", but it's not clear to me reading the documentation what I'm supposed to read or how I'm supposed to get to and from that type (assuming it's GenericArray). I don't see it documented anywhere. Ergo this issue. There is no example.

In Python, this is very simple. And the documentation is great, https://pycryptodome.readthedocs.io/en/latest/src/cipher/aes.html

cipher = AES.new(key, AES.MODE_CBC, IV=iv)
decrypted = cipher.decrypt(encrypted_value)

Where is the analog of this in Rust?

@tarcieri
Copy link
Member

The documentation for the CBC API is here: https://docs.rs/cbc/

Note that as is idiomatic in Rust, we use types/generics rather than runtime dispatch as in Python.

@newpavlov
Copy link
Member

GenericArray, and there isn't a From implemented for Array slices

Currently used versions of generic-array do support conversion from arrays of appropriate length using From and Into traits. The linked aes-gcm examples uses it here:

let key: &[u8; 32] = &[42; 32];
let key: &Key<Aes256Gcm> = key.into();

The first key variable is a reference to an array, while the second one is a reference to GenericArray<u8, U32> (it's aliased as Key for convenience).

@EvanCarroll
Copy link
Author

EvanCarroll commented Sep 27, 2023

Ahh, well that's the confusion. ding ding ding.

So in python this is called AES. You get to it with from Crypto.Cipher import AES. I went to cargo searched for "aes" and only this module showed up. Which makes no mention of CBC which has its own AES. So I wasn't aware of that at all. I knew I didn't want the aes-gcm (since I don't know what gcm is and it's not mentioned anywhere or explained here or present in Python). I found in this repo this source code,

https://github.com/RustCrypto/block-ciphers/blob/master/aes/src/lib.rs which I thought was the AES code, and I was trying to figure out how to use that. What I didn't know is that despite there being an aes::Aes128 in this repo, that's different from Aes128CbcDec in the cbc repo.

So thanks a billion for helping me out my man @tarcieri !

I thought I had no idea what I was doing, and it turned out I was even worse off then that.

Maybe this whole encryption ecosystem needs a mdbook or something that introduces adead/cbc and explains what to use where, because that Python code is very very simple, and there seems to be no guidance of how to do that in Rust.

It would probably be a good idea to link the cbc module in the docs too, since I'm probably not the only this confused. Seems like searching for "aes" in Cargo should show all things with AES and each option should differentiate from the others.

@tarcieri
Copy link
Member

TBD https://github.com/rustcrypto/book

@EvanCarroll
Copy link
Author

EvanCarroll commented Sep 27, 2023

Well, that's all this issue was about. I just wanted to say I was confused and trying to rtfm, but couldn't find out what to read and where. You got me exactly what I wanted, I'll go play with cbc now. Hope this gets fixed in cargo search though.

https://crates.io/search?q=aes

I would think cbc should be at the top of that list? Since that's what people know simply as AES in Python. It's not on the first page at all.

@tarcieri
Copy link
Member

We could probably link to the block mode crates from the aes docs to make them more discoverable

@EvanCarroll EvanCarroll changed the title add tests, and document this stuff. Help idiots like me better find cbc crate. Sep 27, 2023
@newpavlov
Copy link
Member

newpavlov commented Sep 27, 2023

I would think cbc should be at the top of that list?

Why would it be? CBC is a block mode (one of many), it can be used with any other block cipher. We could introduce various "combination" crates like aes-cbc, but I think they provide really low value outside of initial learning steps (which ideally should be covered by the book) at the cost of additional maintenance burden.

In RustCrypto we do things a bit different from how things are usually done in other languages, we write implementations in a highly modular way and heavily rely on generic implementations of cryptographic algorithms.

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

No branches or pull requests

3 participants