sophuwu.site > goauth
idk
sophuwu sophie@skisiel.com
Tue, 14 May 2024 22:36:56 +0200
commit

7333a03c899a50cdcd378ed4db74b1f2f153f5f8

7 files changed, 191 insertions(+), 0 deletions(-)

jump to
A .gitignore

@@ -0,0 +1,2 @@

+.idea +build/
A go.mod

@@ -0,0 +1,7 @@

+module sophuwu.site/goauth + +go 1.22.3 + +require github.com/pquerna/otp v1.4.0 + +require github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
A go.sum

@@ -0,0 +1,11 @@

+github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= +github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= +github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
A http.go

@@ -0,0 +1,19 @@

+package goauth + +import ( + "crypto/subtle" + "net/http" +) + +func HttpAuth(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + inputUser, inputPass, authOK := r.BasicAuth() + CheckPassword(inputUser, inputPass) + if !authOK || !lookupOK || { + w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) + http.Error(w, "Unauthorized.", http.StatusUnauthorized) + return + } + next.ServeHTTP(w, r) + }) +}
A otp.go

@@ -0,0 +1,34 @@

+package goauth + +import ( + "github.com/pquerna/otp" + "github.com/pquerna/otp/totp" + + "fmt" + "os" +) + +func generate(user string) { + key, err := totp.Generate(totp.GenerateOpts{ + Issuer: "soph.local", + AccountName: user, + }) + if err != nil { + panic(err) + } + fmt.Println(key.URL()) +} + +func validate(key *otp.Key) { + // Now Validate that the user's successfully added the passcode. + fmt.Println("Validating TOTP...") + passcode := promptForPasscode() + valid := totp.Validate(passcode, key.Secret()) + if valid { + println("Valid passcode!") + os.Exit(0) + } else { + println("Invalid passcode!") + os.Exit(1) + } +}
A test/main.go

@@ -0,0 +1,57 @@

+package main + +import ( + "fmt" + "github.com/boombuler/barcode/qr" + "github.com/pquerna/otp/totp" + "image/color" + "strings" +) + +const blank = " " // U+0020 +const upper = "▀" // U+2580 +const lower = "▄" // U+2584 +const whole = "█" // U+2588 + +var block []string = []string{blank, upper, lower, whole} + +func isNotBlack(c color.Color) int { + if c != color.Black && c != color.Transparent { + return 1 + } + return 0 +} + +func qrline(s string) { + // fmt.Println("\033[97;40m" + s + "\033[0m") + fmt.Println(s) +} + +func main() { + key, err := totp.Generate(totp.GenerateOpts{AccountName: "soeiuhfiosuhfoiushgfusehfoushfuoseuhosfph", Issuer: "soph.local"}) + if err != nil { + panic(err) + } + fmt.Println(key.Secret()) + fmt.Println(key.URL()) + bar, err := qr.Encode(key.URL(), qr.L, qr.Unicode) + if err != nil { + panic(err) + } + qrline(strings.Repeat(lower, bar.Bounds().Dx()+2)) + var s string + for y := bar.Bounds().Min.Y; y < bar.Bounds().Max.Y+(bar.Bounds().Dy()%2); y += 2 { + s = whole + for x := bar.Bounds().Min.X; x < bar.Bounds().Max.X; x++ { + s += block[isNotBlack(bar.At(x, y))+2*isNotBlack(bar.At(x, y+1))] + // s += fmt.Sprintf("\033[%d;%dm%s\033[0m", 30+67*isNotBlack(bar.At(x, y)), 40+67*isNotBlack(bar.At(x, y+1)), upperblock) + } + qrline(s + whole) + } + qrline(strings.Repeat(upper, bar.Bounds().Dx()+2)) + // s, e := totp.GenerateCode("test", time.Now().UTC()) + // if e != nil { + // panic(e) + // } + // fmt.Println(s) +}
A user.go

@@ -0,0 +1,61 @@

+package goauth + +import ( + "crypto/rand" + "crypto/sha256" + "crypto/subtle" + "github.com/pquerna/otp/totp" +) + +// User struct for storing user data +type User struct { + Name string + Hash []byte + Salt []byte + OtpS string +} + +func salt() []byte { + var s = make([]byte, 32) + _, err := rand.Read(s) + if err != nil { + panic(err) + } + return s +} +func hash(b ...[]byte) []byte { + h := sha256.New() + for _, v := range b { + h.Write(v) + } + return h.Sum(nil) +} + +func (u *User) SetPass(pass string) { + u.Salt = salt() + u.Hash = hash([]byte(pass), u.Salt) +} + +func (u *User) CheckPass(pass string) bool { + return subtle.ConstantTimeCompare(u.Hash, hash([]byte(pass), u.Salt)) == 1 +} + +// NewUser creates a new user +func NewUser(name, pass string) *User { + var u User + key, err := totp.Generate(totp.GenerateOpts{AccountName: name, Issuer: "soph.local"}) + if err != nil { + panic(err) + } + key.Secret() + u.Name = name + u.SetPass(pass) + +} + +// CheckPassword checks if the password is correct +func CheckPassword(name, pass string) bool { + return false +} + +// subtle.ConstantTimeCompare([]byte(expectedPass), []byte(pass)) == 1