]> Cypherpunks.ru repositories - gocheese.git/blobdiff - argon2i.go
Add auth with argon2i and sha256 hashed passwords
[gocheese.git] / argon2i.go
diff --git a/argon2i.go b/argon2i.go
new file mode 100644 (file)
index 0000000..d83a8fc
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+GoCheese -- Python private package repository and caching proxy
+Copyright (C) 2019 Elena Balakhonova <balakhonova_e@riseup.net>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// Python private package repository and caching proxy
+package main
+
+import (
+       "bytes"
+       "encoding/base64"
+       "errors"
+       "fmt"
+       "strings"
+
+       "golang.org/x/crypto/argon2"
+)
+
+type Argon2iAuthData struct {
+       version  int
+       memory   uint32
+       time     uint32
+       threads  uint8
+       salt     []byte
+       password []byte
+}
+
+func (ad Argon2iAuthData) Auth(password string) bool {
+       hashedPassword := argon2.Key(
+               []byte(password),
+               ad.salt,
+               ad.time,
+               ad.memory,
+               ad.threads,
+               uint32(len(ad.password)),
+       )
+       return bytes.Equal(hashedPassword, ad.password)
+}
+
+func parseArgon2i(params string) (Auther, error) {
+       var time, memory uint32
+       var threads uint8
+       var version int
+       var saltAndPasswordUnitedB64 string
+       n, err := fmt.Sscanf(
+               params,
+               "v=%d$m=%d,t=%d,p=%d$%s",
+               &version,
+               &memory,
+               &time,
+               &threads,
+               &saltAndPasswordUnitedB64,
+       )
+       if n != 5 || err != nil {
+               return nil, fmt.Errorf("argon2i parameters %q have wrong format", params)
+       }
+       if version != argon2.Version {
+               return nil, errors.New("unsupported argon2i version")
+       }
+       saltAndPasswordSplittedB64 := strings.Split(saltAndPasswordUnitedB64, "$")
+       salt, err := base64.RawStdEncoding.DecodeString(saltAndPasswordSplittedB64[0])
+       if err != nil {
+               return nil, errors.New("invalid salt format")
+       }
+       password, err := base64.RawStdEncoding.DecodeString(saltAndPasswordSplittedB64[1])
+       if err != nil {
+               return nil, errors.New("invalid password format")
+       }
+       return Argon2iAuthData{
+               version:  version,
+               time:     time,
+               memory:   memory,
+               threads:  threads,
+               salt:     salt,
+               password: password,
+       }, nil
+}