2610.1 - Initial commit
This commit is contained in:
1 parent
8d1a244eb7
commit
1c5cc1a921
2 files changed
+176
-1
No files matched your search
@@ -1,3 +1,26 @@
|
||||
# checkpassword_py
|
||||
|
||||
Password Checker interface.
|
||||
Python/tkinter port of the C# `checkpassword` (SHA1Hash) WinForms app. Checks passwords against a local pwned-password API using SHA1 hashes.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3
|
||||
- tkinter (on Debian/Ubuntu: `sudo apt install python3-tk`)
|
||||
|
||||
No other dependencies — stdlib only.
|
||||
|
||||
## Run
|
||||
|
||||
```
|
||||
python3 checkpassword.py
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- **Hash** — SHA1-hashes the entered string and queries `https://www.home.daprogs.net/pwn/indexapi.php`. Shows the hit count if the password is in the master list.
|
||||
- **ZeroTrust** — sends only `sha5` (first 5 hash chars) plus 3 chars from a random position, querying `https://www.home.daprogs.net/pwn/zerotrust.php`. Reveals the full hash only if the server confirms a match.
|
||||
- **Create Report** — reads `passList-tci.csv` (rows: `user;...;password;domain`), hashes each password, queries the API, and writes compromised entries to `userReport-tci.txt`. Run from the directory containing the CSV.
|
||||
|
||||
## Note
|
||||
|
||||
SHA1 is used only as a lookup key for the pwned-password service, not for authentication.
|
||||
@@ -0,0 +1,152 @@
|
||||
import hashlib
|
||||
import random
|
||||
import tkinter as tk
|
||||
from tkinter import font as tkfont
|
||||
from urllib.parse import urlencode
|
||||
from urllib.request import urlopen
|
||||
|
||||
URL_FULL = "https://www.home.daprogs.net/pwn/indexapi.php"
|
||||
URL_ZERO = "https://www.home.daprogs.net/pwn/zerotrust.php"
|
||||
|
||||
|
||||
def compute_sha1(text: str) -> str:
|
||||
return hashlib.sha1(text.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def fetch(url: str, params: dict) -> str:
|
||||
try:
|
||||
with urlopen(f"{url}?{urlencode(params)}") as resp:
|
||||
return resp.read().decode("utf-8")
|
||||
except Exception as e:
|
||||
return f"Request exception: {e}"
|
||||
|
||||
|
||||
class App:
|
||||
def __init__(self, root: tk.Tk):
|
||||
self.root = root
|
||||
root.title("Password Checker")
|
||||
mono = tkfont.Font(family="Consolas", size=10)
|
||||
|
||||
tk.Label(root, text="Enter String").grid(row=0, column=0, columnspan=2, sticky="w")
|
||||
self.txt_input = tk.Entry(root, font=mono, width=40)
|
||||
self.txt_input.grid(row=1, column=0, sticky="we")
|
||||
self.btn_hash = tk.Button(root, text="Hash", command=self.on_hash)
|
||||
self.btn_hash.grid(row=1, column=1, sticky="we")
|
||||
self.txt_output = tk.Entry(root, font=mono, width=40)
|
||||
self.txt_output.grid(row=2, column=0, sticky="we")
|
||||
self.btn_zero = tk.Button(root, text="ZeroTrust", command=self.on_zero_trust)
|
||||
self.btn_zero.grid(row=2, column=1, sticky="we")
|
||||
self.lbl_status = tk.Label(root, text="...")
|
||||
self.lbl_status.grid(row=3, column=0, columnspan=2, sticky="w")
|
||||
self.txt_result = tk.Entry(root, font=mono, width=50)
|
||||
self.txt_result.grid(row=4, column=0, columnspan=2, sticky="we")
|
||||
self.txt_desc = tk.Text(root, font=mono, width=50, height=12)
|
||||
self.txt_desc.grid(row=5, column=0, columnspan=2, sticky="we")
|
||||
self.btn_report = tk.Button(root, text="Create Report", command=self.on_create_report)
|
||||
self.btn_report.grid(row=6, column=0, columnspan=2, sticky="we")
|
||||
root.columnconfigure(0, weight=1)
|
||||
root.bind("<Return>", lambda e: self.on_hash())
|
||||
self.txt_input.focus_set()
|
||||
|
||||
def clear_fields(self):
|
||||
self.txt_desc.delete("1.0", "end")
|
||||
self.txt_output.delete(0, "end")
|
||||
self.txt_result.delete(0, "end")
|
||||
self.root_update()
|
||||
|
||||
def select_all_input(self):
|
||||
self.txt_input.focus_set()
|
||||
self.txt_input.selection_range(0, "end")
|
||||
|
||||
def root_update(self):
|
||||
self.root.update()
|
||||
|
||||
def on_hash(self):
|
||||
self.clear_fields()
|
||||
h = compute_sha1(self.txt_input.get())
|
||||
self.txt_output.insert(0, h)
|
||||
self.lbl_status.config(text="web request...")
|
||||
self.root_update()
|
||||
ret = fetch(URL_FULL, {"sha1": h})
|
||||
self.lbl_status.config(text="response...")
|
||||
self.root_update()
|
||||
self.txt_result.insert(0, ret)
|
||||
self.lbl_status.config(text="...")
|
||||
self.root_update()
|
||||
if "BAD" in ret:
|
||||
count = ret.split(":")[1].replace("\r\n", "")
|
||||
self.txt_desc.insert("1.0",
|
||||
"This password is in the master list.\r\n"
|
||||
f"It has been seen {count} times\r\n"
|
||||
"Even a value of 1 is bad.\r\n"
|
||||
"You need to change this password ASAP!\r\n")
|
||||
self.select_all_input()
|
||||
|
||||
def on_zero_trust(self):
|
||||
self.clear_fields()
|
||||
h = compute_sha1(self.txt_input.get())
|
||||
self.txt_output.insert(0, h)
|
||||
sha5 = h[:5]
|
||||
start = random.randrange(6, 36)
|
||||
sha6 = h[start:start + 3]
|
||||
r_hash = h[5:]
|
||||
self.txt_output.delete(0, "end")
|
||||
self.txt_output.insert(0, r_hash)
|
||||
self.lbl_status.config(text="web request...")
|
||||
self.root_update()
|
||||
ret = fetch(URL_ZERO, {"sha5": sha5, "sha6": sha6})
|
||||
self.lbl_status.config(text="response...")
|
||||
self.root_update()
|
||||
self.lbl_status.config(text=f"request sent: {sha5}-{sha6}")
|
||||
self.root_update()
|
||||
if "BAD" in ret:
|
||||
if r_hash.lower() in ret.lower():
|
||||
self.txt_result.insert(0, "BAD - Your password is listed")
|
||||
desc = ret.replace("BAD:\r\n", "")
|
||||
self.txt_desc.insert("1.0", desc)
|
||||
pos = desc.find(r_hash.upper())
|
||||
if pos >= 0:
|
||||
self.txt_desc.tag_add("sel", f"1.0+{pos}", f"1.0+{pos + 35}")
|
||||
self.txt_desc.see(pos)
|
||||
else:
|
||||
self.txt_result.insert(0, "OK - Not in list")
|
||||
else:
|
||||
self.txt_result.insert(0, ret)
|
||||
self.select_all_input()
|
||||
|
||||
def on_create_report(self):
|
||||
self.clear_fields()
|
||||
with open("passList-tci.csv", encoding="utf-8", errors="replace") as f:
|
||||
pass_list = f.read().split("\r\n")
|
||||
total = len(pass_list)
|
||||
count = 0
|
||||
with open("userReport-tci.txt", "w", encoding="utf-8") as out:
|
||||
for item in pass_list:
|
||||
if "," in item:
|
||||
items = item.split(",")
|
||||
email = items[0].split(";")[0] + "@" + items[2]
|
||||
password = items[1]
|
||||
if len(password) > 0:
|
||||
h = compute_sha1(password)
|
||||
self.txt_output.delete(0, "end")
|
||||
self.txt_output.insert(0, h)
|
||||
self.txt_result.delete(0, "end")
|
||||
self.txt_result.insert(0, f"{count}/{total}")
|
||||
self.lbl_status.config(text="web request...")
|
||||
self.root_update()
|
||||
ret = fetch(URL_FULL, {"sha1": h})
|
||||
self.lbl_status.config(text="response...")
|
||||
self.root_update()
|
||||
if "BAD" in ret:
|
||||
out.write(f"{email},Password is hacked!({ret.split(':')[1].replace(chr(13) + chr(10), '')})\n")
|
||||
count += 1
|
||||
self.txt_output.delete(0, "end")
|
||||
self.txt_output.insert(0, "Complete.")
|
||||
self.lbl_status.config(text="Complete.")
|
||||
self.root_update()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
root = tk.Tk()
|
||||
App(root)
|
||||
root.mainloop()
|
||||
Reference in new issue
Block a user