mirror of
https://gitlab.gnome.org/World/Authenticator.git
synced 2025-03-04 00:34:40 +01:00
Store attributes & app pass with argon2
This commit is contained in:
parent
fd4d6e5537
commit
09448846dd
3 changed files with 83 additions and 11 deletions
44
Cargo.lock
generated
44
Cargo.lock
generated
|
@ -81,6 +81,18 @@ version = "1.0.38"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "ashpd"
|
||||
version = "0.1.0"
|
||||
|
@ -265,11 +277,12 @@ dependencies = [
|
|||
"pretty_env_logger",
|
||||
"qrcode",
|
||||
"quick-xml",
|
||||
"rand 0.8.2",
|
||||
"ring",
|
||||
"rust-argon2",
|
||||
"secret-service",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"surf",
|
||||
"unicase",
|
||||
"url",
|
||||
|
@ -306,6 +319,17 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
|
@ -473,6 +497,12 @@ version = "0.4.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.14.3"
|
||||
|
@ -2407,6 +2437,18 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"blake2b_simd",
|
||||
"constant_time_eq",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
|
|
|
@ -25,11 +25,12 @@ percent-encoding = "2.1"
|
|||
pretty_env_logger = "0.4"
|
||||
qrcode = {version = "0.12", features = ["image"]}
|
||||
quick-xml = "0.20"
|
||||
rand = "0.8"
|
||||
ring = "0.16"
|
||||
rust-argon2 = "0.8"
|
||||
secret-service = "2.0"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
sha2 = "0.9"
|
||||
surf = "2.1"
|
||||
unicase = "2.6"
|
||||
url = "2.2"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::config;
|
||||
use secret_service::{Collection, EncryptionType, Error, SecretService};
|
||||
use sha2::{Digest, Sha512};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct Keyring;
|
||||
|
@ -20,6 +19,31 @@ fn password_attributes() -> HashMap<&'static str, &'static str> {
|
|||
attributes
|
||||
}
|
||||
|
||||
fn random_salt() -> [u8; 64] {
|
||||
use rand::RngCore;
|
||||
|
||||
let mut salt = [0u8; 64];
|
||||
rand::thread_rng().fill_bytes(&mut salt);
|
||||
salt
|
||||
}
|
||||
|
||||
fn encode_argon2(secret: &str) -> anyhow::Result<String> {
|
||||
use argon2::Config;
|
||||
|
||||
let password = secret.as_bytes();
|
||||
let salt = &random_salt();
|
||||
let config = Config::default();
|
||||
let hash = argon2::hash_encoded(password, salt, &config)?;
|
||||
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
/// Verifies that the hash generated by `password` corresponds
|
||||
/// to `hash`.
|
||||
fn verify_argon2(hash: &str, password: &str) -> anyhow::Result<bool> {
|
||||
Ok(argon2::verify_encoded(hash, password.as_bytes())?)
|
||||
}
|
||||
|
||||
impl Keyring {
|
||||
pub fn get_default_collection<'a>(ss: &'a SecretService<'a>) -> Result<Collection<'a>, Error> {
|
||||
let collection = match ss.get_default_collection() {
|
||||
|
@ -38,14 +62,13 @@ impl Keyring {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn store(label: &str, token: &str) -> Result<String, Error> {
|
||||
let token = token.as_bytes();
|
||||
pub fn store(label: &str, token: &str) -> anyhow::Result<String> {
|
||||
let ss = SecretService::new(EncryptionType::Dh)?;
|
||||
let col = Self::get_default_collection(&ss)?;
|
||||
|
||||
let token_id = hex::encode(Sha512::digest(token));
|
||||
let token_id = encode_argon2(token)?;
|
||||
let attributes = token_attributes(&token_id);
|
||||
let base64_token = hex::encode(token);
|
||||
let base64_token = hex::encode(token.as_bytes());
|
||||
col.create_item(label, attributes, base64_token.as_bytes(), true, "plain")?;
|
||||
Ok(token_id)
|
||||
}
|
||||
|
@ -85,15 +108,17 @@ impl Keyring {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_password(password: &str) -> Result<(), Error> {
|
||||
/// Stores password using the Argon2 algorithm with a random 128bit salt.
|
||||
pub fn set_password(password: &str) -> anyhow::Result<()> {
|
||||
let ss = SecretService::new(EncryptionType::Dh)?;
|
||||
let col = Self::get_default_collection(&ss)?;
|
||||
|
||||
let encoded_password = encode_argon2(password)?;
|
||||
let attributes = password_attributes();
|
||||
col.create_item(
|
||||
"Authenticator password",
|
||||
attributes,
|
||||
password.as_bytes(),
|
||||
encoded_password.as_bytes(),
|
||||
true,
|
||||
"plain",
|
||||
)?;
|
||||
|
@ -113,14 +138,18 @@ impl Keyring {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_current_password(password: &str) -> Result<bool, Error> {
|
||||
pub fn is_current_password(password: &str) -> anyhow::Result<bool> {
|
||||
let ss = SecretService::new(EncryptionType::Dh)?;
|
||||
let col = Self::get_default_collection(&ss)?;
|
||||
|
||||
let attributes = password_attributes();
|
||||
let items = col.search_items(attributes)?;
|
||||
Ok(match items.get(0) {
|
||||
Some(i) => i.get_secret()? == password.as_bytes(),
|
||||
Some(i) => {
|
||||
let secret = &i.get_secret()?;
|
||||
let stored_pass = std::str::from_utf8(secret)?;
|
||||
verify_argon2(stored_pass, password)?
|
||||
}
|
||||
None => false,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue