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

Remove deprecated rustc-serialize crate #437

Open
BelfordZ opened this issue Jun 8, 2018 · 15 comments
Open

Remove deprecated rustc-serialize crate #437

BelfordZ opened this issue Jun 8, 2018 · 15 comments

Comments

@BelfordZ
Copy link

BelfordZ commented Jun 8, 2018

No description provided.

@sallar
Copy link

sallar commented Jun 8, 2018

Somebody has already submitted a PR for this, but it's from 1 year ago and apparently this project is dead.
#415

@BelfordZ
Copy link
Author

BelfordZ commented Jun 8, 2018

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

@sallar
Copy link

sallar commented Jun 8, 2018

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

@newpavlov
Copy link

@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
Copy link

sallar commented Jun 11, 2018

@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
Copy link

newpavlov commented Jun 11, 2018

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
Copy link

sallar commented Jun 11, 2018

@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:

  • PBKDF2 derivation
  • CBC Encryption
  • Hmac

Thanks!

@newpavlov
Copy link

newpavlov commented Jun 11, 2018

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
Copy link

sallar commented Jun 11, 2018

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:

  • What is the difference between aes_safe and aes?
  • I'm encrypting / decrypting a huge amount of text, not just 32 characters so that buffer probably wont work. That's why I had this (using old rust-crypto):
    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
Copy link

newpavlov commented Jun 11, 2018

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
Copy link

sallar commented Jun 11, 2018

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

@newpavlov
Copy link

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

@sallar
Copy link

sallar commented Jun 11, 2018

@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
Copy link

newpavlov commented Jun 11, 2018

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

  • SHA256_BLOCK_LEN should be AES256_BLOCK_LEN
  • .expect("HMAC Key is required.") is not strictly speaking correct, as HMAC can be initialized with any key-size, i.e. even empty slice will not produce error, so "HMAC can take key of any size" will be a better explanation.
  • don't unwrap on new_varkey, decrypt_pad and base64::decode, map error into your error type.
  • unwrap on encrypt_pad probably better replaced with expect("we ensure enough space for padding")
  • expand better replaced with extend_from_slice (I remembered about it after I've wrote the post)
  • looks like your forgot to remove rust-crypto-wasm from your Cargo.toml
  • it looks a bit strange to compute MAC over message encoded into base64, but I guess it's your protocol

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
Copy link

sallar commented Jun 12, 2018

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.

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