Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PowerShell script to check password against leaked password database from https://haveibeenpwned.com/ using the Pwned Passwords V2 API. Only the first 5 characters of the password string hash is checked against the API (k-anonymity). More info on the HIBP API at https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/.
#requires -version 4
<#
.SYNOPSIS
Check password against leaked password database from https://haveibeenpwned.com/ using the Pwned Passwords V2 API https://api.pwnedpasswords.com/range/<hashPrefix>.
.DESCRIPTION
Only the first 5 characters of the password string hash is checked against the API (k-anonymity). The API returns a list of all passwords matching the hash prefix, then the script checks if the suffix is present or not.
More info on the HIBP API at https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/.
.PARAMETER Password
Enter the password to check.
.PARAMETER SecurePassword
Switch to enable secure prompt for password.
.EXAMPLE
.\Test-LeakedPasswordHIBP.ps1 -password "P@ssw0rd"
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)]
[string]$Password,
[Parameter(Mandatory=$False)]
[switch]$SecurePassword
)
if ($SecurePassword) {
$Credentials = Get-Credential -Message "Enter the password to test" -UserName "dummy"
$Password = $credentials.GetNetworkCredential().Password
} else {
if ($Password -eq "") {
$Password = Read-Host -Prompt "Enter the password to test"
}
}
#Force TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
#Create SHA-1 hash from string
Function Get-StringHash()
{
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True)]
[String]$inputString
)
$Private:outputHash = [string]::Empty
$hasher = New-Object -TypeName "System.Security.Cryptography.SHA1CryptoServiceProvider"
$hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($inputString)) | ForEach-Object { $outputHash += $_.ToString("x2") }
$outputHash.ToUpper()
}
$stringHash = Get-StringHash -inputString $Password
$hashPrefix = $stringHash.Substring(0, 5)
$hashSuffix = $stringHash.Substring(5, ($stringHash.Length - 5))
try {
$response = Invoke-RestMethod -Uri "https://api.pwnedpasswords.com/range/$($hashPrefix)" -Method Get -ErrorVariable errorRequest
}
catch {
Write-Output "Error with the request!"
Write-Output $errorRequest
break
}
if ($response -ne $null) {
$findHashSuffix = $response.Contains($hashSuffix)
if ($findHashSuffix -eq $true) {
$result = $response.Substring($response.IndexOf($hashSuffix), $response.IndexOf([System.Environment]::NewLine, $response.IndexOf($hashSuffix)) - $response.IndexOf($hashSuffix))
$resultCount = ($result.Split(":"))[1]
Write-Output "Your password has been found $($resultCount) times!"
}
else {
Write-Output "Your password has not been found."
}
}
else {
Write-Output "No occurence of the hash prefix found."
}
@toledotown

This comment has been minimized.

Copy link

toledotown commented Feb 26, 2018

It should be noted that haveibeenpwned.com strongly discourages you from testing production or sensitive passwords in this way.

@pyrocumulus

This comment has been minimized.

Copy link

pyrocumulus commented Feb 27, 2018

@toledotown I don't think that's entirely correct. They discourage you from using the passwords page on the HIBP website and entering passwords you actually use on that site. What this script does is hash the password on the client machine and only send the first five characters to the HIBP api for verification.

But, one could say that using a script like this poses a risk in itself. Which is quite true, but only when you don't understand the script.

@mrik23

This comment has been minimized.

Copy link
Owner Author

mrik23 commented Mar 2, 2018

As long as you trust the machine on which the script is running, I think it's pretty safe. We just retrieve a list of hash from the API and then the comparison is done locally on the machine.

@patschi

This comment has been minimized.

Copy link

patschi commented May 8, 2019

If anyone comes across the same issue: The script unfortunately fails on non-Windows machines, e.g. using PSCore on Linux. The failing line is 92, and related to the Substring.

The reason is that [System.Environment]::NewLine returns back following:

  • on Windows: \r\n
  • on Linux: \n

But as the HIBP API reports back the hashes splitted by the Windows line-endings, the IndexOf/Substring at line 92 fails. The fix is quite simple: Just replace [System.Environment]::NewLine on line 92 with `r`n.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.