Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
Smash_pass
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Smashpass
Smash_pass
Commits
d5cd51e4
Commit
d5cd51e4
authored
Dec 09, 2024
by
Benjamin REED
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
working build, basically feature complete, could use some bug testing
parent
792c364a
Pipeline
#3049
canceled with stages
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
193 additions
and
188 deletions
+193
-188
main.py
main.py
+193
-188
No files found.
main.py
View file @
d5cd51e4
import
sys
import
sys
from
typing
import
Optional
import
secrets
import
secrets
import
os
import
os
import
random
import
random
...
@@ -156,22 +157,200 @@ class State:
...
@@ -156,22 +157,200 @@ class State:
file
.
close
()
file
.
close
()
def
caesar_cipher
(
inp
,
offset
):
pass
def
generate_password
(
length
,
charset
):
def
generate_password
(
length
,
charset
):
s
=
[]
s
=
[]
for
i
in
range
(
0
,
length
):
for
i
in
range
(
0
,
length
):
s
.
append
(
random
.
choice
(
list
(
charset
)))
s
.
append
(
random
.
choice
(
list
(
charset
)))
return
''
.
join
(
s
)
return
''
.
join
(
s
)
def
aes_256
(
inp
):
pass
def
handle_args
(
db
:
str
,
password
:
str
):
def
handle_args
(
db
:
str
,
password
:
str
):
state
=
State
(
db
,
password
)
state
=
State
(
db
,
password
)
return
state
return
state
def
handle_command
(
state
:
State
,
args
:
[
str
],
cfg
)
->
Optional
[
bool
]:
command
=
args
[
0
]
if
command
==
"q"
or
command
==
"quit"
or
command
==
"exit"
:
if
len
(
args
)
==
2
:
if
args
[
1
]
==
"f"
or
args
[
1
]
==
"force"
or
args
[
1
]
==
"nosave"
:
if
len
(
args
)
>
2
and
args
[
2
]
==
"y"
:
return
True
elif
confirm
(
"Are you sure you want to exit without saving?"
,
"y"
,
"n"
):
return
True
else
:
return
False
if
command
==
"cfg"
or
command
==
"config"
or
command
==
"settings"
:
if
len
(
args
)
<
2
:
print
(
f
"Settings: hints: {cfg['hints']}, ..."
)
return
None
s
=
args
[
1
]
.
split
(
"="
)
if
len
(
s
)
<
2
:
print
(
f
"Incorrect format for modifying program parameters. Usage: {USAGES['cfg']}"
)
return
None
if
s
[
0
]
not
in
cfg
:
print
(
f
"Unknown cfg parameter '{s[0]}'. Type 'cfg' for a list of config parameters."
)
return
None
try
:
cfg
[
s
[
0
]]
=
s
[
1
]
except
:
print
(
f
"Incorrect format for cfg parameter {s[0]}, expected type {type(cfg[s[0]])}"
)
elif
command
==
"help"
or
command
==
"h"
or
command
==
"?"
:
if
len
(
args
)
==
1
:
print
(
"Available commands: "
)
print
(
"
\t
"
+
", "
.
join
(
USAGES
.
keys
()))
if
cfg
[
'hints'
]
==
True
:
print
(
"(Hint: type 'help <command name>' for more detailed info about that command)"
)
else
:
cmd
=
args
[
1
]
if
not
cmd
in
USAGES
:
print
(
"Unknown command, you may have mistyped it."
)
return
None
print
(
USAGES
[
cmd
])
elif
command
==
"echo"
:
if
len
(
args
)
<
2
:
print
(
f
"Too few arguments for {command}, usage: {USAGES['echo']}"
)
return
None
print
(
" "
.
join
(
args
[
1
:]))
elif
command
==
"save"
or
command
==
"s"
:
try
:
state
.
save
()
print
(
f
"State saved to {filepath}!"
)
except
:
print
(
"There was an error saving, maybe back up your stuff now. Sorry"
)
elif
command
==
"drop"
or
command
==
"delete"
or
command
==
"del"
or
command
==
"rm"
:
if
len
(
args
)
<
2
:
print
(
f
"Too few arguments for command {command}, usage: {USAGES['drop']}"
)
return
None
label
=
args
[
1
]
.
strip
()
.
lower
()
if
label
in
state
.
to_remove
:
if
confirm
(
f
"Are you sure you want to PERMANANTLY DELETE {label}? FOREVER????? (Note: this CANNOT be undone)"
,
"y"
,
"n"
):
del
state
.
passwords
[
label
]
del
state
.
to_remove
[
state
.
to_remove
.
index
(
label
)]
print
(
f
"Password '{label}' was permanently removed from database. This cannot be undone."
)
elif
label
in
state
.
passwords
:
if
confirm
(
f
"Are you sure you want to delete {label}?"
,
"y"
,
"n"
):
state
.
to_remove
.
append
(
label
)
print
(
f
"Password '{label}' removed from database."
)
if
cfg
[
'hints'
]
==
True
:
print
(
"(Hint: use 'undo' to undo this operation, and 'history' to see previous deleted passwords and restore them)"
)
else
:
print
(
f
"Password '{label}' was not found, have you spelt it correctly?"
)
elif
command
==
"undo"
or
command
==
"un"
:
if
len
(
state
.
to_remove
)
==
0
:
print
(
"Already on latest change"
)
return
None
ltst
=
state
.
to_remove
.
pop
()
print
(
f
"Undone latest deletion: {ltst}"
)
elif
command
==
"restore"
or
command
==
"res"
or
command
==
"r"
:
if
len
(
args
)
<
2
:
print
(
f
"Too few arguments for command {command}. Usage: {USAGES['restore']}"
)
return
None
args
[
1
]
.
strip
()
og_label
=
args
[
1
]
.
lower
()
label
=
og_label
if
og_label
in
state
.
passwords
and
(
og_label
in
state
.
overwritten
or
og_label
in
state
.
to_remove
):
print
(
"You will have to rename this password to restore it."
)
label_in
=
input
(
"New label (If left empty, a number will be used): "
)
if
label_in
==
""
:
label
=
str
(
len
(
state
.
passwords
)
+
1
)
# oh so hacky, i hate python and i want my damn state to be operated on by its own damn functions. I hate this.
else
:
label_in
.
strip
()
label
=
label_in
.
lower
()
if
og_label
in
state
.
to_remove
:
del
state
.
to_remove
[
state
.
to_remove
.
index
(
og_label
)]
print
(
f
"Restored {og_label}"
)
elif
og_label
in
state
.
overwritten
:
del
state
.
overwritten
[
state
.
overwritten
.
index
(
og_label
)]
state
.
passwords
[
label
]
=
state
.
passwords
[
f
"old({og_label})"
]
del
state
.
passwords
[
f
"old({og_label})"
]
print
(
f
"Restored {og_label}"
)
else
:
print
(
f
"Label '{og_label}' could not be found in deleted or overwritten passwords"
)
elif
command
==
"rename"
or
command
==
"rn"
:
if
len
(
args
)
<
3
:
print
(
f
"Too few args for {command}. Usage: {USAGES['rename']}."
)
return
None
if
args
[
1
]
in
state
.
passwords
:
state
.
passwords
[
args
[
2
]]
=
state
.
passwords
[
args
[
1
]]
del
state
.
passwords
[
args
[
1
]]
print
(
f
"{args[1]} -> {args[2]}"
)
else
:
print
(
f
"{args[1]} is not a known password label"
)
elif
command
==
"history"
or
command
==
"his"
or
command
==
"undolist"
:
print
(
"Deleted:"
)
for
remd
in
state
.
to_remove
:
print
(
f
"{remd}: [...]"
,
end
=
' '
)
print
(
"
\n
Overwritten:"
)
for
over
in
state
.
overwritten
:
print
(
f
"{over}: [...]"
,
end
=
' '
)
print
(
""
)
elif
command
==
"new"
:
# Form: new <length> [ <label> ]
if
len
(
args
)
<
2
:
print
(
f
"Too few arguments for {command}, usage: {USAGES['new']}"
)
return
None
try
:
length
=
int
(
args
[
1
])
except
:
print
(
f
"Error parsing length as number, usage: {USAGES['new']}"
)
return
None
if
len
(
args
)
>=
3
:
label
=
args
[
2
]
else
:
label
=
""
if
label
in
state
.
passwords
:
print
(
f
"Error generating new password, label '{label}' is already in use."
)
if
label
in
state
.
overwritten
:
if
confim
(
"Do you want to PERMANENTLY OVERWRITE {label}? (THIS CANNOT BE UNDONE)"
,
"y"
,
"n"
):
todo
if
confirm
(
"Would you like to replace it?"
,
"y"
,
"n"
):
state
.
overwritten
.
append
(
label
)
state
.
passwords
[
f
"old({label})"
]
=
state
.
passwords
[
label
]
print
(
f
"Overwriting '{label}' with new password..."
)
if
cfg
[
'hints'
]
==
True
:
print
(
"(Hint: use the 'restore' command to undo this action)"
)
else
:
return
None
charset
=
"all"
chars
=
set
()
if
len
(
args
)
==
4
:
charset
=
args
[
3
]
if
charset
==
"all"
:
chars
=
LOWERCASE_ALPHABET
|
UPPERCASE_ALPHABET
|
NUMBERS
|
SPECIAL
else
:
s
=
charset
.
split
(
"-"
)
for
c
in
list
(
s
[
0
]):
chars
|=
CHARSET_MAP
[
c
]
if
len
(
s
)
>
1
:
for
c
in
s
[
1
]:
# list of chars to exclude
chars
^=
set
(
c
)
password
=
generate_password
(
length
,
chars
)
print
(
str
(
password
))
state
.
add_password
(
label
,
password
)
elif
command
==
"list"
or
command
==
"ls"
:
if
len
(
args
)
==
1
:
# if state.passwords.len() >= 10:
# TODO: make it possible to scroll thru a list of passwords
for
l
in
state
.
passwords
:
if
l
not
in
state
.
to_remove
and
"old"
not
in
l
:
print
(
f
"{l}: [...]"
)
if
cfg
[
'hints'
]
==
True
:
print
(
"(Hint: type 'list <key>' to decrypt your chosen password"
)
elif
len
(
args
)
==
2
:
print
(
state
.
get_password
(
args
[
1
])
.
decode
(
'utf-8'
))
return
None
def
main
():
def
main
():
filepath
=
""
filepath
=
""
if
len
(
sys
.
argv
)
<
2
:
if
len
(
sys
.
argv
)
<
2
:
...
@@ -221,190 +400,16 @@ def main():
...
@@ -221,190 +400,16 @@ def main():
if
len
(
args
)
==
0
:
if
len
(
args
)
==
0
:
continue
continue
command
=
args
[
0
]
should_immediately_exit
=
None
try
:
if
command
==
"q"
or
command
==
"quit"
or
command
==
"exit"
:
should_immediately_exit
=
handle_command
(
state
,
args
,
cfg
)
if
len
(
args
)
==
2
:
except
e
:
if
args
[
1
]
==
"f"
or
args
[
1
]
==
"force"
or
args
[
1
]
==
"nosave"
:
print
(
f
"ERROR: handling the inputted command: {e}"
)
if
confirm
(
"Are you sure you want to exit without saving?"
,
"y"
,
"n"
):
if
should_immediately_exit
is
not
None
:
return
if
should_immediately_exit
:
return
else
:
else
:
break
break
if
command
==
"cfg"
or
command
==
"config"
or
command
==
"settings"
:
if
len
(
args
)
<
2
:
print
(
f
"Settings: hints: {cfg['hints']}, ..."
)
continue
s
=
args
[
1
]
.
split
(
"="
)
if
len
(
s
)
<
2
:
print
(
f
"Incorrect format for modifying program parameters. Usage: {USAGES['cfg']}"
)
continue
if
s
[
0
]
not
in
cfg
:
print
(
f
"Unknown cfg parameter '{s[0]}'. Type 'cfg' for a list of config parameters."
)
continue
try
:
cfg
[
s
[
0
]]
=
s
[
1
]
except
:
print
(
f
"Incorrect format for cfg parameter {s[0]}, expected type {type(cfg[s[0]])}"
)
elif
command
==
"help"
or
command
==
"h"
or
command
==
"?"
:
if
len
(
args
)
==
1
:
print
(
"Available commands: "
)
print
(
"
\t
"
+
", "
.
join
(
USAGES
.
keys
()))
if
cfg
[
'hints'
]
==
True
:
print
(
"(Hint: type 'help <command name>' for more detailed info about that command)"
)
else
:
cmd
=
args
[
1
]
if
not
cmd
in
USAGES
:
print
(
"Unknown command, you may have mistyped it."
)
continue
print
(
USAGES
[
cmd
])
elif
command
==
"echo"
:
if
len
(
args
)
<
2
:
print
(
f
"Too few arguments for {command}, usage: {USAGES['echo']}"
)
continue
print
(
" "
.
join
(
args
[
1
:]))
elif
command
==
"dbg"
:
print
(
vars
(
state
))
elif
command
==
"save"
or
command
==
"s"
:
try
:
state
.
save
()
print
(
f
"State saved to {filepath}!"
)
except
:
print
(
"There was an error saving, maybe back up your stuff now. Sorry"
)
elif
command
==
"drop"
or
command
==
"delete"
or
command
==
"del"
or
command
==
"rm"
:
if
len
(
args
)
<
2
:
print
(
f
"Too few arguments for command {command}, usage: {USAGES['drop']}"
)
continue
label
=
args
[
1
]
.
strip
()
.
lower
()
if
label
in
state
.
to_remove
:
if
confirm
(
f
"Are you sure you want to PERMANANTLY DELETE {label}? FOREVER????? (Note: this CANNOT be undone)"
,
"y"
,
"n"
):
del
state
.
passwords
[
label
]
del
state
.
to_remove
[
state
.
to_remove
.
index
(
label
)]
print
(
f
"Password '{label}' was permanently removed from database. This cannot be undone."
)
elif
label
in
state
.
passwords
:
if
confirm
(
f
"Are you sure you want to delete {label}?"
,
"y"
,
"n"
):
state
.
to_remove
.
append
(
label
)
print
(
f
"Password '{label}' removed from database."
)
if
cfg
[
'hints'
]
==
True
:
print
(
"(Hint: use 'undo' to undo this operation, and 'history' to see previous deleted passwords and restore them)"
)
else
:
print
(
f
"Password '{label}' was not found, have you spelt it correctly?"
)
elif
command
==
"undo"
or
command
==
"un"
:
if
len
(
state
.
to_remove
)
==
0
:
print
(
"Already on latest change"
)
continue
ltst
=
state
.
to_remove
.
pop
()
print
(
f
"Undone latest deletion: {ltst}"
)
elif
command
==
"restore"
or
command
==
"res"
or
command
==
"r"
:
if
len
(
args
)
<
2
:
print
(
f
"Too few arguments for command {command}. Usage: {USAGES['restore']}"
)
continue
args
[
1
]
.
strip
()
og_label
=
args
[
1
]
.
lower
()
label
=
og_label
if
og_label
in
state
.
passwords
and
(
og_label
in
state
.
overwritten
or
og_label
in
state
.
to_remove
):
print
(
"You will have to rename this password to restore it."
)
label_in
=
input
(
"New label (If left empty, a number will be used): "
)
if
label_in
==
""
:
label
=
str
(
len
(
state
.
passwords
)
+
1
)
# oh so hacky, i hate python and i want my damn state to be operated on by its own damn functions. I hate this.
else
:
label_in
.
strip
()
label
=
label_in
.
lower
()
if
og_label
in
state
.
to_remove
:
del
state
.
to_remove
[
state
.
to_remove
.
index
(
og_label
)]
print
(
f
"Restored {og_label}"
)
elif
og_label
in
state
.
overwritten
:
del
state
.
overwritten
[
state
.
overwritten
.
index
(
og_label
)]
state
.
passwords
[
label
]
=
state
.
passwords
[
f
"old({og_label})"
]
del
state
.
passwords
[
f
"old({og_label})"
]
print
(
f
"Restored {og_label}"
)
else
:
print
(
f
"Label '{og_label}' could not be found in deleted or overwritten passwords"
)
elif
command
==
"rename"
or
command
==
"rn"
:
if
len
(
args
)
<
3
:
print
(
f
"Too few args for {command}. Usage: {USAGES['rename']}."
)
continue
if
args
[
1
]
in
state
.
passwords
:
state
.
passwords
[
args
[
2
]]
=
state
.
passwords
[
args
[
1
]]
del
state
.
passwords
[
args
[
1
]]
print
(
f
"{args[1]} -> {args[2]}"
)
else
:
print
(
f
"{args[1]} is not a known password label"
)
elif
command
==
"history"
or
command
==
"his"
or
command
==
"undolist"
:
print
(
"Deleted:"
)
for
remd
in
state
.
to_remove
:
print
(
f
"{remd}: [...]"
,
end
=
' '
)
print
(
"
\n
Overwritten:"
)
for
over
in
state
.
overwritten
:
print
(
f
"{over}: [...]"
,
end
=
' '
)
print
(
""
)
elif
command
==
"new"
:
# Form: new <length> [ <label> ]
if
len
(
args
)
<
2
:
print
(
f
"Too few arguments for {command}, usage: {USAGES['new']}"
)
continue
try
:
length
=
int
(
args
[
1
])
except
:
print
(
f
"Error parsing length as number, usage: {USAGES['new']}"
)
continue
if
len
(
args
)
>=
3
:
label
=
args
[
2
]
else
:
label
=
""
if
label
in
state
.
passwords
:
print
(
f
"Error generating new password, label '{label}' is already in use."
)
if
label
in
state
.
overwritten
:
if
confim
(
"Do you want to PERMANENTLY OVERWRITE {label}? (THIS CANNOT BE UNDONE)"
,
"y"
,
"n"
):
todo
if
confirm
(
"Would you like to replace it?"
,
"y"
,
"n"
):
state
.
overwritten
.
append
(
label
)
state
.
passwords
[
f
"old({label})"
]
=
state
.
passwords
[
label
]
print
(
f
"Overwriting '{label}' with new password..."
)
if
cfg
[
'hints'
]
==
True
:
print
(
"(Hint: use the 'restore' command to undo this action)"
)
else
:
continue
charset
=
"all"
chars
=
set
()
if
len
(
args
)
==
4
:
charset
=
args
[
3
]
if
charset
==
"all"
:
chars
=
LOWERCASE_ALPHABET
|
UPPERCASE_ALPHABET
|
NUMBERS
|
SPECIAL
else
:
s
=
charset
.
split
(
"-"
)
for
c
in
list
(
s
[
0
]):
chars
|=
CHARSET_MAP
[
c
]
if
len
(
s
)
>
1
:
for
c
in
s
[
1
]:
# list of chars to exclude
chars
^=
set
(
c
)
password
=
generate_password
(
length
,
chars
)
print
(
str
(
password
))
state
.
add_password
(
label
,
password
)
elif
command
==
"list"
or
command
==
"ls"
:
if
len
(
args
)
==
1
:
# if state.passwords.len() >= 10:
# TODO: make it possible to scroll thru a list of passwords
for
l
in
state
.
passwords
:
if
l
not
in
state
.
to_remove
and
"old"
not
in
l
:
print
(
f
"{l}: [...]"
)
if
cfg
[
'hints'
]
==
True
:
print
(
"(Hint: type 'list <key>' to decrypt your chosen password"
)
elif
len
(
args
)
==
2
:
print
(
state
.
get_password
(
args
[
1
])
.
decode
(
'utf-8'
))
state
.
save
()
state
.
save
()
print
(
"Thanks for using!"
)
print
(
"Thanks for using!"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a 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