From 53e653cb5f08eca372ec8158d2bc56feead1484b Mon Sep 17 00:00:00 2001 From: Andy Royle Date: Mon, 19 Nov 2018 13:05:15 +0000 Subject: [PATCH] vendoring in version 0849cea of github.com/tg123/go-htpasswd --- go.mod | 1 + go.sum | 2 + .../github.com/tg123/go-htpasswd/.gitignore | 24 +++ vendor/github.com/tg123/go-htpasswd/LICENSE | 22 +++ vendor/github.com/tg123/go-htpasswd/README.md | 17 ++ vendor/github.com/tg123/go-htpasswd/bcrypt.go | 37 ++++ .../github.com/tg123/go-htpasswd/htpasswd.go | 173 ++++++++++++++++++ vendor/github.com/tg123/go-htpasswd/md5.go | 156 ++++++++++++++++ vendor/github.com/tg123/go-htpasswd/plain.go | 28 +++ vendor/github.com/tg123/go-htpasswd/sha.go | 43 +++++ vendor/github.com/tg123/go-htpasswd/ssha.go | 51 ++++++ vendor/github.com/tg123/go-htpasswd/util.go | 18 ++ vendor/modules.txt | 4 +- 13 files changed, 575 insertions(+), 1 deletion(-) create mode 100644 vendor/github.com/tg123/go-htpasswd/.gitignore create mode 100644 vendor/github.com/tg123/go-htpasswd/LICENSE create mode 100644 vendor/github.com/tg123/go-htpasswd/README.md create mode 100644 vendor/github.com/tg123/go-htpasswd/bcrypt.go create mode 100644 vendor/github.com/tg123/go-htpasswd/htpasswd.go create mode 100644 vendor/github.com/tg123/go-htpasswd/md5.go create mode 100644 vendor/github.com/tg123/go-htpasswd/plain.go create mode 100644 vendor/github.com/tg123/go-htpasswd/sha.go create mode 100644 vendor/github.com/tg123/go-htpasswd/ssha.go create mode 100644 vendor/github.com/tg123/go-htpasswd/util.go diff --git a/go.mod b/go.mod index 0e93f4614..ff64fadfd 100644 --- a/go.mod +++ b/go.mod @@ -85,6 +85,7 @@ require ( github.com/sergi/go-diff v0.0.0-20170118131230-24e2351369ec github.com/sirupsen/logrus v1.2.0 // indirect github.com/soheilhy/cmux v0.1.4 // indirect + github.com/tg123/go-htpasswd v0.0.0-20181019180120-0849ceac46bc // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 // indirect github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f // indirect diff --git a/go.sum b/go.sum index ef6f68f05..d06af826a 100644 --- a/go.sum +++ b/go.sum @@ -222,6 +222,8 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/tg123/go-htpasswd v0.0.0-20181019180120-0849ceac46bc h1:xex1qjYrr0ez7t6pWHwYJrdKrJYzsvPQfoHG87u7FTs= +github.com/tg123/go-htpasswd v0.0.0-20181019180120-0849ceac46bc/go.mod h1:rFFqmvZbM9kVmDDVpeVr8VJ+8nRWwuXR/uvvjJ/3aJo= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 h1:lYIiVDtZnyTWlNwiAxLj0bbpTcx1BWCFhXjfsvmPdNc= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= diff --git a/vendor/github.com/tg123/go-htpasswd/.gitignore b/vendor/github.com/tg123/go-htpasswd/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/tg123/go-htpasswd/LICENSE b/vendor/github.com/tg123/go-htpasswd/LICENSE new file mode 100644 index 000000000..279ed63ca --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 tgic + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/tg123/go-htpasswd/README.md b/vendor/github.com/tg123/go-htpasswd/README.md new file mode 100644 index 000000000..de297a97d --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/README.md @@ -0,0 +1,17 @@ +# htpasswd for Go + +This is a libary to validate user credentials against an HTTPasswd file. + +This was forked from +with modifications by @brian-avery to support SSHA, Md5Crypt, and Bcrypt. + +## Currently, this supports: +* SSHA +* MD5Crypt +* APR1Crypt +* SHA +* Bcrypt +* Plain text + +## Not supported: +* Crypt diff --git a/vendor/github.com/tg123/go-htpasswd/bcrypt.go b/vendor/github.com/tg123/go-htpasswd/bcrypt.go new file mode 100644 index 000000000..fd4c40e5e --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/bcrypt.go @@ -0,0 +1,37 @@ +package htpasswd + +import ( + "fmt" + "strings" + + "golang.org/x/crypto/bcrypt" +) + +type bcryptPassword struct { + hashed []byte +} + +//AcceptBcrypt accepts any valid password encoded using bcrypt. +func AcceptBcrypt(src string) (EncodedPasswd, error) { + if !strings.HasPrefix(src, "$2y$") && !strings.HasPrefix(src, "$2a$") { + return nil, nil + } + + return &bcryptPassword{hashed: []byte(src)}, nil +} + +//RejectBcrypt rejects any password encoded using bcrypt. +func RejectBcrypt(src string) (EncodedPasswd, error) { + if strings.HasPrefix(src, "$2y$") || strings.HasPrefix(src, "$2a$") { + return nil, fmt.Errorf("bcrypt passwords are not accepted: %s", src) + } + + return nil, nil +} + +func (b *bcryptPassword) MatchesPassword(password string) bool { + if err := bcrypt.CompareHashAndPassword(b.hashed, []byte(password)); err != nil { + return false + } + return true +} diff --git a/vendor/github.com/tg123/go-htpasswd/htpasswd.go b/vendor/github.com/tg123/go-htpasswd/htpasswd.go new file mode 100644 index 000000000..52149725b --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/htpasswd.go @@ -0,0 +1,173 @@ +// Package htpasswd provides HTTP Basic Authentication using Apache-style htpasswd files +// for the user and password data. +// +// It supports most common hashing systems used over the decades and can be easily extended +// by the programmer to support others. (See the sha.go source file as a guide.) +// +// You will want to use something like... +// myauth := htpasswd.New("My Realm", "./my-htpasswd-file", htpasswd.DefaultSystems, nil) +// m.Use(myauth.Handler) +// ...to configure your authentication and then use the myauth.Handler as a middleware handler in your Martini stack. +// You should read about that nil, as well as Reread() too. +package htpasswd + +import ( + "bufio" + "fmt" + "os" + "strings" + "sync" +) + +// An EncodedPasswd is created from the encoded password in a password file by a PasswdParser. +// +// The password files consist of lines like "user:passwd-encoding". The user part is stripped off and +// the passwd-encoding part is captured in an EncodedPasswd. +type EncodedPasswd interface { + // Return true if the string matches the password. + // This may cache the result in the case of expensive comparison functions. + MatchesPassword(pw string) bool +} + +// PasswdParser examines an encoded password, and if it is formatted correctly and sane, return an +// EncodedPasswd which will recognize it. +// +// If the format is not understood, then return nil +// so that another parser may have a chance. If the format is understood but not sane, +// return an error to prevent other formats from possibly claiming it +// +// You may write and supply one of these functions to support a format (e.g. bcrypt) not +// already included in this package. Use sha.c as a template, it is simple but not too simple. +type PasswdParser func(pw string) (EncodedPasswd, error) + +type passwdTable map[string]EncodedPasswd + +// A BadLineHandler is used to notice bad lines in a password file. If not nil, it will be +// called for each bad line with a descriptive error. Think about what you do with these, they +// will sometimes contain hashed passwords. +type BadLineHandler func(err error) + +// An HtpasswdFile encompasses an Apache-style htpasswd file for HTTP Basic authentication +type HtpasswdFile struct { + filePath string + mutex sync.Mutex + passwds passwdTable + parsers []PasswdParser +} + +// DefaultSystems is an array of PasswdParser including all builtin parsers. Notice that Plain is last, since it accepts anything +var DefaultSystems = []PasswdParser{AcceptMd5, AcceptSha, AcceptBcrypt, AcceptSsha, AcceptPlain} + +// New creates an HtpasswdFile from an Apache-style htpasswd file for HTTP Basic Authentication. +// +// The realm is presented to the user in the login dialog. +// +// The filename must exist and be accessible to the process, as well as being a valid htpasswd file. +// +// parsers is a list of functions to handle various hashing systems. In practice you will probably +// just pass htpasswd.DefaultSystems, but you could make your own to explicitly reject some formats or +// implement your own. +// +// bad is a function, which if not nil will be called for each malformed or rejected entry in +// the password file. +func New(filename string, parsers []PasswdParser, bad BadLineHandler) (*HtpasswdFile, error) { + bf := HtpasswdFile{ + filePath: filename, + parsers: parsers, + } + + if err := bf.Reload(bad); err != nil { + return nil, err + } + + return &bf, nil +} + +// Match checks the username and password combination to see if it represents +// a valid account from the htpassword file. +func (bf *HtpasswdFile) Match(username, password string) bool { + bf.mutex.Lock() + matcher, ok := bf.passwds[username] + bf.mutex.Unlock() + + if ok && matcher.MatchesPassword(password) { + // we are good + return true + } + + return false +} + +// Reload rereads the htpassword file.. +// You will need to call this to notice any changes to the password file. +// This function is thread safe. Someone versed in fsnotify might make it +// happen automatically. Likewise you might also connect a SIGHUP handler to +// this function. +func (bf *HtpasswdFile) Reload(bad BadLineHandler) error { + // with the file... + f, err := os.Open(bf.filePath) + if err != nil { + return err + } + defer f.Close() + + // ... and a new map ... + newPasswdMap := passwdTable{} + + // ... for each line ... + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + + // ... add it to the map, noting errors along the way + if perr := bf.addHtpasswdUser(&newPasswdMap, line); perr != nil && bad != nil { + bad(perr) + } + } + if err := scanner.Err(); err != nil { + return fmt.Errorf("Error scanning htpasswd file: %s", err.Error()) + } + + // .. finally, safely swap in the new map + bf.mutex.Lock() + bf.passwds = newPasswdMap + bf.mutex.Unlock() + + return nil +} + +// addHtpasswdUser processes a line from an htpasswd file and add it to the user/password map. We may +// encounter some malformed lines, this will not be an error, but we will log them if +// the caller has given us a logger. +func (bf *HtpasswdFile) addHtpasswdUser(pwmap *passwdTable, rawLine string) error { + // ignore white space lines + line := strings.TrimSpace(rawLine) + if line == "" { + return nil + } + + // split "user:encoding" at colon + parts := strings.SplitN(line, ":", 2) + if len(parts) != 2 { + return fmt.Errorf("malformed line, no colon: %s", line) + } + + user := parts[0] + encoding := parts[1] + + // give each parser a shot. The first one to produce a matcher wins. + // If one produces an error then stop (to prevent Plain from catching it) + for _, p := range bf.parsers { + matcher, err := p(encoding) + if err != nil { + return err + } + if matcher != nil { + (*pwmap)[user] = matcher + return nil // we are done, we took to first match + } + } + + // No one liked this line + return fmt.Errorf("unable to recognize password for %s in %s", user, encoding) +} diff --git a/vendor/github.com/tg123/go-htpasswd/md5.go b/vendor/github.com/tg123/go-htpasswd/md5.go new file mode 100644 index 000000000..5df809bfe --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/md5.go @@ -0,0 +1,156 @@ +package htpasswd + +import ( + "bytes" + "crypto/md5" + "fmt" + "strings" +) + +type md5Password struct { + salt string + hashed string + prefix string +} + +//PrefixCryptMd5 is the Md5crypt hash prefix +const PrefixCryptMd5 = "$1$" + +//PrefixCryptApr1 is the Apache Apr1 hash prefix +const PrefixCryptApr1 = "$apr1$" + +// AcceptMd5 accepts valid MD5 encoded passwords +func AcceptMd5(src string) (EncodedPasswd, error) { + if !strings.HasPrefix(src, PrefixCryptApr1) && !strings.HasPrefix(src, PrefixCryptMd5) { + return nil, nil + } + + prefix := PrefixCryptApr1 + if strings.HasPrefix(src, PrefixCryptMd5) { + prefix = PrefixCryptMd5 + } + rest := strings.TrimPrefix(src, prefix) + mparts := strings.SplitN(rest, "$", 2) + if len(mparts) != 2 { + return nil, fmt.Errorf("malformed md5 password: %s", src) + } + + salt, hashed := mparts[0], mparts[1] + return &md5Password{salt, hashed, prefix}, nil +} + +// RejectMd5 rejects any MD5 encoded password +func RejectMd5(src string) (EncodedPasswd, error) { + if !strings.HasPrefix(src, PrefixCryptApr1) && !strings.HasPrefix(src, PrefixCryptMd5) { + return nil, nil + } + return nil, fmt.Errorf("md5 password rejected: %s", src) +} + +// This is the MD5 hashing function out of Apache's htpasswd program. The algorithm +// is insane, but we have to match it. Mercifully I found a PHP variant of it at +// http://stackoverflow.com/questions/2994637/how-to-edit-htpasswd-using-php +// in an answer. That reads better than the original C, and is easy to instrument. +// We will eventually go back to the original apr_md5.c for inspiration when the +// PHP gets too weird. +// The algorithm makes more sense if you imagine the original authors in a pub, +// drinking beer and rolling dice as the fundamental design process. +// Note that this is the same algorithm used in md5Crypt except for the prefix in md5Crypt is $1$ +// while in apr1 it's $apr1$ +func md5Crypt(password string, salt string, prefix string) string { + + // start with a hash of password and salt + initBin := md5.Sum([]byte(password + salt + password)) + + // begin an initial string with hash and salt + initText := bytes.NewBufferString(password + prefix + salt) + + // add crap to the string willy-nilly + for i := len(password); i > 0; i -= 16 { + lim := i + if lim > 16 { + lim = 16 + } + initText.Write(initBin[0:lim]) + } + + // add more crap to the string willy-nilly + for i := len(password); i > 0; i >>= 1 { + if (i & 1) == 1 { + initText.WriteByte(byte(0)) + } else { + initText.WriteByte(password[0]) + } + } + + // Begin our hashing in earnest using our initial string + bin := md5.Sum(initText.Bytes()) + + n := bytes.NewBuffer([]byte{}) + + for i := 0; i < 1000; i++ { + // prepare to make a new muddle + n.Reset() + + // alternate password+crap+bin with bin+crap+password + if (i & 1) == 1 { + n.WriteString(password) + } else { + n.Write(bin[:]) + } + + // usually add the salt, but not always + if i%3 != 0 { + n.WriteString(salt) + } + + // usually add the password but not always + if i%7 != 0 { + n.WriteString(password) + } + + // the back half of that alternation + if (i & 1) == 1 { + n.Write(bin[:]) + } else { + n.WriteString(password) + } + + // replace bin with the md5 of this muddle + bin = md5.Sum(n.Bytes()) + } + + // At this point we stop transliterating the PHP code and flip back to + // reading the Apache source. The PHP uses their base64 library, but that + // uses the wrong character set so needs to be repaired afterwards and reversed + // and it is just really weird to read. + + result := bytes.NewBuffer([]byte{}) + + // This is our own little similar-to-base64-but-not-quite filler + fill := func(a byte, b byte, c byte) { + v := (uint(a) << 16) + (uint(b) << 8) + uint(c) // take our 24 input bits + + for i := 0; i < 4; i++ { // and pump out a character for each 6 bits + result.WriteByte("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[v&0x3f]) + v >>= 6 + } + } + + // The order of these indices is strange, be careful + fill(bin[0], bin[6], bin[12]) + fill(bin[1], bin[7], bin[13]) + fill(bin[2], bin[8], bin[14]) + fill(bin[3], bin[9], bin[15]) + fill(bin[4], bin[10], bin[5]) // 5? Yes. + fill(0, 0, bin[11]) + + resultString := string(result.Bytes()[0:22]) // we wrote two extras since we only need 22. + + return resultString +} + +func (m *md5Password) MatchesPassword(pw string) bool { + hashed := md5Crypt(pw, m.salt, m.prefix) + return constantTimeEquals(hashed, m.hashed) +} diff --git a/vendor/github.com/tg123/go-htpasswd/plain.go b/vendor/github.com/tg123/go-htpasswd/plain.go new file mode 100644 index 000000000..512e9745e --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/plain.go @@ -0,0 +1,28 @@ +package htpasswd + +import ( + "fmt" +) + +type plainPassword struct { + password string +} + +// AcceptPlain accepts any password in the plain text encoding. +// Be careful: This matches any line, so it *must* be the last parser in you list. +func AcceptPlain(pw string) (EncodedPasswd, error) { + return &plainPassword{pw}, nil +} + +// RejectPlain rejects any plain text encoded password. +// Be careful: This matches any line, so it *must* be the last parser in you list. +func RejectPlain(pw string) (EncodedPasswd, error) { + return nil, fmt.Errorf("plain password rejected: %s", pw) +} + +func (p *plainPassword) MatchesPassword(pw string) bool { + // Notice: nginx prefixes plain passwords with {PLAIN}, so we see if that would + // let us match too. I'd split {PLAIN} off, but someone probably uses that + // in their password. It's a big planet. + return constantTimeEquals(pw, p.password) || constantTimeEquals("{PLAIN}"+pw, p.password) +} diff --git a/vendor/github.com/tg123/go-htpasswd/sha.go b/vendor/github.com/tg123/go-htpasswd/sha.go new file mode 100644 index 000000000..19018aa50 --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/sha.go @@ -0,0 +1,43 @@ +package htpasswd + +import ( + "crypto/sha1" + "crypto/subtle" + "encoding/base64" + "fmt" + "strings" +) + +type shaPassword struct { + hashed []byte +} + +// AcceptSha accepts valid SHA encoded passwords. +func AcceptSha(src string) (EncodedPasswd, error) { + if !strings.HasPrefix(src, "{SHA}") { + return nil, nil + } + + b64 := strings.TrimPrefix(src, "{SHA}") + hashed, err := base64.StdEncoding.DecodeString(b64) + if err != nil { + return nil, fmt.Errorf("Malformed sha1(%s): %s", src, err.Error()) + } + if len(hashed) != sha1.Size { + return nil, fmt.Errorf("Malformed sha1(%s): wrong length", src) + } + return &shaPassword{hashed}, nil +} + +// RejectSha rejects any password encoded as SHA. +func RejectSha(src string) (EncodedPasswd, error) { + if !strings.HasPrefix(src, "{SHA}") { + return nil, nil + } + return nil, fmt.Errorf("sha password rejected: %s", src) +} + +func (s *shaPassword) MatchesPassword(pw string) bool { + h := sha1.Sum([]byte(pw)) + return subtle.ConstantTimeCompare(h[:], s.hashed) == 1 +} diff --git a/vendor/github.com/tg123/go-htpasswd/ssha.go b/vendor/github.com/tg123/go-htpasswd/ssha.go new file mode 100644 index 000000000..3ab126dd1 --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/ssha.go @@ -0,0 +1,51 @@ +package htpasswd + +import ( + "crypto/sha1" + "crypto/subtle" + "encoding/base64" + "fmt" + "strings" +) + +type sshaPassword struct { + hashed []byte + salt []byte +} + +//AcceptSsha accepts any valid password encoded using bcrypt. +func AcceptSsha(src string) (EncodedPasswd, error) { + if !strings.HasPrefix(src, "{SSHA}") { + return nil, nil + } + + b64 := strings.TrimPrefix(src, "{SSHA}") + hashed, err := base64.StdEncoding.DecodeString(b64) + if err != nil { + return nil, fmt.Errorf("Malformed ssha(%s): %s", src, err.Error()) + } + + //ssha appends the length onto the end of the SHA, so the length can't be less than sha1.Size. + if len(hashed) < sha1.Size { + return nil, fmt.Errorf("Malformed ssha(%s): wrong length", src) + } + + hash := hashed[:sha1.Size] + salt := hashed[sha1.Size:] + return &sshaPassword{hash, salt}, nil +} + +//RejectSsha rejects any password encoded using SSHA1. +func RejectSsha(src string) (EncodedPasswd, error) { + if !strings.HasPrefix(src, "{SSHA}") { + return nil, nil + } + return nil, fmt.Errorf("ssha passwords are not accepted: %s", src) +} + +func (s *sshaPassword) MatchesPassword(password string) bool { + //SSHA appends the salt onto the password before computing the hash. + sha := append([]byte(password), s.salt[:]...) + hash := sha1.Sum(sha) + return subtle.ConstantTimeCompare(hash[:], s.hashed) == 1 +} diff --git a/vendor/github.com/tg123/go-htpasswd/util.go b/vendor/github.com/tg123/go-htpasswd/util.go new file mode 100644 index 000000000..b5b03d8e0 --- /dev/null +++ b/vendor/github.com/tg123/go-htpasswd/util.go @@ -0,0 +1,18 @@ +package htpasswd + +import ( + "crypto/sha1" + "crypto/subtle" +) + +func constantTimeEquals(a string, b string) bool { + // compare SHA-1 as a gatekeeper in constant time + // then check that we didn't get by because of a collision + aSha := sha1.Sum([]byte(a)) + bSha := sha1.Sum([]byte(b)) + if subtle.ConstantTimeCompare(aSha[:], bSha[:]) == 1 { + // yes, this bit isn't constant, but you had to make a Sha1 collision to get here + return a == b + } + return false +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 391a13a3d..08a367464 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -126,6 +126,8 @@ golang.org/x/net/idna golang.org/x/sync/singleflight # golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b golang.org/x/sys/unix +# github.com/tg123/go-htpasswd v0.0.0-20181019180120-0849ceac46bc +github.com/tg123/go-htpasswd # golang.org/x/text v0.3.0 golang.org/x/text/secure/bidirule golang.org/x/text/unicode/bidi @@ -159,4 +161,4 @@ google.golang.org/grpc/resolver google.golang.org/grpc/resolver/dns google.golang.org/grpc/resolver/passthrough google.golang.org/grpc/tap -google.golang.org/grpc/balancer/base +google.golang.org/grpc/balancer/base \ No newline at end of file