]> Cypherpunks.ru repositories - govpn.git/commitdiff
Replace Argon2 with Balloon hashing
authorSergey Matveev <stargrave@stargrave.org>
Sun, 11 Sep 2016 13:12:54 +0000 (16:12 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 11 Sep 2016 13:48:16 +0000 (16:48 +0300)
* We should use Argon2i, instead of Argon2d. Current implementation was
  Argon2i and did not support d-one.
* Other Argon2i implementations on Go exists, but they implements not
  the latest Argon2 1.3 version.
* Argon2 is not so trivial to rewrite from scratch.
* Used argon2 library contained testing-library import, that added -test
  related flags to the command line.
* Argon2i has some cryptoanalysis, showing it is not so perfect as
  expected.

So all the issues above are mitigated by replacing this hashing function
with much more simpler Balloon hashing written from scratch. Simplicity
wins.

17 files changed:
.gitmodules
VERSION
doc/developer.texi
doc/example.texi
doc/installation.texi
doc/news.ru.texi
doc/news.texi
doc/server.texi
doc/sources.texi
doc/thanks.texi
doc/verifier.texi
doc/verifierstruct.texi
src/cypherpunks.ru/balloon [new submodule]
src/cypherpunks.ru/govpn/cmd/govpn-verifier/main.go
src/cypherpunks.ru/govpn/verifier.go
src/github.com/magical/argon2 [deleted submodule]
utils/makedist.sh

index 27bf6b5f55b2e0bc11f7ca0365b936886f011aba..bb2b1f83ab61d548a662c6536318abd69342dea4 100644 (file)
@@ -7,12 +7,12 @@
 [submodule "src/golang.org/x/crypto"]
        path = src/golang.org/x/crypto
        url = https://go.googlesource.com/crypto
-[submodule "src/github.com/magical/argon2"]
-       path = src/github.com/magical/argon2
-       url = https://github.com/magical/argon2.git
 [submodule "src/github.com/dchest/blake2b"]
        path = src/github.com/dchest/blake2b
        url = https://github.com/dchest/blake2b.git
 [submodule "src/github.com/go-yaml/yaml"]
        path = src/github.com/go-yaml/yaml
        url = https://github.com/go-yaml/yaml.git
+[submodule "src/cypherpunks.ru/balloon"]
+       path = src/cypherpunks.ru/balloon
+       url = git://git.cypherpunks.ru/balloon.git
diff --git a/VERSION b/VERSION
index f9ce5a96efa2084f1e5e4e342358198b7159cbec..e0ea36feef6e828ce8587989537a827d0c3c98ed 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-5.10
+6.0
index f2fe00ec5ba392b87a26ee14c99ddffab48f1606..e147f7e280a82b5294db149d9e1a08cacc1b87ca 100644 (file)
@@ -16,7 +16,8 @@ Pay attention how to get @ref{Sources, development source code}.
 @item DH elliptic-curve point encoding for public keys
     @url{http://elligator.cr.yp.to/, Elligator}.
 @item Verifier password hashing algorithm
-    @url{https://password-hashing.net/#argon2, Argon2d}.
+    @url{https://crypto.stanford.edu/balloon/, Balloon hashing} based
+    on BLAKE2b-256.
 @item Encryptionless confidentiality preserving encoding
     @url{http://people.csail.mit.edu/rivest/chaffing-980701.txt,
     Chaffing-and-Winnowing} (two Poly1305 MACs for each bit of message)
index 5f28a7fd861050be3de3d33926bb0c544502723a..483177262533fdcca383f4dd0c6617b4720bb33a 100644 (file)
@@ -23,14 +23,14 @@ example:
 @verbatim
 client% ./utils/newclient.sh Alice
 Passphrase:
-Your client verifier is: $argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg
+Your client verifier is: $balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg
 
 Place the following YAML configuration entry on the server's side:
 
     Alice:
         up: /path/to/up.sh
         iface: or TAP interface name
-        verifier: $argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
+        verifier: $balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
 @end verbatim
 
 @strong{Prepare the server}. Add this entry to @file{peers.yaml}
@@ -39,7 +39,7 @@ configuration file:
 @verbatim
 Alice:
     iface: tap10
-    verifier: $argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
+    verifier: $balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
 @end verbatim
 
 @strong{Prepare network on GNU/Linux IPv4 server}:
@@ -71,7 +71,7 @@ client% ip route add 128/1 via 172.16.0.1
 @strong{Run client daemon itself}:
 @verbatim
 client% govpn-client \
-    -verifier '$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg' \
+    -verifier '$balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg' \
     -iface tap10 \
     -remote 192.168.0.1:1194
 @end verbatim
@@ -89,7 +89,7 @@ client% ifconfig tap10
 client% ifconfig tap10 inet6 fc00::2/96 up
 client% route -6 add default fc00::1
 client% govpn-client \
-    -verifier '$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg' \
+    -verifier '$balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg' \
     -iface tap10 \
     -remote "[fe80::1%me0]":1194
 @end verbatim
index 39e901d75d5827628b02132bff1ccf130b527430..01ac54b8e1cbc48aaf04a193ad7f7f08ac2c17dc 100644 (file)
@@ -28,7 +28,6 @@ Included required libraries:
 @item @code{github.com/bigeagle/water} @tab GNU/Linux @tab BSD 3-Clause
 @item @code{github.com/dchest/blake2b} @tab All @tab CC0 1.0
 @item @code{github.com/go-yaml/yaml} @tab All @tab LGPLv3 and MIT
-@item @code{github.com/magical/argon2} @tab All @tab BSD 2-Clause
 @item @code{golang.org/x/crypto} @tab All @tab BSD 3-Clause
 @end multitable
 
index 38d03364becef1c412bbc7f320b77f13ccebe7bc..47ba43bc1607d386173505a9fd3ccbbc483e5746 100644 (file)
@@ -1,6 +1,18 @@
 @node Новости
 @section Новости
 
+@node Релиз 6.0
+@subsection Релиз 6.0
+@itemize
+@item Argon2d заменён на Balloon хэширование. Найденные Argon2
+библиотеки, написанные полностью на Go, имеют различные проблемы. Более
+того, Argon2i должен был быть использован вместо Argon2d, но у него есть
+возможные @url{http://eprint.iacr.org/2016/027, криптографические
+недостатки}. Поэтому он заменён на гораздо более простое (и, похоже,
+даже криптографически лучшее)
+@url{https://crypto.stanford.edu/balloon/, Balloon хэширование}.
+@end itemize
+
 @node Релиз 5.10
 @subsection Релиз 5.10
 @itemize
index 58b6d129bbb3021ae4e19bb21bf52f806b973ed3..631c5940ac541920570e9a02f9e807d232a872fe 100644 (file)
@@ -3,6 +3,17 @@
 
 See also this page @ref{Новости, on russian}.
 
+@node Release 6.0
+@section Release 6.0
+@itemize
+@item Argon2d is replaced with Balloon hashing. Found Argon2 libraries
+written on pure Go have various problems. Moreover Argon2i should be
+used instead, but it has some possible
+@url{http://eprint.iacr.org/2016/027, cryptographic defects}. So it is
+replaced with much more simpler (and seems even cryptographically
+better) @url{https://crypto.stanford.edu/balloon/, Balloon hashing}.
+@end itemize
+
 @node Release 5.10
 @section Release 5.10
 @itemize
index 0d44b798d14fd5e4c9731cdcd4be5d8db10461b6..325d317cb4b435f88398e56d51382166919c008f 100644 (file)
@@ -34,7 +34,7 @@ stargrave:                          <-- Peer human readable name
     noise: No                       <-- OPTIONAL noise enabler
     cpr: 64                         <-- OPTIONAL constant packet rate, KiB/sec
     encless: No                     <-- OPTIONAL Encryptionless mode
-    verifier: $argon2d...           <-- verifier received from client
+    verifier: $baloon...            <-- verifier received from client
 [...]
 @end verbatim
 
@@ -63,25 +63,25 @@ creation:
 @verbatim
 % ./utils/newclient.sh Alice
 [...]
-Your client verifier is: $argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg
+Your client verifier is: $balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg
 
 Place the following YAML configuration entry on the server's side:
 
     Alice:
         up: /path/to/up.sh
         iface: or TAP interface name
-        verifier: $argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
+        verifier: $balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
 @end verbatim
 
 Example configuration file:
 @verbatim
 stargrave:
     iface: tap0
-    verifier: $argon2d$m=4096,t=128,p=1$VMirzcshcHuG2V4jhUsEjw$X5fC07L8k61h3S1Oro/rC76+m0oGDTA9Bq+aWJ1uOgY
+    verifier: $balloon$s=32768,t=16,p=2$VMirzcshcHuG2V4jhUsEjw$X5fC07L8k61h3S1Oro/rC76+m0oGDTA9Bq+aWJ1uOgY
 slow:
     iface: tap1
     encless: Yes
     mtu: 9000
     cpr: 384
-    verifier: $argon2d$m=4096,t=128,p=1$YbIA5garDqCOhtI/2EZVNg$gOo5vcEGynmpeepNscwclicfZsWxzgYFRLbgG21EZ1U
+    verifier: $balloon$s=32768,t=16,p=2$YbIA5garDqCOhtI/2EZVNg$gOo5vcEGynmpeepNscwclicfZsWxzgYFRLbgG21EZ1U
 @end verbatim
index 4f4b4382aaddefe3b33e175a357689dbccb6d253..778a786a6600d67481b2eb5c123e4ab0c0e051e4 100644 (file)
@@ -27,6 +27,5 @@ repositories will be unavailable (they are seldom updated):
 @item @code{github.com/bigeagle/water} @tab @url{git://git.cypherpunks.ru/water.git}
 @item @code{github.com/dchest/blake2b} @tab @url{git://git.cypherpunks.ru/blake2b.git}
 @item @code{github.com/go-yaml/yaml} @tab @url{git://git.cypherpunks.ru/yaml.git}
-@item @code{github.com/magical/argon2} @tab @url{git://git.cypherpunks.ru/argon2.git}
 @item @code{golang.org/x/crypto} @tab @url{git://git.cypherpunks.ru/crypto.git}
 @end multitable
index eebdedd80302c0bf42022ee78ec3867999f36ddc..0a6757cf6069dfecaeaaf5987a8586353705313d 100644 (file)
@@ -9,6 +9,7 @@ Thanks for contributions and suggestions to:
 @item @url{https://www.cs.columbia.edu/~smb/papers/aeke.pdf, Augmented Encrypted Key Exchange}: a Password-Based Protocol Secure Against Dictionary Attacks and Password File Compromise @copyright{} Steven M. Belloving, Michael Merrit.
 @item @email{watsonbladd@@gmail.com, Watson Ladd} for suggestion of @url{http://elligator.cr.yp.to/, Elligator} encoding.
 @item @url{https://password-hashing.net/#argon2, Password Hashing Competition for Argon2}.
+@item @url{https://crypto.stanford.edu/balloon/, Balloon hashing}.
 @item @url{http://people.csail.mit.edu/rivest/chaffing-980701.txt, Chaffing and Winnowing: Confidentiality without Encryption} @copyright{} Ronald L. Rivest
 @item @email{wzyboy@@wzyboy.org, Zhuoyun Wei} for @url{https://aur.archlinux.org/packages/govpn/, AUR} port maintaining and his documentation related fixes.
 @end itemize
index 7efdf07c1e74dfa7d1782308a556d049feec3e82..ecf98ad6ddc606342e78dc7886c1c19c99014b01 100644 (file)
@@ -6,8 +6,8 @@ Verifier is created using @command{govpn-verifier} utility.
 @verbatim
 % govpn-verifier
 Passphrase:[hello world]
-$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
-$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg
+$balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
+$balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg
 @end verbatim
 
 First line is the verifier for the server side. Second line is for the
@@ -18,7 +18,7 @@ You can check passphrase against verifier by specifying @option{-verifier}
 option with the path to verifier file:
 
 @verbatim
-% govpn-verifier -verifier '$argon2d...'
+% govpn-verifier -verifier '$balloon...'
 Passphrase:[hello world]
 true
 @end verbatim
index 792506dd9f93ac95f4509998c07b8ce2db8cbf14..b199d72faebc09f42b48488179baf1c8724db75e 100644 (file)
@@ -6,17 +6,18 @@ dictionary attacks and can not be used for authentication (only
 its verifying).
 
 @verbatim
-SOURCE = Argon2d(m, t, p, SALT=PeerId, PASSWORD)
+SOURCE = Balloon(PASSWORD, SALT=PeerId, sCost, tCost, pJobs)
 PUB, PRIV = Ed25519.Generate(SOURCE)
 @end verbatim
 
+Balloon hashing uses BLAKE2b-256 hash. Space cost (sCost), time cost
+(tCost) and number of parallel jobs (pJobs) are specific to Balloon
+implementation.
+
 Verifier is serialized representation of public data above:
 @verbatim
-$argon2d$m=m,t=t,p=p$Base64(SALT)$Base64(PUB)
+$balloon$s=s,t=t,p=p$Base64(SALT)$Base64(PUB)
 @end verbatim
 
-m, t and p parameters are Argon2d-specific: memory, iterations and
-parallelizm parameters.
-
 Server stores and knows only verifier. Client can compute the whole
 keypair every time he makes handshake.
diff --git a/src/cypherpunks.ru/balloon b/src/cypherpunks.ru/balloon
new file mode 160000 (submodule)
index 0000000..9e7f630
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 9e7f63092012aa91a6690d93f00f5bc476e4d3b5
index 16f7847ea8fdbd8061d534449821618b7b1cfb2c..a83f9d15f18f75ea73a0951fd119db26940ba9df 100644 (file)
@@ -32,9 +32,9 @@ import (
 var (
        keyPath  = flag.String("key", "", "Path to passphrase file")
        verifier = flag.String("verifier", "", "Optional verifier")
-       mOpt     = flag.Int("m", govpn.DefaultM, "Argon2d memory parameter (KiBs)")
-       tOpt     = flag.Int("t", govpn.DefaultT, "Argon2d iteration parameter")
-       pOpt     = flag.Int("p", govpn.DefaultP, "Argon2d parallelizm parameter")
+       sOpt     = flag.Int("s", govpn.DefaultS, "Balloon space cost")
+       tOpt     = flag.Int("t", govpn.DefaultT, "Balloon time cost")
+       pOpt     = flag.Int("p", govpn.DefaultP, "Balloon parallel jobs")
        egdPath  = flag.String("egd", "", "Optional path to EGD socket")
        version  = flag.Bool("version", false, "Print version information")
        warranty = flag.Bool("warranty", false, "Print warranty information")
@@ -63,7 +63,7 @@ func main() {
                        log.Fatalln(err)
                }
                pid := govpn.PeerId(*id)
-               v := govpn.VerifierNew(*mOpt, *tOpt, *pOpt, &pid)
+               v := govpn.VerifierNew(*sOpt, *tOpt, *pOpt, &pid)
                v.PasswordApply(key)
                fmt.Println(v.LongForm())
                fmt.Println(v.ShortForm())
index 15955e77a2cf65e35ab18172d638a677170a3200..b68063b94823361f25bc5734d50cd7aa43a6502b 100644 (file)
@@ -28,19 +28,20 @@ import (
        "os"
        "strings"
 
+       "cypherpunks.ru/balloon"
        "github.com/agl/ed25519"
-       "github.com/magical/argon2"
+       "github.com/dchest/blake2b"
        "golang.org/x/crypto/ssh/terminal"
 )
 
 const (
-       DefaultM = 1 << 12
-       DefaultT = 1 << 7
-       DefaultP = 1
+       DefaultS = 1 << 20 / 32
+       DefaultT = 1 << 4
+       DefaultP = 2
 )
 
 type Verifier struct {
-       M   int
+       S   int
        T   int
        P   int
        Id  *PeerId
@@ -49,17 +50,14 @@ type Verifier struct {
 
 // 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}
+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)
-       if err != nil {
-               log.Fatalln("Unable to apply Argon2d", err)
-       }
+       r := balloon.H(blake2b.New256, []byte(password), v.Id[:], v.S, v.T, v.P)
        defer SliceZero(r)
        src := bytes.NewBuffer(r)
        pub, prv, err := ed25519.GenerateKey(src)
@@ -72,26 +70,26 @@ func (v *Verifier) PasswordApply(password string) *[ed25519.PrivateKeySize]byte
 
 // Parse either short or long verifier form.
 func VerifierFromString(input string) (*Verifier, error) {
-       s := strings.Split(input, "$")
-       if len(s) < 4 || 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])
+       if len(ss) == 5 {
+               pub, err := base64.RawStdEncoding.DecodeString(ss[4])
                if err != nil {
                        return nil, err
                }
@@ -105,8 +103,8 @@ func VerifierFromString(input string) (*Verifier, error) {
 // 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[:]),
        )
 }
 
diff --git a/src/github.com/magical/argon2 b/src/github.com/magical/argon2
deleted file mode 160000 (submodule)
index 190e3cf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 190e3cf208e185668db6aa048e4985b7b7b4d890
index 7c1240a671f134430403a130b804660727aee9b5..96dfb60623f6cfc5cc407e2cb606103495c16889 100755 (executable)
@@ -11,7 +11,6 @@ repos="
     src/github.com/bigeagle/water
     src/github.com/dchest/blake2b
     src/github.com/go-yaml/yaml
-    src/github.com/magical/argon2
     src/golang.org/x/crypto
 "
 for repo in $repos; do