Skip to content

Instantly share code, notes, and snippets.

@rupert-madden-abbott
Last active January 28, 2019 22:54
Show Gist options
  • Save rupert-madden-abbott/6219acc49045b71670af99b83cb6c795 to your computer and use it in GitHub Desktop.
Save rupert-madden-abbott/6219acc49045b71670af99b83cb6c795 to your computer and use it in GitHub Desktop.
Lastpass -> HaveIBeenPwned Passwords Checker

This script will search your exported Lastpass passwords against the HaveIBeenPwned password API and let you know if you have any breaches.

You need Maven and Kotlin.

  • Create a standard Maven directory layout
  • Add the pom.xml to the root directory
  • Add Application.kt to src/main/kotlin
  • Export your lastpass passwords to src/main/resources/temp.csv
  • Build and run the main method
  • Delete your temp.csv file when finished.
import org.apache.commons.csv.CSVFormat
import java.io.FileReader
import java.net.HttpURLConnection
import java.net.URL
import java.security.MessageDigest
fun main(args: Array<String>) {
val allCredentials = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(FileReader("src/main/resources/temp.csv"))
.filter { row -> !row["password"].isNullOrBlank() }
.map { row -> LastPassSite(row["name"], row["url"], hash(row["password"])) }
val credentialsCount = allCredentials.size
println("There are $credentialsCount credentials to check")
allCredentials.withIndex()
.mapNotNull { (index, credentials) ->
println("Checking credentials ${index + 1} of $credentialsCount")
val response = httpGet(
"https://api.pwnedpasswords.com/range/${credentials.passwordHashStart}",
"Kotlin Lastpass password checker - https://gist.github.com/rupert654/6219acc49045b71670af99b83cb6c795"
)
val breach = response.body
.lines()
.map { it.split(':') }
.map { Breach(it[0], it[1]) }
.firstOrNull { "${credentials.passwordHashStart}${it.passwordHash}" == credentials.passwordHash }
if (breach == null) null else BreachedCredentials(credentials, breach)
}
.forEach(::println)
}
data class HttpResponse(
val code: Int,
val body: String
)
data class Breach(
val passwordHash: String,
val count: String
)
data class BreachedCredentials(
val credentials: LastPassSite,
val breach: Breach
) {
override fun toString(): String {
return "Password for $credentials breached ${breach.count} times."
}
}
data class LastPassSite(
val name: String,
val url: String,
val passwordHash: String
) {
val passwordHashStart = passwordHash.substring(0..4)
override fun toString(): String {
var result = ""
if (name.isNotBlank()) {
result += name
}
if (url.isNotBlank()) {
result += " ($url)"
}
return result
}
}
fun hash(value: String): String {
val hexChars = "0123456789ABCDEF"
val bytes = MessageDigest
.getInstance("SHA-1")
.digest(value.toByteArray())
val result = StringBuilder(bytes.size * 2)
bytes.forEach {
val i = it.toInt()
result.append(hexChars[i shr 4 and 0x0f])
result.append(hexChars[i and 0x0f])
}
return result.toString()
}
fun httpGet(url: String, userAgent: String): HttpResponse {
val connection = URL(url).openConnection() as HttpURLConnection
connection.addRequestProperty("User-Agent", userAgent)
connection.connect()
val responseCode = connection.responseCode
if (responseCode != 200) {
throw IllegalStateException("Error getting URL $url with response code $responseCode")
}
return HttpResponse(responseCode, connection.inputStream.use { it.reader().use { reader -> reader.readText() } })
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.gist</groupId>
<artifactId>lastpass-checker</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<kotlin.version>1.3.20</kotlin.version>
<kotlin.code.style>official</kotlin.code.style>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment