mirror of
https://github.com/wneessen/go-hibp.git
synced 2024-11-22 12:50:50 +01:00
commit
659a359ea0
4 changed files with 42 additions and 14 deletions
18
README.md
18
README.md
|
@ -1,15 +1,19 @@
|
||||||
# go-hibp - Simple go client for the HIBP API
|
# go-hibp - Simple Go binding to the "Have I Been Pwned" API
|
||||||
|
|
||||||
[![Go Reference](https://pkg.go.dev/badge/github.com/wneessen/go-hibp.svg)](https://pkg.go.dev/github.com/wneessen/go-hibp)
|
[![GoDoc](https://godoc.org/github.com/wneessen/go-hibp?status.svg)](https://pkg.go.dev/github.com/wneessen/go-hibp)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/wneessen/go-hibp)](https://goreportcard.com/report/github.com/wneessen/go-hibp)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/wneessen/go-hibp)](https://goreportcard.com/report/github.com/wneessen/go-hibp)
|
||||||
[![Build Status](https://api.cirrus-ci.com/github/wneessen/go-hibp.svg)](https://cirrus-ci.com/github/wneessen/go-hibp)
|
[![Build Status](https://api.cirrus-ci.com/github/wneessen/go-hibp.svg)](https://cirrus-ci.com/github/wneessen/go-hibp)
|
||||||
[![codecov](https://codecov.io/gh/wneessen/go-hibp/branch/main/graph/badge.svg?token=ST96EC0JHU)](https://codecov.io/gh/wneessen/go-hibp)
|
[![codecov](https://codecov.io/gh/wneessen/go-hibp/branch/main/graph/badge.svg?token=ST96EC0JHU)](https://codecov.io/gh/wneessen/go-hibp)
|
||||||
<a href="https://ko-fi.com/D1D24V9IX"><img src="https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/5cbed8a4ae2b88347c06c923_BuyMeACoffee_blue.png" height="20" alt="buy ma a coffee"></a>
|
<a href="https://ko-fi.com/D1D24V9IX"><img src="https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/5cbed8a4ae2b88347c06c923_BuyMeACoffee_blue.png" height="20" alt="buy ma a coffee"></a>
|
||||||
|
|
||||||
This Go package provides an simple to use interface to the excellent
|
This Go library provides simple bindings to the excellent
|
||||||
"[Have I Been Pwned](https://haveibeenpwned.com/API/v3)" (HIBP) API by Troy Hunt.
|
"[Have I Been Pwned](https://haveibeenpwned.com/API/v3)" (HIBP) API by Troy Hunt. It implements all 3 APIs
|
||||||
|
that are provided by HIBP (Breaches, Pastes, Passwords). API key support for the private API endpoints are
|
||||||
|
supported as well. go-hibp follows idiomatic Go style and best practice. It's only dependency is the Go Standard
|
||||||
|
Library.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
Check out the [GoDocs Reference](https://pkg.go.dev/github.com/wneessen/go-hibp) for details on how to implement
|
The library is fully documented using the execellent GoDoc functionality. Check out the
|
||||||
access to the HIBP API with this package. You will also find GoDoc code examples there.
|
[GoDocs Reference](https://pkg.go.dev/github.com/wneessen/go-hibp) for details on how to implement
|
||||||
|
access to any of the 3 APIs with this package. You will also find GoDoc code examples there for each of those
|
||||||
|
APIs.
|
||||||
|
|
2
hibp.go
2
hibp.go
|
@ -1,4 +1,4 @@
|
||||||
// Package hibp provides Go binding to all 3 APIs of the "Have I been Pwned" by Troy Hunt
|
// Package hibp provides Go binding to all 3 APIs of the "Have I Been Pwned" by Troy Hunt
|
||||||
package hibp
|
package hibp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -52,6 +52,9 @@ func (p *PwnedPassApi) CheckSHA1(h string) (*Match, *http.Response, error) {
|
||||||
// apiCall performs the API call to the Pwned Password API endpoint and returns
|
// apiCall performs the API call to the Pwned Password API endpoint and returns
|
||||||
// the http.Response
|
// the http.Response
|
||||||
func (p *PwnedPassApi) apiCall(h string) ([]Match, *http.Response, error) {
|
func (p *PwnedPassApi) apiCall(h string) ([]Match, *http.Response, error) {
|
||||||
|
if len(h) < 5 {
|
||||||
|
return nil, nil, fmt.Errorf("password hash cannot be shorter than 5 characters")
|
||||||
|
}
|
||||||
sh := h[:5]
|
sh := h[:5]
|
||||||
hreq, err := p.hibp.HttpReq(http.MethodGet, fmt.Sprintf("https://api.pwnedpasswords.com/range/%s", sh),
|
hreq, err := p.hibp.HttpReq(http.MethodGet, fmt.Sprintf("https://api.pwnedpasswords.com/range/%s", sh),
|
||||||
nil)
|
nil)
|
||||||
|
|
|
@ -37,20 +37,23 @@ func TestPwnedPasswordString(t *testing.T) {
|
||||||
// TestPwnedPasswordHash verifies the Pwned Passwords API with the CheckSHA1 method
|
// TestPwnedPasswordHash verifies the Pwned Passwords API with the CheckSHA1 method
|
||||||
func TestPwnedPasswordHash(t *testing.T) {
|
func TestPwnedPasswordHash(t *testing.T) {
|
||||||
testTable := []struct {
|
testTable := []struct {
|
||||||
testName string
|
testName string
|
||||||
pwHash string
|
pwHash string
|
||||||
isLeaked bool
|
isLeaked bool
|
||||||
|
shouldFail bool
|
||||||
}{
|
}{
|
||||||
{"weak password 'test123' is expected to be leaked",
|
{"weak password 'test123' is expected to be leaked",
|
||||||
"7288edd0fc3ffcbe93a0cf06e3568e28521687bc", true},
|
"7288edd0fc3ffcbe93a0cf06e3568e28521687bc", true, false},
|
||||||
{"strong, unknown password is expected to be not leaked",
|
{"strong, unknown password is expected to be not leaked",
|
||||||
"90efc095c82eab44e882fda507cfab1a2cd31fc0", false},
|
"90efc095c82eab44e882fda507cfab1a2cd31fc0", false, false},
|
||||||
|
{"empty string should fail",
|
||||||
|
"", false, true},
|
||||||
}
|
}
|
||||||
hc := New()
|
hc := New()
|
||||||
for _, tc := range testTable {
|
for _, tc := range testTable {
|
||||||
t.Run(tc.testName, func(t *testing.T) {
|
t.Run(tc.testName, func(t *testing.T) {
|
||||||
m, _, err := hc.PwnedPassApi.CheckSHA1(tc.pwHash)
|
m, _, err := hc.PwnedPassApi.CheckSHA1(tc.pwHash)
|
||||||
if err != nil {
|
if err != nil && !tc.shouldFail {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -65,6 +68,24 @@ func TestPwnedPasswordHash(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestPwnedPassApi_apiCall tests the non-public apiCall method (especially for failures that are not
|
||||||
|
// tested by the other tests already)
|
||||||
|
func TestPwnedPassApi_apiCall(t *testing.T) {
|
||||||
|
hc := New()
|
||||||
|
|
||||||
|
// Should return a 404
|
||||||
|
_, _, err := hc.PwnedPassApi.apiCall("ZZZZZZZZZZZZZZ")
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("apiCall was supposed to fail, but didn't")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non allowed characters
|
||||||
|
_, _, err = hc.PwnedPassApi.apiCall(string([]byte{0}))
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("apiCall was supposed to fail, but didn't")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ExamplePwnedPassApi_CheckPassword is a code example to show how to check a given password
|
// ExamplePwnedPassApi_CheckPassword is a code example to show how to check a given password
|
||||||
// against the HIBP passwords API
|
// against the HIBP passwords API
|
||||||
func ExamplePwnedPassApi_CheckPassword() {
|
func ExamplePwnedPassApi_CheckPassword() {
|
||||||
|
|
Loading…
Reference in a new issue