Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Marcus Pedersén
ttp
Commits
ac189343
Commit
ac189343
authored
Oct 05, 2020
by
Marcus Pedersén
Browse files
Updated to version 1.0.0 and added enctyption choise, added man page
parent
f4dd62f5
Changes
5
Hide whitespace changes
Inline
Side-by-side
CHANGELOG.md
0 → 100644
View file @
ac189343
# Change Log
## [v1.0.0]
-
Added options to choose hash function to to generate TOTP password,
Available hash functions: Sha1 (Deefault), Sha256, Sha512
Cargo.lock
View file @
ac189343
...
...
@@ -537,7 +537,7 @@ dependencies = [
[[package]]
name = "ttp"
version = "
0.9
.0"
version = "
1.0
.0"
dependencies = [
"boringauth",
"data-encoding",
...
...
Cargo.toml
View file @
ac189343
[package]
name
=
"ttp"
version
=
"
0.9
.0"
version
=
"
1.0
.0"
authors
=
[
"marcus <marcus.pedersen@slu.se>"
]
edition
=
"2018"
...
...
man.1
0 → 100644
View file @
ac189343
.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>
src/main.rs
View file @
ac189343
...
...
@@ -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
();
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment