Created
August 12, 2018 19:27
-
-
Save mholt/1b05760370cefaf42e062b6428efac71 to your computer and use it in GitHub Desktop.
Use Go to check if a password has been pwned
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// checkPasswordPwned checks if the password is "pwned" according | |
// to the API offered by https://haveibeenpwned.com/. (The password | |
// is not sent to their servers to do the check.) | |
// | |
// This function returns the number of times the password appears in | |
// their data set. A password is pwned, or compromised, if the return | |
// value is greater than 0. | |
// | |
// API Docs: https://haveibeenpwned.com/API/v2#SearchingPwnedPasswordsByRange | |
// | |
// Written by Matthew Holt (@mholt6) for the Relica code base: https://relicabackup.com | |
func checkPasswordPwned(plaintextPass string) (int, error) { | |
pwdSha1 := fmt.Sprintf("%X", sha1.Sum([]byte(plaintextPass))) | |
prefix := pwdSha1[:5] | |
endpoint := fmt.Sprintf("https://api.pwnedpasswords.com/range/%s", prefix) | |
resp, err := http.Get(endpoint) | |
if err != nil { | |
return 0, err | |
} | |
defer resp.Body.Close() | |
scanner := bufio.NewScanner(resp.Body) | |
for scanner.Scan() { | |
parts := strings.SplitN(scanner.Text(), ":", 2) | |
if len(parts) < 2 { | |
continue | |
} | |
suffix := parts[0] | |
countStr := parts[1] | |
if prefix+suffix == pwdSha1 { | |
count, err := strconv.Atoi(countStr) | |
if err != nil { | |
return 0, fmt.Errorf("invalid count value received: %v", err) | |
} | |
return count, nil | |
} | |
} | |
if err := scanner.Err(); err != nil { | |
return 0, fmt.Errorf("scanning response body: %v", err) | |
} | |
return 0, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment