mirror of https://github.com/CympleTech/ESSE.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.2 KiB
107 lines
3.2 KiB
use aes_gcm::{ |
|
aead::{generic_array::GenericArray, Aead, NewAead}, |
|
Aes256Gcm, |
|
}; |
|
use sha2::{Digest, Sha256}; |
|
|
|
const FIX_PADDING: [u8; 19] = [ |
|
69, 83, 83, 69, 70, 111, 114, 68, 97, 116, 97, 83, 101, 99, 117, 114, 105, 116, 121, |
|
]; |
|
|
|
/// Hash the given pin. |
|
pub fn hash_pin(salt: &[u8], pin: &str, index: i64) -> Vec<u8> { |
|
let mut hasher = Sha256::new(); |
|
hasher.update(salt); // for avoid same hash when no-pin in other derives. |
|
hasher.update(pin.as_bytes()); |
|
hasher.update(index.to_le_bytes()); // for avoid same hash when no-pin in one device. |
|
hasher.finalize().to_vec() |
|
} |
|
|
|
/// check the pin is the given hash pre-image. |
|
pub fn check_pin(salt: &[u8], pin: &str, index: i64, hash: &[u8]) -> bool { |
|
let mut hasher = Sha256::new(); |
|
hasher.update(salt); |
|
hasher.update(pin.as_bytes()); |
|
hasher.update(index.to_le_bytes()); |
|
let hash_key = hasher.finalize(); |
|
&hash_key[..] == hash |
|
} |
|
|
|
fn build_cipher(salt: &[u8], pin: &str) -> Aes256Gcm { |
|
let mut hasher = blake3::Hasher::new(); |
|
hasher.update(salt); |
|
hasher.update(pin.as_bytes()); |
|
hasher.update(&FIX_PADDING); |
|
let hash_key = hasher.finalize(); |
|
Aes256Gcm::new(GenericArray::from_slice(hash_key.as_bytes())) // 256-bit key. |
|
} |
|
|
|
/// encrypted bytes. |
|
pub fn encrypt(salt: &[u8], pin: &str, ptext: &[u8]) -> anyhow::Result<Vec<u8>> { |
|
let cipher = build_cipher(salt, pin); |
|
|
|
let mut nonce = Sha256::new(); |
|
nonce.update(pin.as_bytes()); |
|
nonce.update(&FIX_PADDING); |
|
let res = nonce.finalize(); |
|
let nonce = GenericArray::from_slice(&res[0..12]); // 96-bit key. |
|
|
|
cipher |
|
.encrypt(nonce, ptext) |
|
.or(Err(anyhow!("encrypt data failure."))) |
|
} |
|
|
|
pub fn encrypt_multiple(salt: &[u8], pin: &str, ptext: Vec<&[u8]>) -> anyhow::Result<Vec<Vec<u8>>> { |
|
let cipher = build_cipher(salt, pin); |
|
|
|
let mut nonce = Sha256::new(); |
|
nonce.update(pin.as_bytes()); |
|
nonce.update(&FIX_PADDING); |
|
let res = nonce.finalize(); |
|
let nonce = GenericArray::from_slice(&res[0..12]); // 96-bit key. |
|
|
|
let mut ebytes = vec![]; |
|
for p in ptext { |
|
ebytes.push( |
|
cipher |
|
.encrypt(nonce, p) |
|
.or(Err(anyhow!("encrypt data failure.")))?, |
|
); |
|
} |
|
Ok(ebytes) |
|
} |
|
|
|
/// decrypted bytes. |
|
pub fn decrypt(salt: &[u8], pin: &str, ctext: &[u8]) -> anyhow::Result<Vec<u8>> { |
|
let cipher = build_cipher(salt, pin); |
|
|
|
let mut nonce = Sha256::new(); |
|
nonce.update(pin.as_bytes()); |
|
nonce.update(&FIX_PADDING); |
|
let res = nonce.finalize(); |
|
let nonce = GenericArray::from_slice(&res[0..12]); // 96-bit key. |
|
|
|
cipher |
|
.decrypt(nonce, ctext) |
|
.or(Err(anyhow!("decrypt data failure."))) |
|
} |
|
|
|
pub fn decrypt_multiple(salt: &[u8], pin: &str, ctext: Vec<&[u8]>) -> anyhow::Result<Vec<Vec<u8>>> { |
|
let cipher = build_cipher(salt, pin); |
|
|
|
let mut nonce = Sha256::new(); |
|
nonce.update(pin.as_bytes()); |
|
nonce.update(&FIX_PADDING); |
|
let res = nonce.finalize(); |
|
let nonce = GenericArray::from_slice(&res[0..12]); // 96-bit key. |
|
|
|
let mut pbytes = vec![]; |
|
for c in ctext { |
|
pbytes.push( |
|
cipher |
|
.decrypt(nonce, c) |
|
.or(Err(anyhow!("decrypt data failure.")))?, |
|
); |
|
} |
|
Ok(pbytes) |
|
}
|
|
|