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

feature request: add block_size method to BlockCipher #131

Closed
hxzhao527 opened this issue Jun 9, 2020 · 6 comments · Fixed by RustCrypto/traits#849
Closed

feature request: add block_size method to BlockCipher #131

hxzhao527 opened this issue Jun 9, 2020 · 6 comments · Fixed by RustCrypto/traits#849

Comments

@hxzhao527
Copy link

hxzhao527 commented Jun 9, 2020

describe & question

BlockCipher.encrypt work in-place, and no allocate. So I need to calculate the buffer size manually.
my question :

  • Is there any way to get block-size easily? not the wordy one.
  • can we add block_size method to BlockCipher?

my code

use std::error;

use aes::block_cipher::{generic_array::typenum::Unsigned, BlockCipher};
use aes::Aes128;
use block_modes::{block_padding::Pkcs7, BlockMode, Cbc};

type Aes128Cbc = Cbc<Aes128, Pkcs7>;
type Byte = u8;

fn aes128_cbc_encrypt(
    plaintext: &[Byte],
    key: &[Byte],
    iv: &[Byte],
) -> Result<Vec<Byte>, Box<dyn error::Error>> {
    // pading只是做对齐, 但是这个对齐是in-place, 这个buf还是需要自己申请大小以满足条件
    // pading just fill, no allocate
    // =======================================
    let block_size = <Aes128 as BlockCipher>::BlockSize::to_usize();
    let padding_length = block_size - plaintext.len() % block_size;
    // =======================================
    let cipher = Aes128Cbc::new_var(&key, &iv)?;

    let mut buffer = Vec::with_capacity(padding_length + plaintext.len());
    buffer.resize(padding_length + plaintext.len(), 0u8);
    // unsafe { buffer.set_len(padding_length+plaintext.len()); }
    buffer[..plaintext.len()].copy_from_slice(plaintext);

    //let ciphertext = cipher.encrypt(&mut buffer, plaintext.len())?;
    cipher.encrypt(&mut buffer, plaintext.len())?;
    Ok(buffer)
}

Cargo.toml

[dependencies]
block-modes="0.4.0"
aes="0.4.0
@tarcieri
Copy link
Member

tarcieri commented Jun 9, 2020

I think adding a block_size() method makes sense.

Kind of curious what you're trying to do there specifically and if we could add some additional higher level methods to help. Do you specifically need (unauthenticated) AES-CBC encryption?

@hxzhao527
Copy link
Author

Just transform golang to rust. 😂

In go, https://golang.org/pkg/crypto/cipher/#Block, provide a method BlockSize(), it is
convenient.

@tarcieri
Copy link
Member

Eventually they'll just be associated consts (after const generics land), but I agree for now having a method is easier than <Aes128 as BlockCipher>::BlockSize::to_usize()

@hxzhao527
Copy link
Author

you mean something like this?

pub trait BlockCipher {
    const Size: usize;
    fn block_size() -> usize {
        Self::Size
    }

    fn new() -> Self;
}

pub struct Aes {}

impl BlockCipher for Aes {
    const Size: usize = 1;
    fn new() -> Self {
        Self {}
    }
}

pub struct Cbc<C: BlockCipher> {
    cipher: C,
}
impl<C> Cbc<C>
where
    C: BlockCipher,
{
    fn encrypt(self, data: &str) {
        for _ in 0..C::block_size() {
            println!("data: {}", data);
        }
    }

    fn new() -> Self {
        Self { cipher: C::new() }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    type AesCbc = Cbc<Aes>;
    #[test]
    pub fn test_size() {
        println!("block_size: {}", Aes::block_size());
        let encryptor = AesCbc::new();
        encryptor.encrypt("hello");
    }
}

image

@tarcieri
Copy link
Member

What I'm talking about involves changes to the Rust language. Here's a blog post I wrote on the topic:

https://tonyarcieri.com/rust-in-2019-security-maturity-stability#const-generics-and-cryptography_2

@hxzhao527
Copy link
Author

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 a pull request may close this issue.

2 participants