Browse Source

use argon2 replace salt+pin

pull/18/head
Sun 4 years ago
parent
commit
b9cd14244c
  1. 2
      Cargo.toml
  2. 24
      src/account.rs
  3. 2
      src/group.rs
  4. 29
      src/utils/crypto.rs

2
Cargo.toml

@ -29,6 +29,7 @@ image = "0.23" @@ -29,6 +29,7 @@ image = "0.23"
base64 = "0.13"
hex = "0.4"
sha2 = "0.10"
argon2 = "0.3"
blake3 = "1.2"
bincode = "1.3"
aes-gcm = "0.9"
@ -45,6 +46,7 @@ group_types = { git = "https://github.com/cympletech/esse_types", branch="main" @@ -45,6 +46,7 @@ group_types = { git = "https://github.com/cympletech/esse_types", branch="main"
cloud_types = { git = "https://github.com/cympletech/esse_types", branch="main" }
domain_types = { git = "https://github.com/cympletech/esse_types", branch="main" }
dao_types = { git = "https://github.com/cympletech/esse_types", branch="main" }
data = { git = "https://github.com/cympletech/esse_types", branch="main" }
#chat_types = { path = "../esse_types/chat" }
#group_types = { path = "../esse_types/group" }
#dao_types = { path = "../esse_types/dao" }

24
src/account.rs

@ -52,7 +52,7 @@ pub(crate) struct Account { @@ -52,7 +52,7 @@ pub(crate) struct Account {
pub pass: String,
pub name: String,
pub avatar: Vec<u8>,
pub lock: Vec<u8>, // hashed-lock.
pub lock: String, // hashed-lock.
pub secret: Vec<u8>, // encrypted value.
pub encrypt: Vec<u8>, // encrypted encrypt key.
pub wallet: String, // main wallet info.
@ -69,7 +69,7 @@ impl Account { @@ -69,7 +69,7 @@ impl Account {
lang: i64,
pass: String,
name: String,
lock: Vec<u8>,
lock: String,
avatar: Vec<u8>,
mnemonic: Vec<u8>,
secret: Vec<u8>,
@ -138,7 +138,7 @@ impl Account { @@ -138,7 +138,7 @@ impl Account {
lang,
pass.to_string(),
name.to_string(),
hash_pin(salt, lock, index),
hash_pin(lock)?,
avatar,
mnemonic,
secret,
@ -148,8 +148,8 @@ impl Account { @@ -148,8 +148,8 @@ impl Account {
))
}
pub fn check_lock(&self, salt: &[u8], lock: &str) -> Result<()> {
if check_pin(salt, lock, self.index, &self.lock) {
pub fn check_lock(&self, lock: &str) -> Result<()> {
if check_pin(lock, &self.lock)? {
Ok(())
} else {
Err(anyhow!("lock is invalid!"))
@ -157,8 +157,8 @@ impl Account { @@ -157,8 +157,8 @@ impl Account {
}
pub fn pin(&mut self, salt: &[u8], old: &str, new: &str) -> Result<()> {
self.check_lock(salt, old)?;
self.lock = hash_pin(salt, new, self.index);
self.check_lock(old)?;
self.lock = hash_pin(new)?;
let key = decrypt_key(salt, old, &self.encrypt)?;
self.encrypt = encrypt_key(salt, new, &key)?;
@ -166,13 +166,13 @@ impl Account { @@ -166,13 +166,13 @@ impl Account {
}
pub fn mnemonic(&self, salt: &[u8], lock: &str) -> Result<String> {
self.check_lock(salt, lock)?;
self.check_lock(lock)?;
let pbytes = decrypt(salt, lock, &self.encrypt, &self.mnemonic)?;
String::from_utf8(pbytes).or(Err(anyhow!("mnemonic unlock invalid.")))
}
pub fn secret(&self, salt: &[u8], lock: &str) -> Result<Keypair> {
self.check_lock(salt, lock)?;
self.check_lock(lock)?;
let pbytes = decrypt(salt, lock, &self.encrypt, &self.secret)?;
Keypair::from_bytes(&pbytes).or(Err(anyhow!("secret unlock invalid.")))
}
@ -189,7 +189,7 @@ impl Account { @@ -189,7 +189,7 @@ impl Account {
encrypt: base64::decode(v.pop().unwrap().as_str()).unwrap_or(vec![]),
secret: base64::decode(v.pop().unwrap().as_str()).unwrap_or(vec![]),
mnemonic: base64::decode(v.pop().unwrap().as_str()).unwrap_or(vec![]),
lock: base64::decode(v.pop().unwrap().as_string()).unwrap_or(vec![]),
lock: v.pop().unwrap().as_string(),
name: v.pop().unwrap().as_string(),
pass: v.pop().unwrap().as_string(),
lang: v.pop().unwrap().as_i64(),
@ -240,7 +240,7 @@ impl Account { @@ -240,7 +240,7 @@ impl Account {
self.lang,
self.pass,
self.name,
base64::encode(&self.lock),
self.lock,
base64::encode(&self.mnemonic),
base64::encode(&self.secret),
base64::encode(&self.encrypt),
@ -260,7 +260,7 @@ impl Account { @@ -260,7 +260,7 @@ impl Account {
pub fn update(&self, db: &DStorage) -> Result<usize> {
let sql = format!("UPDATE accounts SET name='{}', lock='{}', encrypt='{}', avatar='{}', wallet='{}', pub_height={}, own_height={}, event='{}', datetime={} WHERE id = {}",
self.name,
base64::encode(&self.lock),
self.lock,
base64::encode(&self.encrypt),
base64::encode(&self.avatar),
self.wallet,

2
src/group.rs

@ -278,7 +278,7 @@ impl Group { @@ -278,7 +278,7 @@ impl Group {
pub fn check_lock(&self, gid: &GroupId, lock: &str) -> bool {
if let Some(account) = self.accounts.get(gid) {
account.check_lock(&self.secret, lock).is_ok()
account.check_lock(lock).is_ok()
} else {
false
}

29
src/utils/crypto.rs

@ -2,6 +2,10 @@ use aes_gcm::{ @@ -2,6 +2,10 @@ use aes_gcm::{
aead::{generic_array::GenericArray, Aead, NewAead},
Aes256Gcm,
};
use argon2::{
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
Argon2,
};
use sha2::{Digest, Sha256};
const FIX_PADDING: [u8; 19] = [
@ -9,22 +13,21 @@ const FIX_PADDING: [u8; 19] = [ @@ -9,22 +13,21 @@ const FIX_PADDING: [u8; 19] = [
];
/// 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()
pub fn hash_pin(pin: &str) -> anyhow::Result<String> {
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
Ok(argon2
.hash_password(pin.as_bytes(), &salt)
.map_err(|_| anyhow!("hash pin failure!"))?
.to_string())
}
/// 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
pub fn check_pin(pin: &str, hash: &str) -> anyhow::Result<bool> {
let parsed_hash = PasswordHash::new(hash).map_err(|_| anyhow!("hash pin failure!"))?;
Ok(Argon2::default()
.verify_password(pin.as_bytes(), &parsed_hash)
.is_ok())
}
fn build_cipher(salt: &[u8], pin: &str) -> Aes256Gcm {

Loading…
Cancel
Save