Skip to content

Commit

Permalink
Google Authenticator converter improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Levminer committed Mar 8, 2023
1 parent 97d55f1 commit 8a6fa8f
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 179 deletions.
2 changes: 1 addition & 1 deletion core/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion core/crates/google_authenticator_converter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
[package]
name = "google_authenticator_converter"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
license = "MIT"
description= "Extract name, secret and issuer from a Google Authenticator migration QR code"
repository = "https://github.com/Levminer/authme/tree/dev/core/crates/google_authenticator_converter"

[dependencies]
base32 = "0.4.0"
Expand Down
19 changes: 16 additions & 3 deletions core/crates/google_authenticator_converter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,20 @@

- Extract name, secret and issuer from a Google Authenticator migration QR code

### Based on:
### Example

[google-authenticator-extractor
](https://github.com/zhangyuan/google-authenticator-extractor)
```rs
use google_authenticator_converter::{extract_data_from_uri, process_data, Account};

let qr_code = "otpauth-migration://offline?data=CjMKCkhlbGxvId6tvu8SGFRlc3QxOnRlc3QxQGV4YW1wbGUxLmNvbRoFVGVzdDEgASgBMAIKMwoKSGVsbG8h3q2%2B8BIYVGVzdDI6dGVzdDJAZXhhbXBsZTIuY29tGgVUZXN0MiABKAEwAgozCgpIZWxsbyHerb7xEhhUZXN0Mzp0ZXN0M0BleGFtcGxlMy5jb20aBVRlc3QzIAEoATACEAEYASAAKI3orYEE";

let accounts = process_data(&qr_code);

for account in accounts.unwrap() {
println!("{0} {1} {2}", account.name, account.secret, account.issuer);
}
```

### Based on

[google-authenticator-extractor](https://github.com/zhangyuan/google-authenticator-extractor)
36 changes: 28 additions & 8 deletions core/crates/google_authenticator_converter/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
//! # Google Authenticator Converter
//!
//! - Extract name, secret and issuer from a Google Authenticator migration QR code
//!
//! ### Example
//!
//! ```rust
//! use google_authenticator_converter::{extract_data_from_uri, process_data, Account};
//!
//! let qr_code = "otpauth-migration://offline?data=CjMKCkhlbGxvId6tvu8SGFRlc3QxOnRlc3QxQGV4YW1wbGUxLmNvbRoFVGVzdDEgASgBMAIKMwoKSGVsbG8h3q2%2B8BIYVGVzdDI6dGVzdDJAZXhhbXBsZTIuY29tGgVUZXN0MiABKAEwAgozCgpIZWxsbyHerb7xEhhUZXN0Mzp0ZXN0M0BleGFtcGxlMy5jb20aBVRlc3QzIAEoATACEAEYASAAKI3orYEE";
//!
//! let accounts = process_data(&qr_code);
//!
//! for account in accounts.unwrap() {
//! println!("{0} {1} {2}", account.name, account.secret, account.issuer);
//! }
//!
use base64::{engine::general_purpose, Engine as _};
use protobuf::Message;
use serde::Serialize;

mod proto;
#[derive(Debug, Serialize)]
pub struct Account {
name: String,
secret: String,
issuer: String,
pub name: String,
pub secret: String,
pub issuer: String,
}

impl Account {
Expand All @@ -25,12 +43,13 @@ impl Account {
}
}

pub fn process_data(string: &str) -> Vec<Account> {
let encoded_data = extract_data_from_uri(string).unwrap();
let decoded_data = general_purpose::STANDARD.decode(encoded_data).unwrap();
/// Convert a Google Authenticator migration QR code string to a list of accounts
pub fn process_data(string: &str) -> Result<Vec<Account>, Box<dyn std::error::Error>> {
let encoded_data = extract_data_from_uri(string)?;
let decoded_data = general_purpose::STANDARD.decode(encoded_data)?;

let migration_payload =
proto::google_auth::MigrationPayload::parse_from_bytes(decoded_data.as_slice()).unwrap();
proto::google_auth::MigrationPayload::parse_from_bytes(decoded_data.as_slice())?;

let otp_parameters = migration_payload.otp_parameters.into_vec();

Expand All @@ -47,11 +66,12 @@ pub fn process_data(string: &str) -> Vec<Account> {
})
.collect();

return payloads;
return Ok(payloads);
}

pub fn extract_data_from_uri(raw: &str) -> Result<String, Box<dyn std::error::Error>> {
let mut split = raw.split("data=");
split.next();

if let Some(encoded_data) = split.next() {
let s = urlencoding::decode(encoded_data)?;
Expand Down
9 changes: 7 additions & 2 deletions core/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use google_authenticator_converter::{process_data, Account};
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use std::io::Write;
use std::{env, fs};
use sysinfo::{CpuExt, System, SystemExt};
use tauri::{GlobalShortcutManager, Manager};
use google_authenticator_converter::{process_data, Account};

#[tauri::command]
pub fn get_args() -> Vec<String> {
Expand Down Expand Up @@ -88,5 +88,10 @@ pub fn system_info() -> String {
pub fn google_authenticator_converter(secret: &str) -> Vec<Account> {
let res = process_data(secret);

res.into()
println!("{:?}", res);

match res {
Ok(accounts) => accounts,
Err(_) => vec![],
}
}
4 changes: 4 additions & 0 deletions interface/utils/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ export const migrationImageConverter = async (data: string): Promise<string> =>
// decode data
const decoded: LibCodesFormat[] = await invoke("google_authenticator_converter", { secret: data })

if (decoded.length === 0) {
return ""
}

// make a string
decoded.forEach((element) => {
const tempString = `\nName: ${element.name} \nSecret: ${element.secret} \nIssuer: ${element.issuer} \nType: OTP_TOTP\n`
Expand Down
7 changes: 6 additions & 1 deletion interface/windows/import/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ export const chooseImages = async () => {
importString += totpImageConverter(res.rawValue)
} else {
const converted = await migrationImageConverter(res.rawValue)
importString += converted

if (converted === "") {
return dialog.message("Failed to decode QR code(s). \n\nPlease try again with another picture!", { type: "error" })
} else {
importString += converted
}
}

// QR codes found on all images
Expand Down
Loading

0 comments on commit 8a6fa8f

Please sign in to comment.