简体   繁体   中英

How can I change the return type of this function?

I'm going through the matasano crypto challenges using rust, with rust-crypto for the AES implementation. I have this function to do basic ECB mode encryption (basically taken nearly verbatim from the rust-crypto repository's example ):

pub fn aes_enc_ecb_128(key: &[u8], data: &[u8]) 
                       -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
    let mut encryptor = aes::ecb_encryptor(
            aes::KeySize::KeySize128,
            key,
            blockmodes::NoPadding);
    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(data);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = encryptor.encrypt(&mut read_buffer,
                                       &mut write_buffer,
                                       true);

        final_result.extend(write_buffer
                            .take_read_buffer()
                            .take_remaining().iter().map(|&i| i));
        match result {
            Ok(BufferResult::BufferUnderflow) => break,
            Ok(_) => {},
            Err(e) => return Err(e)
        }
    }

    Ok(final_result)
}

The above version compiles with no problem, and works as expected. However, to make it fit with the rest of my error handling scheme I'd like to change the return type to Result<Vec<u8>,&'static str> . This is the function with that change applied:

pub fn aes_enc_ecb_128(key: &[u8], data: &[u8]) 
                       -> Result<Vec<u8>, &'static str> {
    let mut encryptor = aes::ecb_encryptor(
            aes::KeySize::KeySize128,
            key,
            blockmodes::NoPadding);
    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(data);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = encryptor.encrypt(&mut read_buffer,
                                       &mut write_buffer,
                                       true);

        final_result.extend(write_buffer
                            .take_read_buffer()
                            .take_remaining().iter().map(|&i| i));
        match result {
            Ok(BufferResult::BufferUnderflow) => break,
            Ok(_) => {},
            Err(_) => return Err("Encryption failed")
        }
    }

    Ok(final_result)
}

When I attempt to compile this version, I get the following error (paths removed for clarity):

error: source trait is private
         let result = encryptor.encrypt(&mut read_buffer,
                                        &mut write_buffer,
                                        true);
error: source trait is private
let r = decryptor.decrypt(&mut read_buffer, &mut write_buffer, true);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The only way I've been able to change this type is to wrap the original function in a conversion function like this:

pub fn converted_enc(key: &[u8], data: &[u8]) 
                       -> Result<Vec<u8>, &'static str> {
   match aes_enc_ecb_128(key,data) {
       Ok(v) => Ok(v),
       Err(_) => Err("Encryption failed")
   } 
}

What should I do instead of the above in order to get the return value to fit with the rest of my API, and why is the more direct method failing?

I'm using the following versions of rust/cargo:

rustc 1.2.0-nightly (0cc99f9cc 2015-05-17) (built 2015-05-18)
cargo 0.2.0-nightly (ac61996 2015-05-17) (built 2015-05-17)

I think you have come across a bug of the compiler. Your code should compile

You can use crypto::symmetriccipher::Encryptor; as a workaround:

pub fn aes_enc_ecb_128(key: &[u8], data: &[u8]) 
                       -> Result<Vec<u8>, &'static str> {
    use crypto::symmetriccipher::Encryptor;
    let mut encryptor = aes::ecb_encryptor(
            aes::KeySize::KeySize128,
            key,
            blockmodes::NoPadding);
    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(data);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = encryptor.encrypt(&mut read_buffer,
                                       &mut write_buffer,
                                       true);

        final_result.extend(write_buffer
                            .take_read_buffer()
                            .take_remaining().iter().map(|&i| i));
        match result {
            Ok(BufferResult::BufferUnderflow) => break,
            Ok(_) => {},
            Err(_) => return Err("Encryption failed")
        }
    }

    Ok(final_result)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM