Commit ac189343 authored by Marcus Pedersén's avatar Marcus Pedersén
Browse files

Updated to version 1.0.0 and added enctyption choise, added man page

parent f4dd62f5
# Change Log
## [v1.0.0]
- Added options to choose hash function to to generate TOTP password,
Available hash functions: Sha1 (Deefault), Sha256, Sha512
......@@ -537,7 +537,7 @@ dependencies = [
[[package]]
name = "ttp"
version = "0.9.0"
version = "1.0.0"
dependencies = [
"boringauth",
"data-encoding",
......
[package]
name = "ttp"
version = "0.9.0"
version = "1.0.0"
authors = ["marcus <marcus.pedersen@slu.se>"]
edition = "2018"
......
.TH ttp 1 "October 2020" "ttp-1.0.0" "User manuals"
.SH NAME
\fBttp \fP- Get totp password code
\fB
.SH SYNOPSIS
.nf
.fam C
\fBttp\fP [\fIOPTION\fP] .. [\fIKEYNAME\fP]
.fam T
.fi
.fam T
.fi
.SH DESCRIPTION
Generates TOTP passwords in your terminal.
The encrypted files will be stored in your home directory at: $HOME/.ttp
.PP
If you add a new key and you made the wrong choice or you named it wrong,
you can delete the file in $HOME/.tpp/the_name.
.br
Eg. rm $HOME/.tpp/the_name
.br
and then add it again with: \fBtpp --new\fP
.PP
If you forget your master password, you will have to start over and add all your
keys from the begining.
.br
To delete your master password you will have to delete
the .ttp directory in your home.
.br
Eg. rm -rf $HOME/.ttp
.SH OPTIONS
.TP
.B
no args
Called with no args, same as \fB--list\fP or \fB-l\fP
.TP
.B
\fBKEYNAME\fP
Interactive, will ask for pass phrase to unlock and print current totp password code.
.br
Number of digits that will be generated depends on how many digis were choosen when key was added with option \fB--new\fP.
.TP
.B
\fB-n\fP, \fB--new\fP
Add new totp key, interactive. Give a discriptive name to your key, this name is listed with option \fB--list\fP
.br
Add your bas32 code, choose encoding and number of digits that should be generated.
.br
The default options gives a SHA1 encoded password code with 6 (six) digits.
.TP
.B
\fB-l\fP, \fB--list\fP
List names (\fIKEYNAME\fP) of available totp keys
.TP
.B
\fB-h\fP, \fB--help\fP
Print this help text and exit
.TP
.B
\fB--version\fP
output version information and exit
.RE
.PP
.SH AUTHOR
Written by Marcus Pedersén.
.SH REPORTING BUGS
Report bugs by creating an issue at: <https://projects.interbull.org/marcus/ttp>
.SH COPYRIGHT
.TP
Copyright © 2020 Marcus Pedersén. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
.TP
This is free software: you are free to change and redistribute it. There is no WARRANTY, to the extent permitted by law.
.SH SEE ALSO
For source code and binaries see: <https://projects.interbull.org/marcus/ttp>
......@@ -22,6 +22,7 @@ use std::path::PathBuf;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::fmt;
use rpassword;
use dirs;
use uuid::Uuid;
......@@ -33,15 +34,35 @@ const VERSION: &str = env!("CARGO_PKG_VERSION");
const DB_DIR: &str = ".ttp";
const PW_FILE: &str = ".ttp";
#[derive(PartialEq, PartialOrd)]
enum Hash {
Sha1,
Sha256,
Sha512,
}
impl fmt::Display for Hash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Hash::Sha1 => write!(f, "sha1"),
Hash::Sha256 => write!(f, "sha256"),
Hash::Sha512 => write!(f, "sha512"),
}
}
}
struct CryptKey {
name: String,
crypt_key: String,
digits: u8,
hash: Hash,
}
impl CryptKey {
fn new() -> CryptKey {
CryptKey { name: String::new(), crypt_key: String::new(), digits: 0 }
CryptKey { name: String::new(), crypt_key: String::new(), digits: 0, hash: Hash::Sha1 }
}
}
......@@ -423,6 +444,60 @@ fn add_new() -> Result<(), String> {
}
}
let mut in_hash = String::new();
let hash: Hash;
loop {
println!("Use hash algorithm:");
println!("1. sha1 (Default)");
println!("2. sha256");
println!("3. sha512");
print!("Choose 1-3, enter for default: ");
if std::io::stdout().flush().is_err() {
eprintln!("Error flushing stdout");
}
match std::io::stdin().lock().read_line(&mut in_hash) {
Ok(_) => (),
Err(e) => return Err(format!("Error reading from stdin: {}", e)),
}
in_hash = in_hash.trim().to_string();
if in_hash.is_empty() {
hash = Hash::Sha1;
break;
}
else {
match in_hash.parse::<u8>() {
Ok(d) => {
if d == 1 {
hash = Hash::Sha1;
break;
}
else if d == 2 {
hash = Hash::Sha256;
break;
}
else if d == 3 {
hash = Hash::Sha512;
break;
}
else {
println!("Choice must be an integer between 1-3");
in_hash = String::new();
}
}
Err(_) => {
println!("Choice must be an integer between 1-3");
in_hash = String::new();
},
}
}
}
new_key.hash = hash;
let mut in_digits = String::new();
let digits: u8;
loop {
......@@ -474,8 +549,8 @@ fn add_new() -> Result<(), String> {
if return_stat.is_ok() {
let mc = new_magic_crypt!(clear_pw, 256);
new_key.crypt_key = mc.encrypt_str_to_base64(base32);
let to_file = format!("# ttp\n# {}\n{}\n{}", new_key.name, new_key.crypt_key, new_key.digits);
let to_file = format!("# ttp\n# {}\n{}\n{}\n{}", new_key.name, new_key.crypt_key, new_key.digits, new_key.hash);
let mut full_path = PathBuf::new();
match dirs::home_dir() {
Some(d) => {
......@@ -523,12 +598,14 @@ fn get_key(name: String) -> Result<(), String> {
let mut name_exists = false;
let mut crypt_key = String::new();
let mut digits = 0;
let mut hash = Hash::Sha1;
for k in all_keys {
if name == k.name {
name_exists = true;
crypt_key = k.crypt_key;
digits = k.digits;
hash = k.hash;
}
}
......@@ -552,9 +629,25 @@ fn get_key(name: String) -> Result<(), String> {
}
if return_stat.is_ok() {
match TOTPBuilder::new().base32_key(&base32).hash_function(HashFunction::Sha1).output_len(digits.into()).finalize() {
Ok(t) => println!("Password code: {}", t.generate()),
Err(e) => return_stat = Err(format!("Error generating TOTP password code for: {}, Error: {:?}", name, e)),
if hash == Hash::Sha1 {
match TOTPBuilder::new().base32_key(&base32).hash_function(HashFunction::Sha1).output_len(digits.into()).finalize() {
Ok(t) => println!("Password code: {}", t.generate()),
Err(e) => return_stat = Err(format!("Error generating TOTP password code for: {}, Error: {:?}", name, e)),
}
}
if hash == Hash::Sha256 {
match TOTPBuilder::new().base32_key(&base32).hash_function(HashFunction::Sha256).output_len(digits.into()).finalize() {
Ok(t) => println!("Password code: {}", t.generate()),
Err(e) => return_stat = Err(format!("Error generating TOTP password code for: {}, Error: {:?}", name, e)),
}
}
if hash == Hash::Sha512 {
match TOTPBuilder::new().base32_key(&base32).hash_function(HashFunction::Sha512).output_len(digits.into()).finalize() {
Ok(t) => println!("Password code: {}", t.generate()),
Err(e) => return_stat = Err(format!("Error generating TOTP password code for: {}, Error: {:?}", name, e)),
}
}
}
}
......@@ -571,6 +664,8 @@ fn get_key(name: String) -> Result<(), String> {
/// First line: # ttp
/// Second line: # name_of_file
/// Third line: Contains encrypted string
/// Fourth line: Contains number of digits to generate
/// Fifth line: Contains hash algorithm to use
/// Returned vec contains CryptKey's
fn get_encrypted_key_from_all_files() -> Result<Vec<CryptKey>, String> {
let mut full_path = PathBuf::new();
......@@ -633,6 +728,21 @@ fn get_encrypted_key_from_all_files() -> Result<Vec<CryptKey>, String> {
Err(_) => break,
}
}
else if l_no == 5 {
let l_cont = l.unwrap();
if l_cont == "sha1" {
ck.hash = Hash::Sha1;
}
else if l_cont == "sha256" {
ck.hash = Hash::Sha256;
}
else if l_cont == "sha512" {
ck.hash = Hash::Sha512;
}
else {
break;
}
}
else {
ck.name = String::new();
ck.crypt_key = String::new();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment