rust-crypto
rust-crypto copied to clipboard
Remove deprecated rustc-serialize crate
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
Lets give it a day or two for @DaGenix to get back to us about this, otherwise we should fork together @sallar =P
@belfordz Actually I have already forked it and made it wasm-friendly :) https://github.com/buttercup/rust-crypto-wasm
@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.
@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.
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?
@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!
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.
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?
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.
@newpavlov seems like aes_safe doesn't exist. is aes_soft the same thing?
Ups, I've meant aes-soft
of course.
@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
Several nitpicks after cursory read, but otherwise looks good to me!
-
SHA256_BLOCK_LEN
should beAES256_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
andbase64::decode
, map error into your error type. -
unwrap
onencrypt_pad
probably better replaced withexpect("we ensure enough space for padding")
-
expand
better replaced withextend_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.
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.