Skip to content

Commit 5bc7cd7

Browse files
author
replydev
committed
Import Aegis backup,importers API
1 parent 030b711 commit 5bc7cd7

File tree

7 files changed

+123
-18
lines changed

7 files changed

+123
-18
lines changed

src/argument_functions.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,45 @@
1-
use std::fs::{read_to_string,File};
2-
use std::io::prelude::*;
3-
use super::utils::get_db_path;
41
use super::database_loader;
5-
use super::cryptograpy;
62
use super::otp_helper;
3+
use crate::importers;
74

85
pub fn help(){
96
println!("ARGUMENTS:");
107
println!("-a,--add <secret> <issuer> <label> | Add a new OTP code");
118
println!("-r,--remove <secret> <issuer> <label> | Remove an OTP code");
129
println!("-e,--edit <id> <secret> <issuer> <label> | Edit an OTP code");
13-
println!("-i,--import <filename> | Import an andOTP backup");
10+
println!("-i,--import aegis,andotp <filename> | Import a backup from a given application");
1411
println!("-ex,--export | Export the entire database in a plaintext json format");
1512
println!("-j,--json | Print results in json format");
1613
println!("-h,--help | Print this help");
1714
}
1815

1916
pub fn import(args: Vec<String>){
20-
import_database(&args[2]);
17+
if args.len() == 4{
18+
let result: Result<Vec<database_loader::OTPElement>,String>;
19+
let elements: Vec<database_loader::OTPElement>;
20+
21+
match &args[2][..]{
22+
"andotp" => result = importers::and_otp::import(&args[3]),
23+
"aegis" => result = importers::aegis::import(&args[3]),
24+
_=> {
25+
println!("Invalid argument: {}", &args[2]);
26+
return;
27+
}
28+
}
29+
30+
match result {
31+
Ok(result) => elements = result,
32+
Err(e) => {
33+
println!("An error occurred: {}", e);
34+
return;
35+
}
36+
}
37+
database_loader::overwrite_database(elements);
38+
println!("Successfully imported database");
39+
}
40+
else{
41+
println!("Invalid arguments, type cotp --import <backup_format> <path>");
42+
}
2143
}
2244

2345
pub fn add(args: Vec<String>){
@@ -87,11 +109,3 @@ pub fn json(args: Vec<String>){
87109
println!("Invalid argument, type cotp --json");
88110
}
89111
}
90-
91-
fn import_database(filename: &String){
92-
let mut unencrypted_content = read_to_string(filename).unwrap();
93-
let encrypted_content = cryptograpy::encrypt_string(&mut unencrypted_content,&cryptograpy::prompt_for_passwords("Insert password for database encryption: "));
94-
let mut encrypted_file = File::create(&get_db_path()).expect("Cannot create encrypted database file");
95-
encrypted_file.write_all(encrypted_content.as_bytes()).expect("Cannot write to encrypted file");
96-
println!("Successfully imported database");
97-
}

