* 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:
[submodule "src/golang.org/x/crypto"]
path = src/golang.org/x/crypto
url = https://go.googlesource.com/crypto
[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/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
@item DH elliptic-curve point encoding for public keys
@url{http://elligator.cr.yp.to/, Elligator}.
@item Verifier password hashing algorithm
@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)
@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)
@verbatim
client% ./utils/newclient.sh Alice
Passphrase:
@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
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}
@end verbatim
@strong{Prepare the server}. Add this entry to @file{peers.yaml}
@verbatim
Alice:
iface: tap10
@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}:
@end verbatim
@strong{Prepare network on GNU/Linux IPv4 server}:
@strong{Run client daemon itself}:
@verbatim
client% govpn-client \
@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
-iface tap10 \
-remote 192.168.0.1:1194
@end verbatim
client% ifconfig tap10 inet6 fc00::2/96 up
client% route -6 add default fc00::1
client% govpn-client \
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
-iface tap10 \
-remote "[fe80::1%me0]":1194
@end verbatim
@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/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
@item @code{golang.org/x/crypto} @tab All @tab BSD 3-Clause
@end multitable
@node Новости
@section Новости
@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
@node Релиз 5.10
@subsection Релиз 5.10
@itemize
See also this page @ref{Новости, on russian}.
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
@node Release 5.10
@section Release 5.10
@itemize
noise: No <-- OPTIONAL noise enabler
cpr: 64 <-- OPTIONAL constant packet rate, KiB/sec
encless: No <-- OPTIONAL Encryptionless mode
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
@verbatim
% ./utils/newclient.sh Alice
[...]
@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
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
@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
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
@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/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
@item @code{golang.org/x/crypto} @tab @url{git://git.cypherpunks.ru/crypto.git}
@end multitable
@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://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
@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
@verbatim
% govpn-verifier
Passphrase:[hello world]
@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
@end verbatim
First line is the verifier for the server side. Second line is for the
option with the path to verifier file:
@verbatim
option with the path to verifier file:
@verbatim
-% govpn-verifier -verifier '$argon2d...'
+% govpn-verifier -verifier '$balloon...'
Passphrase:[hello world]
true
@end verbatim
Passphrase:[hello world]
true
@end verbatim
its verifying).
@verbatim
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
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
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)
-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.
Server stores and knows only verifier. Client can compute the whole
keypair every time he makes handshake.
--- /dev/null
+Subproject commit 9e7f63092012aa91a6690d93f00f5bc476e4d3b5
var (
keyPath = flag.String("key", "", "Path to passphrase file")
verifier = flag.String("verifier", "", "Optional verifier")
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")
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")
log.Fatalln(err)
}
pid := govpn.PeerId(*id)
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())
v.PasswordApply(key)
fmt.Println(v.LongForm())
fmt.Println(v.ShortForm())
+ "cypherpunks.ru/balloon"
- "github.com/magical/argon2"
+ "github.com/dchest/blake2b"
"golang.org/x/crypto/ssh/terminal"
)
const (
"golang.org/x/crypto/ssh/terminal"
)
const (
- DefaultM = 1 << 12
- DefaultT = 1 << 7
- DefaultP = 1
+ DefaultS = 1 << 20 / 32
+ DefaultT = 1 << 4
+ DefaultP = 2
// Generate new verifier for given peer, with specified password and
// hashing parameters.
// 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 {
}
// 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)
defer SliceZero(r)
src := bytes.NewBuffer(r)
pub, prv, err := ed25519.GenerateKey(src)
// Parse either short or long verifier form.
func VerifierFromString(input string) (*Verifier, error) {
// 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")
}
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")
}
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
}
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
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
}
if err != nil {
return nil, err
}
// Does not include public key.
func (v *Verifier) ShortForm() string {
return fmt.Sprintf(
// 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[:]),
+++ /dev/null
-Subproject commit 190e3cf208e185668db6aa048e4985b7b7b4d890
src/github.com/bigeagle/water
src/github.com/dchest/blake2b
src/github.com/go-yaml/yaml
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
src/golang.org/x/crypto
"
for repo in $repos; do