DaGenix / rust-crypto

A (mostly) pure-Rust implementation of various cryptographic algorithms.
Apache License 2.0
1.38k stars 296 forks source link

Remove deprecated rustc-serialize crate #437

Open BelfordZ opened 6 years ago

sallar commented 6 years ago

Somebody has already submitted a PR for this, but it's from 1 year ago and apparently this project is dead. https://github.com/DaGenix/rust-crypto/pull/415

BelfordZ commented 6 years ago

Lets give it a day or two for @DaGenix to get back to us about this, otherwise we should fork together @sallar =P

sallar commented 6 years ago

@belfordz Actually I have already forked it and made it wasm-friendly :) https://github.com/buttercup/rust-crypto-wasm

newpavlov commented 6 years ago

@sallar Take a look at RustCrypto organization, it aims to succeed rust-crypto crate by creating an ecosystem of crypto-crates, which are wasm and (if possible) no_std friendly.

sallar commented 6 years ago

@newpavlov I checked those and they look like they are on the correct path.. However half of the stuff is not implemented yet (for example AES encryption) and also the other half is undocumented.

newpavlov commented 6 years ago

AES encryption is implemented in aes-safe and aesni crates (the latter for now works only on Nightly, stable support will happen after SIMD stabilization), block modes of operation are available in the block-modes crate. I agree that RustCrypto/block-ciphers requires some work, particularity regarding documetnation. Can you provide list of algorithms in which you are interested?

sallar commented 6 years ago

@newpavlov I'm rewriting our password manager's internal encryption methods in Rust. But I was quite disappointed with the state of rust-crypto and ring and I had to fork and re-publish rust-crypto. If you check this file:

https://github.com/buttercup/crypto/blob/bbcd406644e4343dd00ebf4fb3ba00ae64834a22/src/encryption/cbc.rs

I'm using AES 256 CBC encryption/decryption and Hmac verification and generation. Also I'm doing Pbkdf2 Key derivation. So the things I need are:

Thanks!

newpavlov commented 6 years ago

PBKDF2 is implemented in pbkdf2 crate. You can use it like this:

use hmac::Hmac;
use sha2::Sha256;

pbkdf2::pbkdf2::<Hmac<Sha256>>(password, salt, complexity, &mut output_buf[..n]);

CBC encryption with aes_safe crate (in future you will be able to use just aes crate):

use block_modes::{BlockMode, BlockModeIv, Cbc};
use block_modes::block_padding::Pkcs7;
// you can change `aes_soft` on `aesni`, or use conditional compilation
use aes_soft::Aes256;

type AesCbc = Cbc<Aes256, Pkcs7>;

let mut cipher = AesCbc::new_varkey(key, iv).unwrap();
// buffer must have enough space for message+padding
let mut buffer = [0u8; 32];
buffer[..msg_len].copy_from_slice(msg);
let encrypted_msg = cipher.encrypt_pad(&mut buffer, msg_len).unwrap();

let mut cipher = AesCbc::new_varkey(key, iv).unwrap();
let decrypted_msg = cipher.decrypt_pad(encrypted_data).unwrap();

And for HMAC, crate documentation should be enough to start.

sallar commented 6 years ago

Thanks @newpavlov that is great information. I just used pbkdf2 and hmac from the crates you mentioned. Now I have to do the AES encryption. Two questions:

    let mut encryptor = cbc_encryptor(KeySize::KeySize256, key, &iv, blockmodes::PkcsPadding);
    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = RefReadBuffer::new(data);
    let mut buffer = [0; 4096];
    let mut write_buffer = RefWriteBuffer::new(&mut buffer);

    loop {
        let result = try!(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 {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => {}
        }
    }

how can I do this using the new method?

newpavlov commented 6 years ago

Glad to help! If you have all your data in a Vec<u8> and don't need streaming encryption, than this should do the work:

// `data` has type `Vec<u8>`
let msg_len = data.len();
// 16 is block size of AES-256, so this extension will be enough
data.extend_from_slice(&[0u8; 16]);
let encrypted_msg = cipher.encrypt_pad(&mut data, msg_len).unwrap();

// `decrypted_msg` slice points to the same underlying buffer used by `encrypted_data`
let decrypted_msg = cipher.decrypt_pad(&mut encrypted_data).unwrap();

In future we will probably add vector based convenience methods and integration with Read/Write traits.

sallar commented 6 years ago

@newpavlov seems like aes_safe doesn't exist. is aes_soft the same thing?

newpavlov commented 6 years ago

Ups, I've meant aes-soft of course.

sallar commented 6 years ago

@newpavlov Thanks a lot for all your help. I think I finally managed to do it. Would you be so kind and have a look at it to see if I've done anything stupid? https://github.com/buttercup/crypto/blob/30f80f3e9620b7e07bcb2daffbcd2d1b743737e5/src/encryption/cbc.rs

newpavlov commented 6 years ago

Several nitpicks after cursory read, but otherwise looks good to me!

Also if you have liberty to change protocol, I would strongly recommend to use Misuse Resistant Authenticated Encryption (MRAE) scheme, e.g. one implemented in the miscreant crate by @tarcieri, and argon2 instead of pbkdf2.

sallar commented 6 years ago

Thanks @newpavlov that is really valuable advice. I'll check that MRAE and I will fix the other issues :) Yeah we have been calculating base64 since our initial code is written in NodeJS and there you calculate Mac over a string and base64 has been the best option. But we can't change that now since this library will need to be compatible with our older ones.