X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=src%2Fcypherpunks.ru%2Fgovpn%2Fverifier.go;h=00ba6322eae8d640ccde58860a503631a8d30596;hb=5a55ad42b9b740659e8e89963403c27f7704e50a;hp=d5976ec8529aa059222219e809055bb8c2018153;hpb=efaad3bf853603c25ae70a5779cce355d1c21016;p=govpn.git diff --git a/src/cypherpunks.ru/govpn/verifier.go b/src/cypherpunks.ru/govpn/verifier.go index d5976ec..00ba632 100644 --- a/src/cypherpunks.ru/govpn/verifier.go +++ b/src/cypherpunks.ru/govpn/verifier.go @@ -21,28 +21,30 @@ package govpn import ( "bytes" "encoding/base64" - "errors" "fmt" "hash" "io/ioutil" - "log" "os" "strings" "syscall" - "cypherpunks.ru/balloon" "github.com/agl/ed25519" + "github.com/pkg/errors" "golang.org/x/crypto/blake2b" "golang.org/x/crypto/ssh/terminal" + + "cypherpunks.ru/balloon" ) const ( - // DefaultS is default Balloon space cost + // DefaultS default Balloon space cost DefaultS = 1 << 20 / 32 - // DefaultT is default Balloon time cost + // DefaultT default Balloon time cost DefaultT = 1 << 4 - // DefaultP is default Balloon number of jobs + // DefaultP default Balloon number of job DefaultP = 2 + + wrapDecodeString = "base64.RawStdEncoding.DecodeString" ) // Verifier is used to authenticate a peer @@ -60,26 +62,30 @@ func VerifierNew(s, t, p int, id *PeerID) *Verifier { return &Verifier{S: s, T: t, P: p, ID: id} } -func blake2bKeyless() hash.Hash { - h, err := blake2b.New256(nil) +// PasswordApply applies the password: create Ed25519 keypair based on it, +// saves public key in verifier. +func (v *Verifier) PasswordApply(password string) (*[ed25519.PrivateKeySize]byte, error) { + // TODO: there is an extremely weird bug, `balloon.H` panic if I the `hash.Hash` + // outside the `hasher` function. + var err error + hasher := func() hash.Hash { + var nilHash hash.Hash + nilHash, err = blake2b.New256(nil) + return nilHash + } + r := balloon.H(hasher, []byte(password), v.ID[:], v.S, v.T, v.P) if err != nil { - panic(err) + return nil, errors.Wrap(err, wrapBlake2bNew256) } - 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) if err != nil { - log.Fatalln("Unable to generate Ed25519 keypair", err) + return nil, errors.Wrap(err, "ed25519.GenerateKey") } v.Pub = pub - return prv + return prv, nil } // VerifierFromString parses either short or long verifier form. @@ -90,12 +96,15 @@ func VerifierFromString(input string) (*Verifier, error) { } 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 { + if err != nil { + return nil, errors.Wrap(err, "fmt.Sscanf") + } + if n != 3 { return nil, errors.New("Invalid verifier parameters") } salt, err := base64.RawStdEncoding.DecodeString(ss[3]) if err != nil { - return nil, err + return nil, errors.Wrap(err, wrapDecodeString) } v := Verifier{S: s, T: t, P: p} id := new([IDSize]byte) @@ -105,7 +114,7 @@ func VerifierFromString(input string) (*Verifier, error) { if len(ss) == 5 { pub, err := base64.RawStdEncoding.DecodeString(ss[4]) if err != nil { - return nil, err + return nil, errors.Wrap(err, wrapDecodeString) } v.Pub = new([ed25519.PublicKeySize]byte) copy(v.Pub[:], pub) @@ -134,23 +143,33 @@ func (v *Verifier) LongForm() string { // KeyRead reads the key either from text file (if path is specified), or // from the terminal. func KeyRead(path string) (string, error) { + const ( + emptyString = "" + wrapOsStderrWrite = "os.Stderr.Write" + ) var p []byte var err error var pass string - if path == "" { - os.Stderr.Write([]byte("Passphrase:")) + if path == emptyString { + if _, err = os.Stderr.Write([]byte("Passphrase:")); err != nil { + return emptyString, errors.Wrap(err, wrapOsStderrWrite) + } p, err = terminal.ReadPassword(int(uintptr(syscall.Stdin))) - os.Stderr.Write([]byte("\n")) + if err != nil { + return emptyString, errors.Wrap(err, "terminal.ReadPassword") + } + if _, err = os.Stderr.Write([]byte("\n")); err != nil { + return emptyString, errors.Wrap(err, wrapOsStderrWrite) + } pass = string(p) } else { - p, err = ioutil.ReadFile(path) + if p, err = ioutil.ReadFile(path); err != nil { + return emptyString, errors.Wrap(err, "ioutil.ReadFile") + } pass = strings.TrimRight(string(p), "\n") } - if err != nil { - return "", err - } if len(pass) == 0 { - return "", errors.New("Empty passphrase submitted") + return emptyString, errors.New("Empty passphrase submitted") } - return pass, err + return pass, nil }