mirror of
https://gitlab.gnome.org/World/Authenticator.git
synced 2025-03-04 00:34:40 +01:00
parent
598cdf9d6b
commit
cdee19ccb8
4 changed files with 30 additions and 70 deletions
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -149,7 +149,6 @@ dependencies = [
|
|||
"aes-gcm",
|
||||
"anyhow",
|
||||
"ashpd",
|
||||
"binascii",
|
||||
"data-encoding",
|
||||
"diesel",
|
||||
"diesel_migrations",
|
||||
|
@ -202,12 +201,6 @@ version = "0.21.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
|
||||
|
||||
[[package]]
|
||||
name = "binascii"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.64.0"
|
||||
|
@ -725,13 +718,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys 0.45.0",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1025,9 +1018,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
@ -1419,9 +1412,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gstreamer-video"
|
||||
version = "0.20.3"
|
||||
version = "0.20.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "467cddb6a4135e72fefb6ba21262b1cca5493e9928792e88fe672ec0a37b761c"
|
||||
checksum = "dce97769effde2d779dc4f7037b37106457b74e53f2a711bddc90b30ffeb7e06"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
|
@ -2749,9 +2742,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.8"
|
||||
version = "0.37.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aef160324be24d31a62147fae491c14d2204a3865c7ca8c3b0d7f7bcb3ea635"
|
||||
checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
|
|
|
@ -8,7 +8,6 @@ adw = {package = "libadwaita", version = "0.3", features = ["v1_2"]}
|
|||
aes-gcm = "0.10"
|
||||
anyhow = "1.0"
|
||||
ashpd = {version = "0.4", default-features = false, features = ["pipewire", "gtk4", "tokio", "tracing"]}
|
||||
binascii = "0.1"
|
||||
data-encoding = "2.3"
|
||||
diesel = {version = "2.0", features = ["sqlite", "r2d2"]}
|
||||
diesel_migrations = {version = "2.0", features = ["sqlite"]}
|
||||
|
|
|
@ -5,7 +5,7 @@ use prost::{Enumeration, Message};
|
|||
use url::Url;
|
||||
|
||||
use super::Restorable;
|
||||
use crate::models::{Algorithm, Method, OTPUri};
|
||||
use crate::models::{otp, Algorithm, Method, OTPUri};
|
||||
|
||||
pub struct Google;
|
||||
|
||||
|
@ -92,20 +92,7 @@ impl Restorable for Google {
|
|||
protobuf::migration_payload::OtpType::OTP_TOTP => Method::TOTP,
|
||||
},
|
||||
secret: {
|
||||
let secret = &*otp.secret;
|
||||
|
||||
let mut buffer = [0; 128];
|
||||
|
||||
if binascii::b32encode(secret, &mut buffer).is_err() {
|
||||
return folded;
|
||||
}
|
||||
|
||||
let buffer = buffer.to_vec();
|
||||
|
||||
let string = match String::from_utf8(buffer) {
|
||||
Ok(string) => string,
|
||||
Err(_) => return folded,
|
||||
};
|
||||
let string = otp::encode_secret(&*otp.secret);
|
||||
|
||||
string
|
||||
.trim_end_matches(|c| c == '\0' || c == '=')
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use data_encoding::BASE32;
|
||||
use ring::hmac;
|
||||
|
||||
use super::Algorithm;
|
||||
|
@ -21,15 +22,15 @@ pub static TOTP_DEFAULT_PERIOD: u32 = 30;
|
|||
/// Decodes a secret (given as an RFC4648 base32-encoded ASCII string)
|
||||
/// into a byte string. It fails if secret is not a valid Base32 string.
|
||||
fn decode_secret(secret: &str) -> Result<Vec<u8>> {
|
||||
let secret = secret.trim().replace(' ', "").to_uppercase();
|
||||
let secret = secret.trim().replace(' ', "").to_ascii_uppercase();
|
||||
// The buffer should have a length of secret.len() * 5 / 8.
|
||||
let size = secret.len();
|
||||
let mut output_buffer = std::iter::repeat(0).take(size).collect::<Vec<u8>>();
|
||||
let vec = binascii::b32decode(secret.as_bytes(), &mut output_buffer)
|
||||
.map_err(|_| anyhow!("Invalid Input"))?
|
||||
.to_vec();
|
||||
BASE32
|
||||
.decode(secret.as_bytes())
|
||||
.map_err(|_| anyhow!("Invalid Input"))
|
||||
}
|
||||
|
||||
Ok(vec)
|
||||
pub fn encode_secret(secret: &[u8]) -> String {
|
||||
BASE32.encode(secret)
|
||||
}
|
||||
|
||||
/// Validates if `secret` is a valid Base32 String.
|
||||
|
@ -61,14 +62,13 @@ fn encode_digest(digest: &[u8]) -> Result<u32> {
|
|||
/// (HOTP) given an RFC4648 base32 encoded secret, and an integer counter.
|
||||
pub(crate) fn hotp(secret: &str, counter: u64, algorithm: Algorithm, digits: u32) -> Result<u32> {
|
||||
let decoded = decode_secret(secret)?;
|
||||
let digest = encode_digest(calc_digest(decoded.as_slice(), counter, algorithm).as_ref())?;
|
||||
let digest = encode_digest(calc_digest(&decoded, counter, algorithm).as_ref())?;
|
||||
Ok(digest % 10_u32.pow(digits))
|
||||
}
|
||||
|
||||
pub(crate) fn steam(secret: &str, counter: u64) -> Result<String> {
|
||||
let decoded = decode_secret(secret)?;
|
||||
let mut full_token =
|
||||
encode_digest(calc_digest(decoded.as_slice(), counter, Algorithm::SHA1).as_ref())?;
|
||||
let mut full_token = encode_digest(calc_digest(&decoded, counter, Algorithm::SHA1).as_ref())?;
|
||||
|
||||
let mut code = String::new();
|
||||
let total_chars = STEAM_CHARS.len() as u32;
|
||||
|
@ -103,30 +103,16 @@ pub(crate) fn time_based_counter(period: u32) -> u64 {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{format, hotp, steam, Algorithm, DEFAULT_DIGITS, TOTP_DEFAULT_PERIOD};
|
||||
use super::{
|
||||
encode_secret, format, hotp, steam, Algorithm, DEFAULT_DIGITS, TOTP_DEFAULT_PERIOD,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_totp() {
|
||||
let secret_sha1 = String::from_utf8(
|
||||
binascii::b32encode(b"12345678901234567890", &mut [0; 64])
|
||||
.unwrap()
|
||||
.to_vec(),
|
||||
)
|
||||
.unwrap();
|
||||
let secret_sha256 = String::from_utf8(
|
||||
binascii::b32encode(b"12345678901234567890123456789012", &mut [0; 64])
|
||||
.unwrap()
|
||||
.to_vec(),
|
||||
)
|
||||
.unwrap();
|
||||
let secret_sha512 = String::from_utf8(
|
||||
binascii::b32encode(
|
||||
b"1234567890123456789012345678901234567890123456789012345678901234",
|
||||
&mut [0; 128],
|
||||
)
|
||||
.unwrap()
|
||||
.to_vec(),
|
||||
)
|
||||
.unwrap();
|
||||
let secret_sha1 = encode_secret(b"12345678901234567890");
|
||||
let secret_sha256 = encode_secret(b"12345678901234567890123456789012");
|
||||
let secret_sha512 =
|
||||
encode_secret(b"1234567890123456789012345678901234567890123456789012345678901234");
|
||||
|
||||
let counter1 = 59 / TOTP_DEFAULT_PERIOD as u64;
|
||||
assert_eq!(
|
||||
|
@ -228,12 +214,7 @@ mod tests {
|
|||
hotp("BASE32SECRET3232", 1401, Algorithm::SHA1, DEFAULT_DIGITS).ok(),
|
||||
Some(316439)
|
||||
);
|
||||
let secret = String::from_utf8(
|
||||
binascii::b32encode(b"12345678901234567890", &mut [0; 64])
|
||||
.unwrap()
|
||||
.to_vec(),
|
||||
)
|
||||
.unwrap();
|
||||
let secret = encode_secret(b"12345678901234567890");
|
||||
assert_eq!(
|
||||
Some(755224),
|
||||
hotp(&secret, 0, Algorithm::SHA1, DEFAULT_DIGITS).ok()
|
||||
|
|
Loading…
Add table
Reference in a new issue