src/database_loader.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,11 @@ pub fn export_database() -> Result<String, String> {
170170

171171
pub fn overwrite_database(elements: Vec<OTPElement>){
172172
let json_string: &str = &serde_json::to_string(&elements).unwrap();
173-
let encrypted = cryptograpy::encrypt_string(&mut json_string.to_string(), &cryptograpy::prompt_for_passwords("Insert password for database encryption: "));
173+
overwrite_database_json(json_string);
174+
}
175+
176+
pub fn overwrite_database_json(json: &str){
177+
let encrypted = cryptograpy::encrypt_string(&mut json.to_string(), &cryptograpy::prompt_for_passwords("Insert password for database encryption: "));
174178
utils::write_to_file(&encrypted, &mut File::create(utils::get_db_path()).expect("Failed to open file"));
175179
}
176180

src/importers/aegis.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use crate::database_loader::OTPElement;
2+
use std::fs::read_to_string;
3+
use serde_json;
4+
use serde::Deserialize;
5+
6+
#[derive(Deserialize)]
7+
struct AegisJson{
8+
version: u64,
9+
header: AegisHeader,
10+
db: AegisDb,
11+
}
12+
13+
#[derive(Deserialize)]
14+
struct AegisHeader{
15+
slots: Option<String>,
16+
params: Option<String>,
17+
}
18+
19+
#[derive(Deserialize)]
20+
struct AegisDb{
21+
version: u64,
22+
entries: Vec<AegisElement>,
23+
}
24+
25+
#[derive(Deserialize)]
26+
struct AegisElement{
27+
#[serde(rename = "type")]
28+
_type: String,
29+
uuid: String,
30+
name: String,
31+
issuer: String,
32+
icon: Option<String>,
33+
info: AegisInfo,
34+
}
35+
36+
#[derive(Deserialize)]
37+
struct AegisInfo {
38+
secret: String,
39+
algo: String,
40+
digits: u64,
41+
period: u64,
42+
}
43+
44+
pub fn import(filepath: &str) -> Result<Vec<OTPElement>,String> {
45+
let file_to_import_contents = read_to_string(filepath).unwrap();
46+
let result: Result<AegisJson,serde_json::Error> = serde_json::from_str(&file_to_import_contents);
47+
let aegis;
48+
match result {
49+
Ok(element) => aegis = element,
50+
Err(e) => return Err(format!("{}", e)),
51+
}
52+
53+
let mut elements: Vec<OTPElement> = Vec::new();
54+
55+
for i in 0..aegis.db.entries.len() {
56+
elements.push(OTPElement::new(
57+
String::from(&aegis.db.entries[i].info.secret),
58+
String::from(&aegis.db.entries[i].issuer),
59+
String::from(&aegis.db.entries[i].name),
60+
aegis.db.entries[i].info.digits,
61+
String::from(&aegis.db.entries[i]._type),
62+
String::from(&aegis.db.entries[i].info.algo),
63+
String::from(""),
64+
0,
65+
0,
66+
aegis.db.entries[i].info.period,
67+
vec![]))
68+
}
69+
Ok(elements)
70+
}

src/importers/and_otp.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use crate::database_loader::OTPElement;
2+
use std::fs::read_to_string;
3+
4+
//no need to declarate andOTP json struct cause it's the same as OTP element
5+
6+
pub fn import(filepath: &str) -> Result<Vec<OTPElement>,String>{
7+
let file_to_import_contents = read_to_string(filepath).unwrap();
8+
let result: Result<Vec<OTPElement>,serde_json::Error> = serde_json::from_str(&file_to_import_contents);
9+
match result {
10+
Ok(element) => return Ok(element),
11+
Err(e) => return Err(String::from(format!("Failed to serialize file: {}",e)))
12+
}
13+
}

src/importers/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod and_otp;
2+
pub mod aegis;

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod argument_functions;
66
mod otp_helper;
77
mod cryptograpy;
88
use sodiumoxide;
9+
mod import_otp;
910

1011
#[cfg(debug_assertions)]
1112
fn print_title(version: &str){

src/utils.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use directories::BaseDirs;
22
use std::fs::{File};
33
use std::io::prelude::*;
44
use std::path::Path;
5-
use super::cryptograpy;
5+
use super::database_loader;
66

77
#[cfg(debug_assertions)]
88
pub fn get_db_path() -> String{
@@ -25,9 +25,10 @@ pub fn get_home_folder() -> String {
2525

2626
pub fn create_db_if_needed(){
2727
if !Path::new(&get_db_path()).exists() {
28-
let mut database_file = File::create(&get_db_path()).expect("Cannot create encrypted database file");
28+
/*let mut database_file = File::create(&get_db_path()).expect("Cannot create encrypted database file");
2929
let encrypted_content = cryptograpy::encrypt_string(&mut String::from("[]"), &cryptograpy::prompt_for_passwords("Insert password for database encryption: "));
30-
write_to_file(&encrypted_content,&mut database_file);
30+
write_to_file(&encrypted_content,&mut database_file);*/
31+
database_loader::overwrite_database_json("[]");
3132
}
3233
}
3334

0 commit comments

Comments
 (0)