ok-ready-go/crypto_helper/src/crypto.rs

62 lines
1.9 KiB
Rust

use pbkdf2::{self, password_hash::PasswordHasher};
use base64::{Engine as _};
use generic_array::typenum::{UInt, B1, B0, UTerm, U32};
use wasm_bindgen::prelude::*;
use aes_gcm::{
aead::{Aead, KeyInit, generic_array::GenericArray},
Aes256Gcm
};
#[wasm_bindgen]
pub struct Crypto {
iv: IV,
c: Aes256Gcm
}
type Key = GenericArray<u8, U32>;
type IV = GenericArray<u8, UInt<UInt<UInt<UInt<UTerm, B1>, B1>, B0>, B0>>;
#[wasm_bindgen]
impl Crypto {
#[wasm_bindgen(constructor)]
pub fn new(password: &str, salt: &str) -> Self {
super::utils::set_panic_hook();
let key = Self::_pbkdf2(password, salt, 1000, 32);
let iv = Self::_pbkdf2(password, salt, 5000, 12);
println!("Key {}\nIV {}", hex::encode(&key), hex::encode(&iv));
let iv: IV = GenericArray::clone_from_slice(&iv);
let key: &Key = GenericArray::from_slice(&key);
let c = Aes256Gcm::new(key);
Crypto { iv: iv, c:c }
}
pub fn sha256(input: &str) -> String {
sha256::digest(input)
}
fn _pbkdf2(password: &str, salt: &str, rounds: u32, output_length: usize) -> Vec<u8> {
let params = pbkdf2::Params { rounds: rounds, output_length: output_length };
let salt = base64::engine::general_purpose::STANDARD_NO_PAD.encode(salt);
let salt = pbkdf2::password_hash::Salt::new(&salt).unwrap();
let res = pbkdf2::Pbkdf2.hash_password_customized(password.as_bytes(), None, None, params, salt).unwrap();
res.hash.unwrap().as_bytes().to_owned()
}
pub fn encrypt(&self, plaintext: &str) -> String {
base64::engine::general_purpose::STANDARD_NO_PAD.encode(self.c.encrypt(&self.iv, plaintext.as_bytes()).unwrap())
}
pub fn decrypt(&self, ciphertext: &str) -> String {
let ciphertext = base64::engine::general_purpose::STANDARD_NO_PAD.decode(ciphertext).unwrap();
String::from_utf8(self.c.decrypt(&self.iv, &*ciphertext).unwrap()).unwrap()
}
}