From 296f4d39e048e2aa05e1961e581adb470eb351ff Mon Sep 17 00:00:00 2001 From: Matthias Gessinger <52350962+MGessinger@users.noreply.github.com> Date: Mon, 9 Dec 2019 11:53:54 +0100 Subject: [PATCH] Julia version * Julia version Add a version for the Julis Programming language. Required Packages: * HTTP * SHA Notice that HTTP does a bunch of junk in the background when you first call to it. Therefore the first call is super slow but all subsequent calls are fairly quick. * Julia Version Add lots of comments into the code. Also the program will now inform the user, that passwords provided as command-line arguments are stored in the history as plain text and it is therefore recommended to clear the history afterwards. * Julia Version Fix a typo and some formatting --- pwned.jl | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 pwned.jl diff --git a/pwned.jl b/pwned.jl new file mode 100644 index 0000000..73df326 --- /dev/null +++ b/pwned.jl @@ -0,0 +1,71 @@ +using HTTP +using SHA + +function lookup_pwned_api(pwd::AbstractString) + # Compute the SHA1 hash of pwd and split it at the fifth position + sha1pwd = bytes2hex(sha1(pwd)) + head,tail = sha1pwd[1:5], sha1pwd[6:end] + + # Query the pwnedpasswords API + url = "https://api.pwnedpasswords.com/range/$head" + res = HTTP.request("GET",url) + if (res.status != 200) + @error "The API lookup failed!" + end + + # The hashes are stored in the body of the response as hex characters (notice: NOT integers) + # To split them, look for line-feeds, which in this case are given by CRLF (boo) + hashes = split(String(res.body),"\r\n") + hashes = [split(st,':') for st in hashes] + + # Find whether or not pwd (or rather its hash) appears in the list of all hashes! + # Because the characters in the response are uppercase (01233456789ABCDEF) + # and bytes2hex produces lowercase (0123456789abcdef), comparing strings is not good enough. + # Instead do a RegEx match with the i flag set! + found = 0 + re = Regex(tail,"i") + for h in hashes + # h[1] is the tail of the hash, h[2] is the number of occurances + if match(re,h[1]) != nothing + found = h[2] + break + end + end + return sha1pwd,found +end + +function check_pwd(pwd::AbstractString) + # Check whether (and if so, how often) the string pwd has been pwned. + sha1pwd,cnt = "",0 + try + sha1pwd,cnt = lookup_pwned_api(pwd) + catch e + # Error Message is printed elsewhere. Just return silently + return + end + # cnt is the number of occurances. If pwd has not been pwned yet, cnt is zero. + print("Password $pwd with the hash $sha1pwd was ") + if (cnt != 0) + print("found $cnt times!\n") + else + print("not found!\n") + end +end + +# ARGS stores the command-line arguments passed to pwned.jl +# If none were given, ARGS is empty and pwned.jl will read from stdin +if ARGS == [] + print("Reading passwords from stdin. Type exit or ^C to quit.\n") + while true + pwd = readline() + if pwd == "exit" + break + end + check_pwd(pwd) + end +else + @warn "Entering passwords in plain text on a terminal is a bad idea!i\nInstead run this program without any arguments,\nin which case it reads from stdin and no history will be created.\nIt is highly recommended to clear your terminal's history after using this program!" + for pwd in ARGS + check_pwd(pwd) + end +end