Skip to content

Commit 52a8d6c

Browse files
authored
chore: use rust 2024 edition (#557)
2 parents f27f7b7 + b99eec6 commit 52a8d6c

File tree

17 files changed

+843
-899
lines changed

17 files changed

+843
-899
lines changed

Cargo.lock

Lines changed: 388 additions & 452 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "cotp"
33
version = "1.9.4"
44
authors = ["replydev <[email protected]>"]
5-
edition = "2021"
5+
edition = "2024"
66
description = "Trustworthy, encrypted, command-line TOTP/HOTP authenticator app with import functionality."
77
repository = "https://github.com/replydev/cotp"
88
homepage = "https://github.com/replydev/cotp"

src/arguments/add.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clap::{value_parser, Args};
1+
use clap::{Args, value_parser};
22
use color_eyre::eyre::{ErrReport, Result};
33

44
use zeroize::Zeroize;

src/arguments/edit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clap::{value_parser, Args};
1+
use clap::{Args, value_parser};
22
use color_eyre::eyre::eyre;
33

44
use crate::otp::{otp_algorithm::OTPAlgorithm, otp_element::OTPDatabase};

src/arguments/list.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clap::Args;
2-
use color_eyre::eyre::{eyre, Result};
2+
use color_eyre::eyre::{Result, eyre};
33
use serde::Serialize;
44

55
use crate::otp::otp_element::{OTPDatabase, OTPElement};

src/clipboard.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use base64::{engine::general_purpose, Engine as _};
1+
use base64::{Engine as _, engine::general_purpose};
22
use color_eyre::eyre::eyre;
33
use copypasta_ext::prelude::*;
44
#[cfg(target_os = "linux")]

src/crypto/cryptography.rs

Lines changed: 101 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,101 @@
1-
use argon2::{Config, Variant, Version};
2-
use chacha20poly1305::aead::Aead;
3-
use chacha20poly1305::{Key, KeyInit, XChaCha20Poly1305, XNonce};
4-
use color_eyre::eyre::{eyre, ErrReport};
5-
use data_encoding::BASE64;
6-
7-
use super::encrypted_database::EncryptedDatabase;
8-
9-
const ARGON2ID_SALT_LENGTH: usize = 16;
10-
const XCHACHA20_POLY1305_NONCE_LENGTH: usize = 24;
11-
const XCHACHA20_POLY1305_KEY_LENGTH: usize = 32;
12-
const KEY_DERIVATION_CONFIG: Config = Config {
13-
variant: Variant::Argon2id,
14-
version: Version::Version13,
15-
mem_cost: 32768,
16-
time_cost: 4,
17-
lanes: 4,
18-
secret: &[],
19-
ad: &[],
20-
hash_length: XCHACHA20_POLY1305_KEY_LENGTH as u32,
21-
};
22-
23-
pub fn argon_derive_key(password_bytes: &[u8], salt: &[u8]) -> color_eyre::Result<Vec<u8>> {
24-
argon2::hash_raw(password_bytes, salt, &KEY_DERIVATION_CONFIG).map_err(ErrReport::from)
25-
}
26-
27-
pub fn gen_salt() -> color_eyre::Result<[u8; ARGON2ID_SALT_LENGTH]> {
28-
let mut salt: [u8; ARGON2ID_SALT_LENGTH] = [0; ARGON2ID_SALT_LENGTH];
29-
getrandom::fill(&mut salt).map_err(|e| eyre!(e))?;
30-
Ok(salt)
31-
}
32-
33-
pub fn encrypt_string_with_key(
34-
plain_text: &str,
35-
key: &Vec<u8>,
36-
salt: &[u8],
37-
) -> color_eyre::Result<EncryptedDatabase> {
38-
let wrapped_key = Key::from_slice(key.as_slice());
39-
40-
let aead = XChaCha20Poly1305::new(wrapped_key);
41-
let mut nonce_bytes: [u8; XCHACHA20_POLY1305_NONCE_LENGTH] =
42-
[0; XCHACHA20_POLY1305_NONCE_LENGTH];
43-
44-
getrandom::fill(&mut nonce_bytes).map_err(|e| eyre!(e))?;
45-
46-
let nonce = XNonce::from_slice(&nonce_bytes);
47-
let cipher_text = aead
48-
.encrypt(nonce, plain_text.as_bytes())
49-
.map_err(|e| eyre!("Error during encryption: {e}"))?;
50-
Ok(EncryptedDatabase::new(
51-
1,
52-
BASE64.encode(&nonce_bytes),
53-
BASE64.encode(salt),
54-
BASE64.encode(&cipher_text),
55-
))
56-
}
57-
58-
pub fn decrypt_string(
59-
encrypted_text: &str,
60-
password: &str,
61-
) -> color_eyre::Result<(String, Vec<u8>, Vec<u8>)> {
62-
//encrypted text is an encrypted database json serialized object
63-
let encrypted_database: EncryptedDatabase = serde_json::from_str(encrypted_text)
64-
.map_err(|e| eyre!("Error during encrypted database deserialization: {e}"))?;
65-
let nonce = BASE64
66-
.decode(encrypted_database.nonce().as_bytes())
67-
.expect("Cannot decode Base64 nonce");
68-
let cipher_text = BASE64
69-
.decode(encrypted_database.cipher().as_bytes())
70-
.expect("Cannot decode Base64 cipher");
71-
let salt = BASE64.decode(encrypted_database.salt().as_bytes()).unwrap();
72-
73-
let key: Vec<u8> = argon_derive_key(password.as_bytes(), salt.as_slice())?;
74-
75-
let wrapped_key = Key::from_slice(&key);
76-
77-
let aead = XChaCha20Poly1305::new(wrapped_key);
78-
let nonce = XNonce::from_slice(nonce.as_slice());
79-
let decrypted = aead
80-
.decrypt(nonce, cipher_text.as_slice())
81-
.map_err(|_| eyre!("Wrong password"))?;
82-
let from_utf8 = String::from_utf8(decrypted).map_err(ErrReport::from)?;
83-
Ok((from_utf8, key, salt))
84-
}
85-
86-
#[cfg(test)]
87-
mod tests {
88-
use crate::crypto::cryptography::{argon_derive_key, gen_salt};
89-
90-
use super::{decrypt_string, encrypt_string_with_key};
91-
92-
#[test]
93-
fn test_encryption() {
94-
let salt = gen_salt().unwrap();
95-
let key = argon_derive_key(b"pa$$w0rd", salt.as_ref()).unwrap();
96-
let encrypted = encrypt_string_with_key("Secret data@#[]ò", &key, salt.as_ref()).unwrap();
97-
let (decrypted, _key, _salt) =
98-
decrypt_string(&serde_json::to_string(&encrypted).unwrap(), "pa$$w0rd").unwrap();
99-
assert_eq!(String::from("Secret data@#[]ò"), decrypted);
100-
}
101-
}
1+
use argon2::{Config, Variant, Version};
2+
use chacha20poly1305::aead::Aead;
3+
use chacha20poly1305::{Key, KeyInit, XChaCha20Poly1305, XNonce};
4+
use color_eyre::eyre::{ErrReport, eyre};
5+
use data_encoding::BASE64;
6+
7+
use super::encrypted_database::EncryptedDatabase;
8+
9+
const ARGON2ID_SALT_LENGTH: usize = 16;
10+
const XCHACHA20_POLY1305_NONCE_LENGTH: usize = 24;
11+
const XCHACHA20_POLY1305_KEY_LENGTH: usize = 32;
12+
const KEY_DERIVATION_CONFIG: Config = Config {
13+
variant: Variant::Argon2id,
14+
version: Version::Version13,
15+
mem_cost: 32768,
16+
time_cost: 4,
17+
lanes: 4,
18+
secret: &[],
19+
ad: &[],
20+
hash_length: XCHACHA20_POLY1305_KEY_LENGTH as u32,
21+
};
22+
23+
pub fn argon_derive_key(password_bytes: &[u8], salt: &[u8]) -> color_eyre::Result<Vec<u8>> {
24+
argon2::hash_raw(password_bytes, salt, &KEY_DERIVATION_CONFIG).map_err(ErrReport::from)
25+
}
26+
27+
pub fn gen_salt() -> color_eyre::Result<[u8; ARGON2ID_SALT_LENGTH]> {
28+
let mut salt: [u8; ARGON2ID_SALT_LENGTH] = [0; ARGON2ID_SALT_LENGTH];
29+
getrandom::fill(&mut salt).map_err(|e| eyre!(e))?;
30+
Ok(salt)
31+
}
32+
33+
pub fn encrypt_string_with_key(
34+
plain_text: &str,
35+
key: &Vec<u8>,
36+
salt: &[u8],
37+
) -> color_eyre::Result<EncryptedDatabase> {
38+
let wrapped_key = Key::from_slice(key.as_slice());
39+
40+
let aead = XChaCha20Poly1305::new(wrapped_key);
41+
let mut nonce_bytes: [u8; XCHACHA20_POLY1305_NONCE_LENGTH] =
42+
[0; XCHACHA20_POLY1305_NONCE_LENGTH];
43+
44+
getrandom::fill(&mut nonce_bytes).map_err(|e| eyre!(e))?;
45+
46+
let nonce = XNonce::from_slice(&nonce_bytes);
47+
let cipher_text = aead
48+
.encrypt(nonce, plain_text.as_bytes())
49+
.map_err(|e| eyre!("Error during encryption: {e}"))?;
50+
Ok(EncryptedDatabase::new(
51+
1,
52+
BASE64.encode(&nonce_bytes),
53+
BASE64.encode(salt),
54+
BASE64.encode(&cipher_text),
55+
))
56+
}
57+
58+
pub fn decrypt_string(
59+
encrypted_text: &str,
60+
password: &str,
61+
) -> color_eyre::Result<(String, Vec<u8>, Vec<u8>)> {
62+
//encrypted text is an encrypted database json serialized object
63+
let encrypted_database: EncryptedDatabase = serde_json::from_str(encrypted_text)
64+
.map_err(|e| eyre!("Error during encrypted database deserialization: {e}"))?;
65+
let nonce = BASE64
66+
.decode(encrypted_database.nonce().as_bytes())
67+
.expect("Cannot decode Base64 nonce");
68+
let cipher_text = BASE64
69+
.decode(encrypted_database.cipher().as_bytes())
70+
.expect("Cannot decode Base64 cipher");
71+
let salt = BASE64.decode(encrypted_database.salt().as_bytes()).unwrap();
72+
73+
let key: Vec<u8> = argon_derive_key(password.as_bytes(), salt.as_slice())?;
74+
75+
let wrapped_key = Key::from_slice(&key);
76+
77+
let aead = XChaCha20Poly1305::new(wrapped_key);
78+
let nonce = XNonce::from_slice(nonce.as_slice());
79+
let decrypted = aead
80+
.decrypt(nonce, cipher_text.as_slice())
81+
.map_err(|_| eyre!("Wrong password"))?;
82+
let from_utf8 = String::from_utf8(decrypted).map_err(ErrReport::from)?;
83+
Ok((from_utf8, key, salt))
84+
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
use crate::crypto::cryptography::{argon_derive_key, gen_salt};
89+
90+
use super::{decrypt_string, encrypt_string_with_key};
91+
92+
#[test]
93+
fn test_encryption() {
94+
let salt = gen_salt().unwrap();
95+
let key = argon_derive_key(b"pa$$w0rd", salt.as_ref()).unwrap();
96+
let encrypted = encrypt_string_with_key("Secret data@#[]ò", &key, salt.as_ref()).unwrap();
97+
let (decrypted, _key, _salt) =
98+
decrypt_string(&serde_json::to_string(&encrypted).unwrap(), "pa$$w0rd").unwrap();
99+
assert_eq!(String::from("Secret data@#[]ò"), decrypted);
100+
}
101+
}

src/importers/aegis_encrypted.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use aes_gcm::aead::generic_array::GenericArray;
21
use aes_gcm::aead::Aead;
2+
use aes_gcm::aead::generic_array::GenericArray;
33
use aes_gcm::{Aes256Gcm, KeyInit, Nonce}; // Or `Aes128Gcm`
44
use data_encoding::BASE64;
55
use hex::FromHex;
@@ -8,7 +8,7 @@ use zeroize::Zeroize;
88

99
use crate::otp::otp_element::OTPElement;
1010
use crate::utils;
11-
use scrypt::{scrypt, Params};
11+
use scrypt::{Params, scrypt};
1212

1313
use super::aegis::AegisDb;
1414

src/importers/freeotp_plus.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ mod tests {
9696
use crate::otp::otp_element::OTPDatabase;
9797
use color_eyre::Result;
9898

99-
use super::{encode_secret, FreeOTPPlusJson};
99+
use super::{FreeOTPPlusJson, encode_secret};
100100

101101
#[test]
102102
fn test_secret_conversion() {

src/importers/importer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{fmt::Debug, fs::read_to_string, path::PathBuf};
22

3-
use color_eyre::eyre::{eyre, Result};
3+
use color_eyre::eyre::{Result, eyre};
44
use serde::Deserialize;
55

66
use crate::otp::otp_element::OTPElement;

0 commit comments

Comments
 (0)