.gitmodules | 6 ++++++ VERSION | 2 +- doc/about.ru.texi | 5 +++-- doc/about.texi | 7 ++++--- doc/client.texi | 4 ++-- doc/developer.texi | 5 ++--- doc/download.texi | 4 ++++ doc/example.texi | 20 ++++++++++---------- doc/handshake.texi | 8 ++++---- doc/identity.texi | 10 ++-------- doc/installation.texi | 4 +++- doc/media.texi | 2 +- doc/news.texi | 42 +++++++++++++++++++++++++----------------- doc/pake.texi | 8 ++++---- doc/precautions.texi | 2 +- doc/server.texi | 14 +++++--------- doc/sources.texi | 4 +++- doc/thanks.texi | 3 ++- doc/todo.texi | 3 --- doc/verifier.texi | 13 +++++++++---- doc/verifierstruct.texi | 16 +++++++++++----- src/govpn/cmd/govpn-client/main.go | 58 +++++++++++++++++++++++++++-------------------------- src/govpn/cmd/govpn-server/common.go | 18 ++++++++++++++++++ src/govpn/cmd/govpn-server/conf.go | 35 +++++++++++------------------------ src/govpn/cmd/govpn-verifier/main.go | 39 +++++++++++++++++++++++---------------- src/govpn/conf.go | 20 ++++++++++---------- src/govpn/handshake.go | 12 ++++++------ src/govpn/identify.go | 17 ----------------- src/govpn/peer.go | 24 ++++++++++++++++++++++++ src/govpn/peer_test.go | 11 ++++++----- src/govpn/stats.go | 18 ++++++++++++++++++ src/govpn/verifier.go | 94 +++++++++++++++++++++++++++++++++++++++++++++-------- utils/makedist.sh | 3 ++- utils/newclient.sh | 19 +++++++++---------- diff --git a/.gitmodules b/.gitmodules index f2d6ae4dfa28c8ac448fae2d6a660339e74c044a..ffbe4428c4b4ad35b59057f4f46ed0a0ed81ca90 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,9 @@ url = https://github.com/agl/ed25519.git [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 diff --git a/VERSION b/VERSION index 5186d07068cfed4c3f4705df79c73e115dd35c43..7d5c902e777905446c67de7e52a945b88fd2038c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0 +4.1 diff --git a/doc/about.ru.texi b/doc/about.ru.texi index d70318f5a5b23969102804e930133c6ec83a1327..3b2fda693f9235cecc521199c6e24de0c39fd430 100644 --- a/doc/about.ru.texi +++ b/doc/about.ru.texi @@ -4,7 +4,7 @@ GoVPN это простой демон виртуальных частных сетей, код которого нацелен на лёгкость чтения и анализа, безопасность, устойчивость к DPI/цензуре. -@itemize @bullet +@itemize @item Свободное программное обеспечение, копилефт: лицензировано под условиями @url{https://www.gnu.org/licenses/gpl-3.0.ru.html, GPLv3+}. @@ -15,7 +15,8 @@ нулевым неразглашением (PAKE DH A-EKE (Diffie-Hellman Augmented Encrypted Key Exchange)). @item Несбалансированные аутентификационные токены устойчивые к внесетевым -(offline) атакам по словарю. Злоумышленник не может замаскироваться под +(offline) атакам по словарю. Используют усиленный по CPU и памяти +алгоритм хэширования. Злоумышленник не может замаскироваться под клиента даже скомпрометировав базу данных токенов сервера. @item Зашифрованный и аутентифицируемый транспортный протокол передачи данных diff --git a/doc/about.texi b/doc/about.texi index d205a109240623c536edac14e03fb2ee1a58468c..6e25072188f06c2bf3ff63f30c5eeeaa500c96ea 100644 --- a/doc/about.texi +++ b/doc/about.texi @@ -2,7 +2,7 @@ GoVPN is simple free software virtual private network daemon, aimed to be reviewable, secure and @url{https://en.wikipedia.org/wiki/Deep_packet_inspection, DPI}/censorship-resistant. -@itemize @bullet +@itemize @item Copylefted free software: licenced under @url{https://www.gnu.org/licenses/gpl-3.0.html, GPLv3+}. @@ -13,8 +13,9 @@ authentication (PAKE DH A-EKE (Diffie-Hellman Augmented Encrypted Key Exchange)). @item @ref{Verifier structure, Augmented authentication tokens} resistant to -offline dictionary attacks. An attacker can not masquerade a client -even with server passphrase verifiers compromising. +offline dictionary attacks. They use CPU and memory hardened hashing +algorithm. An attacker can not masquerade a client even with server +passphrase verifiers compromising. @item Encrypted and authenticated @ref{Transport, payload transport} with 128-bit @ref{Developer, security margin} state-of-the-art diff --git a/doc/client.texi b/doc/client.texi index bab6a47c911b947592fb105ddd35b51b89b7dfd3..40f310f4e145843d6e3b7b8f4f81a0322fb5cc7e 100644 --- a/doc/client.texi +++ b/doc/client.texi @@ -24,8 +24,8 @@ @item -iface TAP interface name. -@item -id -Our client's @ref{Identity} (hexadecimal string). +@item -verifier +Our client's @ref{Verifier}. @item -key Path to the file with the passphrase. See @ref{Verifier} for diff --git a/doc/developer.texi b/doc/developer.texi index 60352254bbbdb391b2f08e17b97e38539e9ac605..d9ec24fffbcdff245b5983402cfd8e400e2e92a5 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -15,9 +15,8 @@ DH-A-EKE powered by @url{http://cr.yp.to/ecdh.html, Curve25519} and @url{http://ed25519.cr.yp.to/, Ed25519}. @item DH elliptic-curve point encoding for public keys @url{http://elligator.cr.yp.to/, Elligator}. -@item Key derivation function for verifier generation -@url{https://en.wikipedia.org/wiki/PBKDF2, PBKDF2} based on -@url{https://en.wikipedia.org/wiki/SHA-2, SHA-512}. +@item Verifier password hashing algorithm +@url{https://password-hashing.net/#argon2, Argon2d}. @item Packet overhead 26 bytes per packet. @item Handshake overhead diff --git a/doc/download.texi b/doc/download.texi index 96367a1d314be0e86428cbfa79ffe29bccaa854b..41a2c4dccb4bb4dfca406645086e952459c58afe 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -6,6 +6,10 @@ @multitable {XXXXX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @headitem Version @tab Size @tab Tarball @tab SHA256 checksum +@item 4.0 @tab 183 KiB +@tab @url{download/govpn-4.0.tar.xz, link} @url{download/govpn-4.0.tar.xz.sig, sign} +@tab @code{a791c3569c01dea8b18aa2f21d27b797ded76f2c33a8d96c2db864a9abf2615b} + @item 3.5 @tab 179 KiB @tab @url{download/govpn-3.5.tar.xz, link} @url{download/govpn-3.5.tar.xz.sig, sign} @tab @code{6b60c2cd4a8b4b2c893e52d3366510678704fd68a02a0ea24cb112bd753ea54b} diff --git a/doc/example.texi b/doc/example.texi index c26284650498e9b2a7e5ff290dc3799bdf0a93e0..6fd62dfd12becda2f470b11ec204e98793b4bbde 100644 --- a/doc/example.texi +++ b/doc/example.texi @@ -4,7 +4,7 @@ Let's assume that there is some insecure link between your computer and WiFi-reachable gateway. -@itemize @bullet +@itemize @item You have got @code{wlan0} NIC with 192.168.0/24 network on it. @item You want to create virtual encrypted and authenticated 172.16.0/24 network and use it as a default transport. @@ -17,25 +17,25 @@ @strong{Install}. At first you must @ref{Installation, install} this software: download, @ref{Integrity, check the signature}, compile. -@strong{Prepare the client}. Generate client's identity and verifier for -Alice as an example: +@strong{Prepare the client}. Generate client's verifier for Alice as an +example: + @verbatim client% ./utils/newclient.sh Alice Enter passphrase: -Your id is: 7012df29deee2170594119df5091d4a2 +Your client verifier is: $argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg Place the following JSON configuration entry on the server's side: - "7012df29deee2170594119df5091d4a2": { - "name": "Alice", + "Alice": { "up": "/path/to/up.sh", - "verifier": "fb43255ca3fe5bd884e364e5eae0cd37ad14774930a027fd38d8938fd0b57425" + "verifier": "$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10" } Verifier was generated with: ./utils/storekey.sh /tmp/passphrase - govpn-verifier -id 7012df29deee2170594119df5091d4a2 -key /tmp/passphrase + govpn-verifier -key /tmp/passphrase @end verbatim @strong{Prepare the server}. Add this entry to @code{peers.json} @@ -77,7 +77,7 @@ @strong{Run client daemon itself}: @example client% govpn-client \ -key key.txt \ - -id 906e34b98750c4f686d6c5489508763c \ + -verifier '$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg' \ -iface tap10 \ -remote 192.168.0.1:1194 \ -mtu 1472 @@ -97,7 +97,7 @@ client% ifconfig tap10 inet6 fc00::2/96 mtu 1412 up client% route -6 add default fc00::1 client% govpn-client \ -key key.txt \ - -id 906e34b98750c4f686d6c5489508763c \ + -verifier '$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg' \ -iface tap10 \ -remote "[fe80::1%me0]":1194 @end example diff --git a/doc/handshake.texi b/doc/handshake.texi index c15e45643857004d2ae4f07b3fe97339fcff7ef8..b445985240b447553293b1ff08537b790fa679ec 100644 --- a/doc/handshake.texi +++ b/doc/handshake.texi @@ -34,7 +34,7 @@ @item @verb{|R + enc(H(DSAPub), R, El(CDHPub)) + IDtag -> Server|} [48 bytes] @item -@itemize @bullet +@itemize @item Server remembers client address. @item Decrypts @code{El(CDHPub)}. @item Inverts @code{El()} encoding and gets @code{CDHPub}. @@ -48,7 +48,7 @@ @item @verb{|enc(H(DSAPub), R+1, El(SDHPub)) + enc(K, R, RS + SS) + IDtag -> Client|} [80 bytes] @item -@itemize @bullet +@itemize @item Client decrypts @code{El(SDHPub)}. @item Inverts @code{El()} encoding and gets @code{SDHPub}. @item Computes @code{K}. @@ -63,7 +63,7 @@ @item @verb{|enc(K, R+1, RS + RC + SC + Sign(DSAPriv, K)) + IDtag -> Server|} [120 bytes] @item -@itemize @bullet +@itemize @item Server decrypts @code{RS}, @code{RC}, @code{SC}, @code{Sign(DSAPriv, K)}. @@ -81,7 +81,7 @@ @item @verb{|ENC(K, R+2, RC) + IDtag -> Client|} [16 bytes] @item -@itemize @bullet +@itemize @item Client decrypts @code{RC} @item Compares with its own one sent before. @item Computes final session encryption key as server did. diff --git a/doc/identity.texi b/doc/identity.texi index 46a6889d2c1fda4041f4c89a1d5c30ffb408ef90..7e33b330254a60894680793506661008453154ed 100644 --- a/doc/identity.texi +++ b/doc/identity.texi @@ -3,11 +3,5 @@ @section Identity Client's identity is 128-bit string. It is not secret, so can be transmitted and stored in the clear. However handshake applies PRP on it -to make DPI and deanonymization much harder to success. - -@example -% ./utils/newclient.sh doesnotmatter -Your id is: 7012df29deee2170594119df5091d4a2 -@end example - -@code{7012df29deee2170594119df5091d4a2} is client's identity. +to make DPI and deanonymization much harder to success. It is used as a +salt in verifier. diff --git a/doc/installation.texi b/doc/installation.texi index cc5debba80d04a517677876933bf7836a5204199..d8d958767c619ac06f1c608ee156bcdb6c9ad4bb 100644 --- a/doc/installation.texi +++ b/doc/installation.texi @@ -3,7 +3,7 @@ @unnumbered Installation Possibly GoVPN already exists in your distribution: -@itemize @bullet +@itemize @item @url{https://aur.archlinux.org/packages/govpn/, AUR} @item @url{http://www.freshports.org/security/govpn/, FreeBSD ports} @end itemize @@ -24,6 +24,8 @@ @multitable @columnfractions .40 .20 .40 @headitem Library @tab Platform @tab Licence @item @code{golang.org/x/crypto} @tab All @tab BSD 3-Clause @item @code{github.com/agl/ed25519} @tab All @tab BSD 3-Clause +@item @code{github.com/dchest/blake2b} @tab All @tab CC0 1.0 +@item @code{github.com/magical/argon2} @tab All @tab BSD 2-Clause @item @code{github.com/bigeagle/water} @tab GNU/Linux @tab BSD 3-Clause @end multitable diff --git a/doc/media.texi b/doc/media.texi index 9423086187e0c00df58dff109e2525f8f1b5b4b4..b129c0dd1b69c40f679e4e433ba72513bb97cbe4 100644 --- a/doc/media.texi +++ b/doc/media.texi @@ -1,7 +1,7 @@ @node Media @unnumbered In the media -@itemize @bullet +@itemize @item @url{http://habrahabr.ru/company/ivi/blog/256365/, Реализуем безопасный VPN-протокол} (on russian) @item @url{http://habrahabr.ru/company/ivi/blog/257431/, Реализуем ещё более безопасный VPN-протокол} (on russian) @item @url{http://www.linuxspace.org/archives/9449, Установка и настройка безопасного VPN-демона GoVPN 3.2} (on russian) diff --git a/doc/news.texi b/doc/news.texi index bdb178e977ef5666aa25fdd16cf113518b78a5b6..c2d06b89b094afa5294fd166583a6d38ef4a72b2 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -3,8 +3,16 @@ @unnumbered News @table @strong +@item Release 4.1 +@itemize +@item @url{https://password-hashing.net/#argon2, Argon2d} is used instead +of PBKDF2 for password verifier hashing. +@item Client's identity is stored inside the verifier, so it simplifies +server-side configuration and the code. +@end itemize + @item Release 4.0 -@itemize @bullet +@itemize @item Handshake messages can be noised: their messages lengths are hidden. Now they are indistinguishable from transport messages. @item Parallelized clients processing on the server side. @@ -13,7 +21,7 @@ @item Single JSON file server configuration. @end itemize @item Release 3.5 -@itemize @bullet +@itemize @item Ability to use @ref{Network, TCP} network transport. Server can listen on both UDP and TCP sockets. @item Ability to use @ref{Proxy, HTTP proxies} (through CONNECT method) @@ -24,7 +32,7 @@ reasons. @end itemize @item Release 3.4 -@itemize @bullet +@itemize @item Ability to use external @ref{EGD}-compatible PRNGs. Now you are able to use GoVPN even on systems with the bad @code{/dev/random}, providing higher quality entropy from external sources. @@ -34,7 +42,7 @@ without performance degradation related to inbound packets reordering. @end itemize @item Release 3.3 -@itemize @bullet +@itemize @item Compatibility with an old GNU Make 3.x. Previously only BSD Make and GNU Make 4.x were supported. @item /dev/urandom is used for correct client identity generation under @@ -44,7 +52,7 @@ @item Updated user manual examples. @end itemize @item Release 3.2 -@itemize @bullet +@itemize @item Deterministic building: dependent libraries source code commits are fixed in our makefiles. @@ -56,7 +64,7 @@ FreeBSD Make compatibility. GNU Make is not necessary anymore. @end itemize @item Release 3.1 -@itemize @bullet +@itemize @item Diffie-Hellman public keys are encoded with Elligator algorithm when sending over the wire, making them indistinguishable from the random @@ -66,7 +74,7 @@ consume twice entropy for DH key generation in average. @end itemize @item Release 3.0 -@itemize @bullet +@itemize @item EKE protocol is replaced by Augmented-EKE and static symmetric (both sides have it) pre-shared key replaced with server-side verifier. This @@ -98,7 +106,7 @@ @code{-cpr} configuration options for server. @end itemize @item Release 2.4 -@itemize @bullet +@itemize @item Added ability to optionally run built-in HTTP-server responding with JSON of all known connected peers information. Real-time client's @@ -109,7 +117,7 @@ Documentation is explicitly licenced under GNU FDL 1.3+. @end itemize @item Release 2.3 -@itemize @bullet +@itemize @item Handshake packets became indistinguishable from the random. Now all GoVPN's traffic is the noise for men in the middle. @@ -124,46 +132,46 @@ consuming and resource heavy computations. @end itemize @item Release 2.2 -@itemize @bullet +@itemize @item Fixed several possible channel deadlocks. @end itemize @item Release 2.1 -@itemize @bullet +@itemize @item Fixed Linux-related building. @end itemize @item Release 2.0 -@itemize @bullet +@itemize @item Added clients identification. @item Simultaneous several clients support by server. @item Per-client up/down scripts. @end itemize @item Release 1.5 -@itemize @bullet +@itemize @item Nonce obfuscation/encryption. @end itemize @item Release 1.4 -@itemize @bullet +@itemize @item Performance optimizations. @end itemize @item Release 1.3 -@itemize @bullet +@itemize @item Heartbeat feature. @item Rehandshake feature. @item up- and down- optinal scripts. @end itemize @item Release 1.1 -@itemize @bullet +@itemize @item FreeBSD support. @end itemize @item Release 1.0 -@itemize @bullet +@itemize @item Initial stable release. @end itemize diff --git a/doc/pake.texi b/doc/pake.texi index d2cb77351f7aed884dddae82efdf2807371e4645..fa8a322c6666a9f132cfacd4564399dad3a4b2fc 100644 --- a/doc/pake.texi +++ b/doc/pake.texi @@ -5,7 +5,7 @@ Previously we used pre-shared high-entropy long-term static key for client-server authentication. Is is secure, but not convenient for some user use-cases: -@itemize @bullet +@itemize @item Compromising of passphrase files on either server or client side allows attacker to masquerade himself a client. @item To prevent compromising of keys on the client side, one needs some @@ -25,6 +25,6 @@ they are memorable. Because of their quantity, they acts as a high entropy source. Passphrases are entered directly by the human on the client side. Server -side stores previously shared so-called @ref{Verifier}. Verifier contains -dictionary attack resistant password derivative. Attacker can not use it -to act as a client. +side stores previously shared so-called @ref{Verifier, verifier}. Verifier +contains dictionary attack resistant password derivative. Attacker can not +use it to act as a client. diff --git a/doc/precautions.texi b/doc/precautions.texi index fad882d6b411e0f2f74d1473888a897ba4b94e69..fbf45d13a4636b2315c7ec52f504362b53858e5c 100644 --- a/doc/precautions.texi +++ b/doc/precautions.texi @@ -6,7 +6,7 @@ @item We use password (passphrase) authentication, so overall security fully depends on its strength. You @strong{should} use long, high-entropy passphrases. Also remember to keep passphrase in temporary file and read -it securely as described in @ref{Verifier}. +it securely as described in @ref{Verifier, verifier}. @item You must @strong{never} use the same key for multiple clients. diff --git a/doc/server.texi b/doc/server.texi index 49a09fb990438998a7a939d354e650c800761120..a00c45219329c0bc460deb2f712e92d6656f3776 100644 --- a/doc/server.texi +++ b/doc/server.texi @@ -25,8 +25,7 @@ Configuration file is JSON file with following example structure: @verbatim { - "9b40701bdaf522f2b291cb039490312": { <-- Peer identifier - "name": "stargrave", <-- OPTIONAL human readable name + "stargrave": { <-- Peer human readable name "up": "./stargrave-up.sh", <-- up-script "down": "./stargrave-down.sh", <-- OPTIONAL down-script "timeout": 60, <-- OPTIONAL overriden timeout @@ -34,13 +33,11 @@ "noise": true, <-- OPTIONAL noise enabler (default: false) "cpr": 64, <-- OPTIONAL constant packet rate in KiB/sec - "verifier": "2c15bbdffc73193bea56db412bce1143c68ccbdaa9e2eade53a684497646a685" + "verifier": "$argon2d..." <-- verifier received from client }, [...] } @end verbatim - -See @ref{Verifier} for its description. up-script executes each time connection with the client is established. Its @emph{stdout} output must contain TAP interface name as the first @@ -62,14 +59,13 @@ @verbatim % ./utils/newclient.sh Alice [...] -Your id is: 7012df29deee2170594119df5091d4a2 +Your client verifier is: $argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg Place the following JSON configuration entry on the server's side: - "906e34b98750c4f686d6c5489508763c": { - "name": "Alice", + "Alice": { "up": "/path/to/up.sh", - "verifier": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "verifier": "$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10" } [...] @end verbatim diff --git a/doc/sources.texi b/doc/sources.texi index 40aa499e28a99f795e47f46073326a1e8716d48c..f2dd06dc22290660624a3fba18b0da58f3479e5c 100644 --- a/doc/sources.texi +++ b/doc/sources.texi @@ -23,7 +23,9 @@ @multitable @columnfractions .50 .50 @headitem Software/library @tab Mirror @item @code{govpn} @tab @url{https://github.com/stargrave/govpn.git} -@item @code{golang.org/x/crypto} @tab @url{git://git.cypherpunks.ru/crypto.git} @item @code{github.com/agl/ed25519} @tab @url{git://git.cypherpunks.ru/ed25519.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/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 diff --git a/doc/thanks.texi b/doc/thanks.texi index b50bc9c789daa824648d57efff24ca9d6f662dfb..5b9dba36b1380165a4ec53ae090dea1d0fa7a279 100644 --- a/doc/thanks.texi +++ b/doc/thanks.texi @@ -3,7 +3,7 @@ @unnumbered Thanks Thanks for contributions and suggestions to: -@itemize @bullet +@itemize @item @url{https://www.schneier.com/books/applied_cryptography/, Applied Cryptography} @copyright{} 1996 Bruce Schneier. @@ -20,4 +20,5 @@ @item @url{http://cr.yp.to/mac.html, A state-of-the-art message-authentication code}. @item @url{http://ed25519.cr.yp.to/, Ed25519: high-speed high-security signatures}. @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, PHC for Argon2}. @end itemize diff --git a/doc/todo.texi b/doc/todo.texi index f7d00f3102f60cedcf7719c63ca03ccbb9761b94..520192c6ac01901d009024313d60f99ff7df4330 100644 --- a/doc/todo.texi +++ b/doc/todo.texi @@ -2,9 +2,6 @@ @node TODO @unnumbered TODO @itemize -@item Use Argon2: -@url{https://password-hashing.net/, Password Hashing Competition} -winner, instead of PBKDF2. @item Ability to tunnel only specified TCP connections, without full featured VPN solution. Similar to ssh -R. @item Randomize ports usage. diff --git a/doc/verifier.texi b/doc/verifier.texi index 61b1e4479f954082327f98bb77f76accee825385..07ba19826e5ccf2fb40f89ff819d472f6817a3b1 100644 --- a/doc/verifier.texi +++ b/doc/verifier.texi @@ -9,18 +9,23 @@ @example % utils/storekey.sh mypass.txt Enter passphrase:[hello world] -% govpn-verifier -id 9da9bf91112d0e4483c135b12d5b48de -key mypass.txt -210e3878542828901a3af9b4aa00b004de530410eef5c1ba2ffb6d04504371b2 +% govpn-verifier -key mypass.txt +$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10 +$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg @end example -Store @code{210...1b2} string on the server's side in corresponding +First line is the verifier for the server side. Second line is for the +client -- it lacks generated public key. However you can server's one +on the client side too. + +Store @code{$argon2d...u10} string on the server's side in corresponding @code{verifier} configuration file's field. You can check passphrase against verifier by specifying @code{-verifier} option with the path to verifier file: @example -% govpn-verifier -id 9da9bf91112d0e4483c135b12d5b48de -key mypass.txt -verifier verifier +% govpn-verifier -key mypass.txt -verifier '$argon2d...' true @end example diff --git a/doc/verifierstruct.texi b/doc/verifierstruct.texi index 65a4e086c14d7fbf8e5fd896fc4145c05845e077..792506dd9f93ac95f4509998c07b8ce2db8cbf14 100644 --- a/doc/verifierstruct.texi +++ b/doc/verifierstruct.texi @@ -6,11 +6,17 @@ dictionary attacks and can not be used for authentication (only its verifying). @verbatim -SOURCE = PBKDF2(SALT=PeerId, PASSWORD, 1<<16, SHA512) +SOURCE = Argon2d(m, t, p, SALT=PeerId, PASSWORD) PUB, PRIV = Ed25519.Generate(SOURCE) @end verbatim -Verifier is @code{PUB} public key of Ed25519 generated from the PBKDF2 -of the passphrase in hexadecimal encoding. @code{PeerId} is used as a -128-bit salt. Server stores and knows only verifier. Client can compute -the whole keypair every time he makes handshake. +Verifier is serialized representation of public data above: +@verbatim +$argon2d$m=m,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/govpn/cmd/govpn-client/main.go b/src/govpn/cmd/govpn-client/main.go index 6c611e746a1c43a8aed5a8657e88cccb34371b08..09b06ca44c753c894357f5b6ebf27fb27e6e5500 100644 --- a/src/govpn/cmd/govpn-client/main.go +++ b/src/govpn/cmd/govpn-client/main.go @@ -31,21 +31,21 @@ "govpn" ) var ( - remoteAddr = flag.String("remote", "", "Remote server address") - proto = flag.String("proto", "udp", "Protocol to use: udp or tcp") - ifaceName = flag.String("iface", "tap0", "TAP network interface") - IDRaw = flag.String("id", "", "Client identification") - keyPath = flag.String("key", "", "Path to passphrase file") - upPath = flag.String("up", "", "Path to up-script") - downPath = flag.String("down", "", "Path to down-script") - stats = flag.String("stats", "", "Enable stats retrieving on host:port") - proxyAddr = flag.String("proxy", "", "Use HTTP proxy on host:port") - proxyAuth = flag.String("proxy-auth", "", "user:password Basic proxy auth") - mtu = flag.Int("mtu", 1452, "MTU for outgoing packets") - timeoutP = flag.Int("timeout", 60, "Timeout seconds") - noisy = flag.Bool("noise", false, "Enable noise appending") - cpr = flag.Int("cpr", 0, "Enable constant KiB/sec out traffic rate") - egdPath = flag.String("egd", "", "Optional path to EGD socket") + remoteAddr = flag.String("remote", "", "Remote server address") + proto = flag.String("proto", "udp", "Protocol to use: udp or tcp") + ifaceName = flag.String("iface", "tap0", "TAP network interface") + verifierRaw = flag.String("verifier", "", "Verifier") + keyPath = flag.String("key", "", "Path to passphrase file") + upPath = flag.String("up", "", "Path to up-script") + downPath = flag.String("down", "", "Path to down-script") + stats = flag.String("stats", "", "Enable stats retrieving on host:port") + proxyAddr = flag.String("proxy", "", "Use HTTP proxy on host:port") + proxyAuth = flag.String("proxy-auth", "", "user:password Basic proxy auth") + mtu = flag.Int("mtu", 1452, "MTU for outgoing packets") + timeoutP = flag.Int("timeout", 60, "Timeout seconds") + noisy = flag.Bool("noise", false, "Enable noise appending") + cpr = flag.Int("cpr", 0, "Enable constant KiB/sec out traffic rate") + egdPath = flag.String("egd", "", "Optional path to EGD socket") conf *govpn.PeerConf tap *govpn.TAP @@ -63,26 +63,25 @@ log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile) govpn.MTU = *mtu - id, err := govpn.IDDecode(*IDRaw) - if err != nil { - log.Fatalln(err) - } - if *egdPath != "" { log.Println("Using", *egdPath, "EGD") govpn.EGDInit(*egdPath) } - pub, priv := govpn.NewVerifier(id, govpn.StringFromFile(*keyPath)) + verifier, err := govpn.VerifierFromString(*verifierRaw) + if err != nil { + log.Fatalln(err) + } + priv := verifier.PasswordApply(govpn.StringFromFile(*keyPath)) conf = &govpn.PeerConf{ - Id: id, - Timeout: time.Second * time.Duration(timeout), - Noise: *noisy, - CPR: *cpr, - DSAPub: pub, - DSAPriv: priv, + Id: verifier.Id, + Timeout: time.Second * time.Duration(timeout), + Noise: *noisy, + CPR: *cpr, + Verifier: verifier, + DSAPriv: priv, } - idsCache = govpn.NewCipherCache([]govpn.PeerId{*id}) + idsCache = govpn.NewCipherCache([]govpn.PeerId{*verifier.Id}) log.Println(govpn.VersionGet()) tap, err = govpn.TAPListen(*ifaceName) @@ -108,6 +107,9 @@ for { timeouted := make(chan struct{}) rehandshaking := make(chan struct{}) termination := make(chan struct{}) + if *proxyAddr != "" { + *proto = "tcp" + } switch *proto { case "udp": go startUDP(timeouted, rehandshaking, termination) diff --git a/src/govpn/cmd/govpn-server/common.go b/src/govpn/cmd/govpn-server/common.go index 4692e52b4c297270a61f30f81f5213cbeef00827..f2cc0d324096cb0a0e6037af401624701d36557b 100644 --- a/src/govpn/cmd/govpn-server/common.go +++ b/src/govpn/cmd/govpn-server/common.go @@ -1,3 +1,21 @@ +/* +GoVPN -- simple secure free software virtual private network daemon +Copyright (C) 2014-2015 Sergey Matveev + +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, either version 3 of the License, or +(at your option) any later version. + +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 . +*/ + package main import ( diff --git a/src/govpn/cmd/govpn-server/conf.go b/src/govpn/cmd/govpn-server/conf.go index 4136fabbdec4a2472af4ee80405d625344750f49..76d56cd8ae9f5185e954ff2dbc729b28a40c15f0 100644 --- a/src/govpn/cmd/govpn-server/conf.go +++ b/src/govpn/cmd/govpn-server/conf.go @@ -19,13 +19,10 @@ package main import ( - "encoding/hex" "encoding/json" "io/ioutil" "log" "time" - - "github.com/agl/ed25519" "govpn" ) @@ -51,35 +48,25 @@ log.Fatalln("Unable to parse configuration:", err) } confs := make(map[govpn.PeerId]*govpn.PeerConf, len(*confsRaw)) - for peerIdRaw, pc := range *confsRaw { - peerId, err := govpn.IDDecode(peerIdRaw) + for name, pc := range *confsRaw { + verifier, err := govpn.VerifierFromString(pc.VerifierRaw) if err != nil { - log.Fatalln("Invalid peer ID:", peerIdRaw, err) + log.Fatalln("Unable to decode the key:", err.Error(), pc.VerifierRaw) } conf := govpn.PeerConf{ - Id: peerId, - Name: pc.Name, - Up: pc.Up, - Down: pc.Down, - Noise: pc.Noise, - CPR: pc.CPR, + Verifier: verifier, + Id: verifier.Id, + Name: name, + Up: pc.Up, + Down: pc.Down, + Noise: pc.Noise, + CPR: pc.CPR, } if pc.TimeoutInt <= 0 { pc.TimeoutInt = govpn.TimeoutDefault } conf.Timeout = time.Second * time.Duration(pc.TimeoutInt) - - if len(pc.Verifier) != ed25519.PublicKeySize*2 { - log.Fatalln("Verifier must be 64 hex characters long") - } - keyDecoded, err := hex.DecodeString(string(pc.Verifier)) - if err != nil { - log.Fatalln("Unable to decode the key:", err.Error(), pc.Verifier) - } - conf.DSAPub = new([ed25519.PublicKeySize]byte) - copy(conf.DSAPub[:], keyDecoded) - - confs[*peerId] = &conf + confs[*verifier.Id] = &conf } return confs } diff --git a/src/govpn/cmd/govpn-verifier/main.go b/src/govpn/cmd/govpn-verifier/main.go index ede2de7438a370c43f770120a818ed454a453b71..1757e1e183976a6e16b36dbb3c6cf21373689b0e 100644 --- a/src/govpn/cmd/govpn-verifier/main.go +++ b/src/govpn/cmd/govpn-verifier/main.go @@ -20,8 +20,8 @@ // Verifier generator and validator for GoVPN VPN daemon. package main import ( + "crypto/rand" "crypto/subtle" - "encoding/hex" "flag" "fmt" "log" @@ -30,25 +30,32 @@ "govpn" ) var ( - IDRaw = flag.String("id", "", "Client identification") - keyPath = flag.String("key", "", "Path to passphrase file") - verifierPath = flag.String("verifier", "", "Optional path to verifier") + 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") ) func main() { flag.Parse() - id, err := govpn.IDDecode(*IDRaw) + if *verifier == "" { + id := new([govpn.IDSize]byte) + if _, err := rand.Read(id[:]); err != nil { + log.Fatalln(err) + } + pid := govpn.PeerId(*id) + v := govpn.VerifierNew(*mOpt, *tOpt, *pOpt, &pid) + v.PasswordApply(govpn.StringFromFile(*keyPath)) + fmt.Println(v.LongForm()) + fmt.Println(v.ShortForm()) + return + } + v, err := govpn.VerifierFromString(*verifier) if err != nil { - log.Fatalln(err) + log.Fatalln("Can not decode verifier", err) } - pub, _ := govpn.NewVerifier(id, govpn.StringFromFile(*keyPath)) - if *verifierPath == "" { - fmt.Println(hex.EncodeToString(pub[:])) - } else { - verifier, err := hex.DecodeString(govpn.StringFromFile(*verifierPath)) - if err != nil { - log.Fatalln("Can not decode verifier:", err) - } - fmt.Println(subtle.ConstantTimeCompare(verifier[:], pub[:]) == 1) - } + pub := *v.Pub + v.PasswordApply(govpn.StringFromFile(*keyPath)) + fmt.Println(subtle.ConstantTimeCompare(v.Pub[:], pub[:]) == 1) } diff --git a/src/govpn/conf.go b/src/govpn/conf.go index 0eff5909fa75c7cc6f243acde2e42a0523e3fd01..d9e74813a058a56dedb05bbd065245aef47ec36c 100644 --- a/src/govpn/conf.go +++ b/src/govpn/conf.go @@ -25,18 +25,18 @@ "github.com/agl/ed25519" ) type PeerConf struct { - Id *PeerId `json:"-"` - Name string `json:"name"` - Up string `json:"up"` - Down string `json:"down"` - TimeoutInt int `json:"timeout"` - Timeout time.Duration `json:"-"` - Noise bool `json:"noise"` - CPR int `json:"cpr"` - Verifier string `json:"verifier"` + Id *PeerId `json:"-"` + Name string `json:"name"` + Up string `json:"up"` + Down string `json:"down"` + TimeoutInt int `json:"timeout"` + Timeout time.Duration `json:"-"` + Noise bool `json:"noise"` + CPR int `json:"cpr"` + VerifierRaw string `json:"verifier"` // This is passphrase verifier - DSAPub *[ed25519.PublicKeySize]byte `json:"-"` + Verifier *Verifier // This field exists only on client's side DSAPriv *[ed25519.PrivateKeySize]byte `json:"-"` } diff --git a/src/govpn/handshake.go b/src/govpn/handshake.go index 0aa65bd624e4e9366db2275b3acff5d6fc04ad1d..f0a8e65202130cf7302603ea21a08fa9353fa8f3 100644 --- a/src/govpn/handshake.go +++ b/src/govpn/handshake.go @@ -142,7 +142,7 @@ LastPing: time.Now(), Conf: conf, } state.dsaPubH = new([ed25519.PublicKeySize]byte) - copy(state.dsaPubH[:], state.Conf.DSAPub[:]) + copy(state.dsaPubH[:], state.Conf.Verifier.Pub[:]) HApply(state.dsaPubH) return &state } @@ -191,7 +191,7 @@ // will be created and used as a transport. If no mutually // authenticated Peer is ready, then return nil. func (h *Handshake) Server(data []byte) *Peer { // R + ENC(H(DSAPub), R, El(CDHPub)) + IDtag - if h.rNonce == nil { + if h.rNonce == nil && len(data) >= 48 { // Generate DH keypair var dhPubRepr *[32]byte h.dhPriv, dhPubRepr = dhKeypairGen() @@ -237,7 +237,7 @@ h.conn.Write(append(encPub, append(encRs, idTag(h.Conf.Id, encPub)...)...)) h.LastPing = time.Now() } else // ENC(K, R+1, RS + RC + SC + Sign(DSAPriv, K)) + IDtag - if h.rClient == nil { + if h.rClient == nil && len(data) >= 120 { // Decrypted Rs compare rServer dec := make([]byte, RSize+RSize+SSize+ed25519.SignatureSize) salsa20.XORKeyStream( @@ -252,7 +252,7 @@ return nil } sign := new([ed25519.SignatureSize]byte) copy(sign[:], dec[RSize+RSize+SSize:]) - if !ed25519.Verify(h.Conf.DSAPub, h.key[:], sign) { + if !ed25519.Verify(h.Conf.Verifier.Pub, h.key[:], sign) { log.Println("Invalid signature from", h.addr) return nil } @@ -290,7 +290,7 @@ // will be created and used as a transport. If no mutually // authenticated Peer is ready, then return nil. func (h *Handshake) Client(data []byte) *Peer { // ENC(H(DSAPub), R+1, El(SDHPub)) + ENC(K, R, RS + SS) + IDtag - if h.rServer == nil && h.key == nil { + if h.rServer == nil && h.key == nil && len(data) >= 80 { // Decrypt remote public key and compute shared key sDHRepr := new([32]byte) salsa20.XORKeyStream(sDHRepr[:], data[:32], h.rNonceNext(1), h.dsaPubH) @@ -334,7 +334,7 @@ h.conn.Write(append(enc, idTag(h.Conf.Id, enc)...)) h.LastPing = time.Now() } else // ENC(K, R+2, RC) + IDtag - if h.key != nil { + if h.key != nil && len(data) >= 16 { // Decrypt rClient dec := make([]byte, RSize) salsa20.XORKeyStream(dec, data[:RSize], h.rNonceNext(2), h.key) diff --git a/src/govpn/identify.go b/src/govpn/identify.go index a0b7d22f65de59d0840de73f8b4efbb8be6626ca..54c87d31e0117a300bab5a6b21fc4edd5aec1f01 100644 --- a/src/govpn/identify.go +++ b/src/govpn/identify.go @@ -21,7 +21,6 @@ import ( "crypto/subtle" "encoding/hex" - "errors" "log" "sync" @@ -36,22 +35,6 @@ type PeerId [IDSize]byte func (id PeerId) String() string { return hex.EncodeToString(id[:]) -} - -// Decode identification string. -// It must be 32 hexadecimal characters long. -func IDDecode(raw string) (*PeerId, error) { - if len(raw) != IDSize*2 { - return nil, errors.New("ID must be 32 characters long") - } - idDecoded, err := hex.DecodeString(raw) - if err != nil { - return nil, errors.New("ID must contain hexadecimal characters only") - } - idP := new([IDSize]byte) - copy(idP[:], idDecoded) - id := PeerId(*idP) - return &id, nil } type CipherCache struct { diff --git a/src/govpn/peer.go b/src/govpn/peer.go index 1076e74bea38300f1e0531e3e9ebf52f94e58340..45b5dd7d01ac47022220387e90c3b040215b1e3f 100644 --- a/src/govpn/peer.go +++ b/src/govpn/peer.go @@ -1,3 +1,21 @@ +/* +GoVPN -- simple secure free software virtual private network daemon +Copyright (C) 2014-2015 Sergey Matveev + +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, either version 3 of the License, or +(at your option) any later version. + +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 . +*/ + package govpn import ( @@ -242,6 +260,9 @@ p.BusyT.Unlock() } func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool { + if len(data) < MinPktLength { + return false + } p.BusyR.Lock() for i := 0; i < SSize; i++ { p.bufR[i] = byte(0) @@ -308,6 +329,9 @@ if p.pktSizeR == 0 { p.HeartbeatRecv++ p.BusyR.Unlock() return true + } + if int(p.pktSizeR) > len(data)-MinPktLength { + return false } p.BytesPayloadIn += int64(p.pktSizeR) tap.Write(p.bufR[S20BS+PktSizeSize : S20BS+PktSizeSize+p.pktSizeR]) diff --git a/src/govpn/peer_test.go b/src/govpn/peer_test.go index 9bad8c6960a792c1ca41b766289188aa977dc1a0..c9c26475e8d7bf58d1ef7468ed1a5b1c8d273f1a 100644 --- a/src/govpn/peer_test.go +++ b/src/govpn/peer_test.go @@ -26,12 +26,13 @@ } func init() { MTU = 1500 - peerId, _ = IDDecode("ffffffffffffffffffffffffffffffff") + id := new([IDSize]byte) + peerId := PeerId(*id) conf = &PeerConf{ - Id: peerId, - Timeout: time.Second * time.Duration(TimeoutDefault), - NoiseEnable: false, - CPR: 0, + Id: &peerId, + Timeout: time.Second * time.Duration(TimeoutDefault), + Noise: false, + CPR: 0, } peer = newPeer(true, "foo", Dummy{&ciphertext}, conf, new([SSize]byte)) plaintext = make([]byte, 789) diff --git a/src/govpn/stats.go b/src/govpn/stats.go index 8d39e7a84b2152ca2926b243632ef3dfd882294f..7cdb3b7298d74f3742e587f2560f5db9cebac0f2 100644 --- a/src/govpn/stats.go +++ b/src/govpn/stats.go @@ -1,3 +1,21 @@ +/* +GoVPN -- simple secure free software virtual private network daemon +Copyright (C) 2014-2015 Sergey Matveev + +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, either version 3 of the License, or +(at your option) any later version. + +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 . +*/ + package govpn import ( diff --git a/src/govpn/verifier.go b/src/govpn/verifier.go index 895404792cfd9edcdff67e28f43528d724adb026..fe0965348d03f7ad5bc04e11ada533d621c3c1c0 100644 --- a/src/govpn/verifier.go +++ b/src/govpn/verifier.go @@ -20,35 +20,101 @@ package govpn import ( "bytes" - "crypto/sha512" + "encoding/base64" + "errors" + "fmt" "io/ioutil" "log" "strings" "github.com/agl/ed25519" - "golang.org/x/crypto/pbkdf2" + "github.com/magical/argon2" ) const ( - PBKDF2Iters = 1 << 16 + DefaultM = 1 << 12 + DefaultT = 1 << 7 + DefaultP = 1 ) -// Create verifier from supplied password for given PeerId. -func NewVerifier(id *PeerId, password string) (*[ed25519.PublicKeySize]byte, *[ed25519.PrivateKeySize]byte) { - r := pbkdf2.Key( - []byte(password), - id[:], - PBKDF2Iters, - ed25519.PrivateKeySize, - sha512.New, - ) +type Verifier struct { + M int + T int + P int + 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} +} + +// 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) + } defer sliceZero(r) src := bytes.NewBuffer(r) - pub, priv, err := ed25519.GenerateKey(src) + pub, prv, err := ed25519.GenerateKey(src) if err != nil { log.Fatalln("Unable to generate Ed25519 keypair", err) } - return pub, priv + v.Pub = pub + return prv +} + +// Parse 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" { + 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) + if n != 3 || err != nil { + return nil, errors.New("Invalid verifier parameters") + } + salt, err := base64.RawStdEncoding.DecodeString(s[3]) + if err != nil { + return nil, err + } + v := Verifier{M: m, 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 err != nil { + return nil, err + } + v.Pub = new([ed25519.PublicKeySize]byte) + copy(v.Pub[:], pub) + } + return &v, nil +} + +// Short verifier string form -- it is useful for the client. +// 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[:]), + ) +} + +// Long verifier string form -- it is useful for the server. +// Includes public key. +func (v *Verifier) LongForm() string { + return fmt.Sprintf( + "%s$%s", v.ShortForm(), + base64.RawStdEncoding.EncodeToString(v.Pub[:]), + ) } // Read string from the file, trimming newline. diff --git a/utils/makedist.sh b/utils/makedist.sh index 10f18d9cdeff86020062ab50d80c45c35552dc12..89bd8c8dd9b7b11c276a554b406036bac8ab6093 100755 --- a/utils/makedist.sh +++ b/utils/makedist.sh @@ -8,7 +8,7 @@ release=$1 [ -n "$release" ] git clone . $tmp/govpn-$release -for repo in src/github.com/bigeagle/water src/github.com/agl/ed25519 src/golang.org/x/crypto; do +for repo in src/github.com/bigeagle/water src/github.com/agl/ed25519 src/github.com/magical/argon2 src/github.com/dchest/blake2b src/golang.org/x/crypto; do git clone $repo $tmp/govpn-$release/$repo done cd $tmp/govpn-$release @@ -133,6 +133,7 @@ ----------------8<-----------------8<-----------------8<---------------- Домашняя страница GoVPN: http://govpn.info -> http://www.cypherpunks.ru/govpn/ +Коротко о демоне: http://www.cypherpunks.ru/govpn/About-RU.html также доступна как скрытый сервис Tor: http://vabu56j2ep2rwv3b.onion/govpn/ Исходный код и его подпись для этой версии находится здесь: diff --git a/utils/newclient.sh b/utils/newclient.sh index 9e1cb3578faaf71f131245cf2c128b2df3d07c06..e0d8c855b8fad14f1b3c8538242d0eb741c5b581 100755 --- a/utils/newclient.sh +++ b/utils/newclient.sh @@ -3,8 +3,8 @@ [ -n "$1" ] || { cat < EOF @@ -12,30 +12,29 @@ exit 1 } username=$1 -peerid=$(dd if=/dev/urandom bs=16 count=1 2>/dev/null | hexdump -ve '"%02x"') -[ $(echo -n $peerid | wc -c) = 32 ] || peerid=0"$peerid" umask 077 passphrase=$(mktemp) $(dirname $0)/storekey.sh $passphrase -verifier=$(govpn-verifier -id $peerid -key $passphrase) +verifier=$(govpn-verifier -key $passphrase) rm -f $passphrase +verifierS=$(echo $verifier | sed 's/^\(.*\) .*$/\1/') +verifierC=$(echo $verifier | sed 's/^.* \(.*\)$/\1/') echo cat <