]> Cypherpunks.ru repositories - govpn.git/blobdiff - src/cypherpunks.ru/govpn/verifier.go
fix password read on windows, `0` isn't Stdin on windows
[govpn.git] / src / cypherpunks.ru / govpn / verifier.go
index a452a50a84737231a2e0e3d28701dee10138bf23..d5976ec8529aa059222219e809055bb8c2018153 100644 (file)
@@ -1,6 +1,6 @@
 /*
 GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
 
 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
@@ -23,43 +23,55 @@ import (
        "encoding/base64"
        "errors"
        "fmt"
+       "hash"
        "io/ioutil"
        "log"
        "os"
        "strings"
+       "syscall"
 
+       "cypherpunks.ru/balloon"
        "github.com/agl/ed25519"
-       "github.com/magical/argon2"
+       "golang.org/x/crypto/blake2b"
        "golang.org/x/crypto/ssh/terminal"
 )
 
 const (
-       DefaultM = 1 << 12
-       DefaultT = 1 << 7
-       DefaultP = 1
+       // DefaultS is default Balloon space cost
+       DefaultS = 1 << 20 / 32
+       // DefaultT is default Balloon time cost
+       DefaultT = 1 << 4
+       // DefaultP is default Balloon number of jobs
+       DefaultP = 2
 )
 
+// Verifier is used to authenticate a peer
 type Verifier struct {
-       M   int
+       S   int
        T   int
        P   int
-       Id  *PeerId
+       ID  *PeerID
        Pub *[ed25519.PublicKeySize]byte
 }
 
-// Generate new verifier for given peer, with specified password and
-// hashing parameters.
-func VerifierNew(m, t, p int, id *PeerId) *Verifier {
-       return &Verifier{M: m, T: t, P: p, Id: id}
+// VerifierNew generates new verifier for given peer,
+// with specified password and hashing parameters.
+func VerifierNew(s, t, p int, id *PeerID) *Verifier {
+       return &Verifier{S: s, T: t, P: p, ID: id}
 }
 
-// Apply the password: create Ed25519 keypair based on it, save public
-// key in verifier.
-func (v *Verifier) PasswordApply(password string) *[ed25519.PrivateKeySize]byte {
-       r, err := argon2.Key([]byte(password), v.Id[:], v.T, v.P, int64(v.M), 32)
+func blake2bKeyless() hash.Hash {
+       h, err := blake2b.New256(nil)
        if err != nil {
-               log.Fatalln("Unable to apply Argon2d", err)
+               panic(err)
        }
+       return h
+}
+
+// PasswordApply applies the password: create Ed25519 keypair based on it,
+// saves public key in verifier.
+func (v *Verifier) PasswordApply(password string) *[ed25519.PrivateKeySize]byte {
+       r := balloon.H(blake2bKeyless, []byte(password), v.ID[:], v.S, v.T, v.P)
        defer SliceZero(r)
        src := bytes.NewBuffer(r)
        pub, prv, err := ed25519.GenerateKey(src)
@@ -70,28 +82,28 @@ func (v *Verifier) PasswordApply(password string) *[ed25519.PrivateKeySize]byte
        return prv
 }
 
-// Parse either short or long verifier form.
+// VerifierFromString parses either short or long verifier form.
 func VerifierFromString(input string) (*Verifier, error) {
-       s := strings.Split(input, "$")
-       if !(len(s) != 4 || len(s) != 5) || s[1] != "argon2d" {
+       ss := strings.Split(input, "$")
+       if len(ss) < 4 || ss[1] != "balloon" {
                return nil, errors.New("Invalid verifier structure")
        }
-       var m, t, p int
-       n, err := fmt.Sscanf(s[2], "m=%d,t=%d,p=%d", &m, &t, &p)
+       var s, t, p int
+       n, err := fmt.Sscanf(ss[2], "s=%d,t=%d,p=%d", &s, &t, &p)
        if n != 3 || err != nil {
                return nil, errors.New("Invalid verifier parameters")
        }
-       salt, err := base64.RawStdEncoding.DecodeString(s[3])
+       salt, err := base64.RawStdEncoding.DecodeString(ss[3])
        if err != nil {
                return nil, err
        }
-       v := Verifier{M: m, T: t, P: p}
+       v := Verifier{S: s, T: t, P: p}
        id := new([IDSize]byte)
        copy(id[:], salt)
-       pid := PeerId(*id)
-       v.Id = &pid
-       if len(s) == 5 {
-               pub, err := base64.RawStdEncoding.DecodeString(s[4])
+       pid := PeerID(*id)
+       v.ID = &pid
+       if len(ss) == 5 {
+               pub, err := base64.RawStdEncoding.DecodeString(ss[4])
                if err != nil {
                        return nil, err
                }
@@ -101,17 +113,17 @@ func VerifierFromString(input string) (*Verifier, error) {
        return &v, nil
 }
 
-// Short verifier string form -- it is useful for the client.
-// Does not include public key.
+// ShortForm outputs the short verifier string form -- it is useful
+// for the client. It does not include public key.
 func (v *Verifier) ShortForm() string {
        return fmt.Sprintf(
-               "$argon2d$m=%d,t=%d,p=%d$%s",
-               v.M, v.T, v.P, base64.RawStdEncoding.EncodeToString(v.Id[:]),
+               "$balloon$s=%d,t=%d,p=%d$%s",
+               v.S, v.T, v.P, base64.RawStdEncoding.EncodeToString(v.ID[:]),
        )
 }
 
-// Long verifier string form -- it is useful for the server.
-// Includes public key.
+// LongForm outputs long verifier string form -- it is useful for the server.
+// It includes public key.
 func (v *Verifier) LongForm() string {
        return fmt.Sprintf(
                "%s$%s", v.ShortForm(),
@@ -119,7 +131,7 @@ func (v *Verifier) LongForm() string {
        )
 }
 
-// Read the key either from text file (if path is specified), or
+// KeyRead reads the key either from text file (if path is specified), or
 // from the terminal.
 func KeyRead(path string) (string, error) {
        var p []byte
@@ -127,7 +139,7 @@ func KeyRead(path string) (string, error) {
        var pass string
        if path == "" {
                os.Stderr.Write([]byte("Passphrase:"))
-               p, err = terminal.ReadPassword(0)
+               p, err = terminal.ReadPassword(int(uintptr(syscall.Stdin)))
                os.Stderr.Write([]byte("\n"))
                pass = string(p)
        } else {