Skip to content

Commit

Permalink
Added python GUI and HTML versions
Browse files Browse the repository at this point in the history
Simple web interface using the API should be mobile compatible.

A simple GUI interface using the original python script as the basis.
  • Loading branch information
PascalPirate75 authored and mikepound committed Mar 20, 2019
1 parent 2fa784b commit b036453
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 0 deletions.
166 changes: 166 additions & 0 deletions html/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<!DOCTYPE html>
<!-- FYI must be serverd via HTTPS to function properly -->
<html>
<head>
<meta charset='UTF-8'/>
<title>Pwned Password API lookup.</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<style>
* {
box-sizing: border-box;
}

html, body {
background-color:lightblue;
cursor:pointer;
height:100%;
width:100%;
padding:0;
margin:0;
}

b {
color : red;
}

#bodyDiv {
border:2px solid blue;
border-radius:7px;
height:150px;
width:600px;
margin:80px;
padding:25px;
background-color:darkgrey;
color:black;
}

@media only screen and (max-width : 700px) {

#bodyDiv {
border:2px solid blue;
border-radius:7px;
width:100%;
height:80%;
margin:0;
padding:25px;
background-color:darkgrey;
color:black;
}

#hash {
font-size:10px;
}

}

</style>
</head>
<body>
<div id="bodyDiv">
<span title="Password does not leave the browser, but it will show on the screen.">?</span>
<input id="inPut" type="text" placeholder="Password...">
<button title="Click to send part of hashed password.">Check</button>
<div>
<p id="outPut"></p>
</div>

</div>
<a href="https://github.com/mikepound/pwned-search">The inspiration!</a>
<script>
let first = "";
let last = "";
let hash = "";
function hexString(buffer) {
// creates an array of 8-bit unsigned integers
const byteArray = new Uint8Array(buffer);
// turns that hash into hex
const hexCodes = [...byteArray].map(value => {
// eash element in array is converted to base 16 string
const hexCode = value.toString(16);
// pad beggining with 0 why?
const paddedHexCode = hexCode.padStart(2, '0');
// return upper case hex hash
return paddedHexCode.toUpperCase();
});
// return a string not an array
return hexCodes.join('');
}

function digestMessage(message) {
// Returns a newly constructed TextEncoder that will generate a byte stream with utf-8 encoding.
const encoder = new TextEncoder();
// Takes a USVString as input, and returns a Uint8Array containing utf-8 encoded text.
const data = encoder.encode(message);
// returns the hash
//The digest() method of the SubtleCrypto interface generates a digest of the given data.
// A digest is a short fixed-length value derived from some variable-length input.
return window.crypto.subtle.digest('SHA-1', data);
}

function runCheck() {
let outPut = document.getElementById("outPut");
let inPut = document.getElementById("inPut");
let text = inPut.value;
if (text === "") return false;
inPut.value = "";


digestMessage(text).then(digestValue => {
hash = hexString(digestValue);
first = hash.substring(0, 5);
last = hash.substring(5);
fetch('https://api.pwnedpasswords.com/range/' + first)
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
return response.text();
})
.then(function(text) {
return text.split("\r\n");
})
.then(function(arr){

document.getElementById("outPut")
.innerHTML = "The password : " + text +
"SHA1 Hash : " + hash +
"<br>Was not found!";

arr.forEach((s)=>{

let a = s.split(":");

if(a[0] == last) {

document.getElementById("outPut")
.innerHTML = "The password : " + text +
"<br>SHA1 Hash : <span id='hash'>" + hash +
"</span><br>Was found <b>" + a[1] + "</b> times!";

return true;

}

});

})
.catch(function(error) {
log('Request failed', error)
});

});

outPut.value = "";

}

document.querySelector("button")
.addEventListener("click", runCheck);

</script>
</body>
</html>

65 changes: 65 additions & 0 deletions pwnedGUI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python
from tkinter import Tk, Label, Button, Entry, StringVar, IntVar, END, W, E
from pwned import lookup_pwned_api
import hashlib
import sys

try:
import requests
except ModuleNotFoundError:
print("### pip install requests ###")
raise


class Calculator:

def __init__(self, master):
self.master = master
master.title("pwned GUI by PPC")
self.p = "";

self.head_label_text = ""
self.head_label = Label(master, textvariable=self.head_label_text)
self.label = Label(master, text="Enter the password to check : ")

vcmd = master.register(self.validate) # we have to wrap the command
self.entry = Entry(master, validate="key", validatecommand=(vcmd, '%P'))

self.submit_button = Button(master, text="Check", command=lambda: self.update("submit"))

self.total_label_text = "Number of times Password found : ...."
self.total_text = StringVar()
self.total_text.set(self.total_label_text)
self.total_label = Label(master, textvariable=self.total_text)
self.total = Label(master, text="")

# LAYOUT

self.label.grid(row=0, column=0, sticky=W, padx=(25, 25), pady=(25, 10))

self.head_label.grid(row=0, column=1, columnspan=4, sticky=E, padx=(25, 25), pady=(10, 10))

self.entry.grid(row=2, column=0, columnspan=3, sticky=W+E, padx=(25, 25), pady=(10, 10))

self.submit_button.grid(row=2, column=4, sticky=W+E, padx=(25, 25), pady=(10, 10))

self.total_label.grid(row=4, column=0, columnspan=3, sticky=W, padx=(25, 25), pady=(10, 20))

def validate(self, new_text):
if not new_text: # the field is being cleared
return True
try:
self.p = new_text
return True
except ValueError:
return False

def update(self, method):
self.total = "Number of times Password found : " + str(lookup_pwned_api(self.p)[1])
self.total_text.set(self.total)
self.entry.delete(0, END)


root = Tk()
my_gui = Calculator(root)
root.mainloop()

0 comments on commit b036453

Please sign in to comment.