[submodule "src/golang.org/x/crypto"]
path = src/golang.org/x/crypto
url = https://go.googlesource.com/crypto
-[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
govpn.info: *.texi handshake.utxt
$(MAKEINFO) -o govpn.info index.texi
+CSS != cat style.css
+
govpn.html: *.texi handshake.utxt
rm -f govpn.html/*.html
$(MAKEINFO) --html \
- --css-include=style.css \
+ --set-customization-variable CSS_LINES='$(CSS)' \
--set-customization-variable SHOW_TITLE=0 \
+ --set-customization-variable USE_ACCESSKEY=0 \
--set-customization-variable DATE_IN_HEADER=1 \
+ --set-customization-variable TOP_NODE_UP_URL=index.html \
+ --set-customization-variable CLOSE_QUOTE_SYMBOL=\" \
+ --set-customization-variable OPEN_QUOTE_SYMBOL=\" \
-o govpn.html index.texi
cp -r .well-known govpn.html/
идентификатор}, невидимый третьим лицам (они анонимны для них).
@item
-Использует @url{https://ru.wikipedia.org/wiki/TUN/TAP, TAP} низлежащие
+Использует @url{https://ru.wikipedia.org/wiki/TUN/TAP, TUN/TAP} низлежащие
сетевые интерфейсы.
@item
for third-parties (they are anonymous).
@item
-Uses @url{https://en.wikipedia.org/wiki/TAP_(network_driver), TAP}
+Uses @url{https://en.wikipedia.org/wiki/TAP_(network_driver), TUN/TAP}
underlying network interfaces.
@item
@table @option
@item -mtu
-Expected TAP interface @ref{MTU}.
+Expected TUN/TAP interface @ref{MTU}.
@item -proto
@ref{Network, Network protocol} to use. Can be either @emph{udp}
Address (@code{host:port} format) of remote server we need to connect to.
@item -iface
-TAP interface name.
+TUN/TAP interface name.
@item -verifier
Our client's @ref{Verifier}.
@table @asis
@item Data encryption
- @url{http://cr.yp.to/snuffle.html, Salsa20}.
+ @url{https://cr.yp.to/chacha.html, ChaCha20}.
@item Message authentication
- @url{http://cr.yp.to/mac.html, Poly1305}.
+ @url{https://cr.yp.to/mac.html, Poly1305}.
@item Nonce and identity obfuscation
@url{https://blake2.net/, BLAKE2b-MAC}.
@item Password authenticated key agreement
- DH-A-EKE powered by @url{http://cr.yp.to/ecdh.html, Curve25519}
- and @url{http://ed25519.cr.yp.to/, Ed25519}.
+ DH-A-EKE powered by @url{https://cr.yp.to/ecdh.html, Curve25519}
+ and @url{https://ed25519.cr.yp.to/, Ed25519}.
@item DH elliptic-curve point encoding for public keys
- @url{http://elligator.cr.yp.to/, Elligator}.
+ @url{https://elligator.cr.yp.to/, Elligator}.
@item Verifier password hashing algorithm
@url{https://crypto.stanford.edu/balloon/, Balloon hashing} based
on BLAKE2b-256.
@url{http://theory.lcs.mit.edu/~cis/pubs/rivest/fusion.ps,
All-Or-Nothing-Transformed} (based on
@url{http://cseweb.ucsd.edu/~mihir/papers/oaep.html, OAEP} using
- Salsa20 with BLAKE2b-256 based
+ ChaCha20 with BLAKE2b-256 based
@url{http://crypto.stanford.edu/~dabo/abstracts/saep.html, SAEP+}
checksums) data with 128-bits of feeded random.
@item Packet overhead
(or use @url{https://sourceforge.net/projects/govpn/files/, Sourceforge mirror}).
Do not forget to check tarball @ref{Integrity, integrity}.
-@multitable {XXXXX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
+@multitable {XXXXX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
@headitem Version @tab Size @tab Tarball @tab SHA256 checksum
+@item @ref{Release 6.0, 6.0} @tab 310 KiB
+@tab @url{download/govpn-6.0.tar.xz, link} @url{download/govpn-6.0.tar.xz.sig, sign}
+@tab @code{3ACAE3B9 884F3260 38FCA9CE 6A309DF6 71BE6386 1FB2058B C79AE7DC 2A1A1811}
+
@item @ref{Release 5.10, 5.10} @tab 316 KiB
@tab @url{download/govpn-5.10.tar.xz, link} @url{download/govpn-5.10.tar.xz.sig, sign}
@tab @code{BC624265 CFCDA8CE 1C1BBF9D 016683C5 0EC6CBA5 AECCF33D 93FCA4E5 D52098BD}
authentication).
GoVPN provides special encryptionless mode of operation. In this mode it
-replaces Salsa20 function used for confidentiality with rather
+replaces ChaCha20 function used for confidentiality with rather
well-known @url{http://people.csail.mit.edu/rivest/chaffing-980701.txt,
Chaffing-and-Winnowing} (CnW) technology. This is rather traffic and
resource hungry algorithm, so we use it after
@item You want to create virtual encrypted and authenticated 172.16.0/24
network and use it as a default transport.
@item Assume that outgoing GoVPN packets can be fragmented, so we do not
-bother configuring MTU of TAP interfaces. For better performance just
+bother configuring MTU of TUN/TAP interfaces. For better performance just
lower it and check that no fragmentation of outgoing UDP packets occurs.
@end itemize
Alice:
up: /path/to/up.sh
- iface: or TAP interface name
+ iface: or TUN/TAP interface name
verifier: $balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
@end verbatim
@headitem Library @tab Platform @tab Licence
@item @code{github.com/agl/ed25519} @tab All @tab BSD 3-Clause
@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{golang.org/x/crypto} @tab All @tab BSD 3-Clause
@end multitable
@item
@verbatim
-% gpg --auto-key-locate pka --locate-keys releases at govpn dot info
+% gpg --keyserver hkp://keys.gnupg.net/ --recv-keys 0xF2F59045FFE2F4A1
% gpg --auto-key-locate dane --locate-keys releases at govpn dot info
% gpg --auto-key-locate wkd --locate-keys releases at govpn dot info
+% gpg --auto-key-locate pka --locate-keys releases at govpn dot info
@end verbatim
@item
@subsection Maximum Transmission Unit
MTU option tells what maximum transmission unit is expected to get from
-TAP interface. It is per-user configuration. Incoming packets of bigger
+TUN/TAP interface. It is per-user configuration. Incoming packets of bigger
sizes (including the padding byte) will be ignored. If either
@ref{Noise, noise}, @ref{Encless, encryptionless mode} or @ref{CPR} are
enabled, then all outgoing packets are filled up to that MTU value.
@node Новости
@section Новости
+@node Релиз 7.0
+@subsection Релиз 7.0
+@itemize
+@item (X)Salsa20 заменён на ChaCha20. Теоретически он должен быть
+быстрее и более безопасным. Это несовместимое с предыдущими версиями
+клиента изменение!
+@item Возможность использовать TUN-интерфейсы под GNU/Linux. FreeBSD без
+изменений уже поддерживала эту возможность.
+@end itemize
+
@node Релиз 6.0
@subsection Релиз 6.0
@itemize
See also this page @ref{Новости, on russian}.
+@node Release 7.0
+@section Release 7.0
+@itemize
+@item (X)Salsa20 is replaced with ChaCha20. Theoretically it should be
+faster and more secure. Previous versions are not compatible with it!
+@item Ability to use TUN-interfaces under GNU/Linux. FreeBSD has already
+supported them without any modifications.
+@end itemize
+
@node Release 6.0
@section Release 6.0
@itemize
Remote peer's address. In client mode it is server's address.
@item GOVPN_IFACE
-TAP interface name. In server mode this can be empty: that means that
+TUN/TAP interface name. In server mode this can be empty: that means that
script must output its name as the first line to stdout.
@end table
@verbatim
stargrave: <-- Peer human readable name
- iface: tap10 <-- OPTIONAL TAP interface name
+ iface: tap10 <-- OPTIONAL TUN/TAP interface name
mtu: 1515 <-- OPTIONAL overriden MTU
up: ./stargrave-up.sh <-- OPTIONAL up-script
down: ./stargrave-down.sh <-- OPTIONAL down-script
At least one of either @code{iface} or @code{up} must be specified. If
you specify @code{iface}, then it will be forcefully used to determine
-what TAP interface will be used. If it is not specified, then
+what TUN/TAP interface will be used. If it is not specified, then
up-@ref{Scripts, script} must output interface's name to stdout
(first output line).
Alice:
up: /path/to/up.sh
- iface: or TAP interface name
+ iface: or TUN/TAP interface name
verifier: $balloon$s=32768,t=16,p=2$bwR5VjeCYIQaa8SeaI3rqg$KCNIqfS4DGsBTtVytamAzcISgrlEWvNxan1UfBrFu10
@end verbatim
@item @code{cypherpunks.ru/govpn} @tab @url{https://github.com/stargrave/govpn.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/go-yaml/yaml} @tab @url{git://git.cypherpunks.ru/yaml.git}
@item @code{golang.org/x/crypto} @tab @url{git://git.cypherpunks.ru/crypto.git}
@end multitable
+<style type="text/css"><!--
body {
margin: auto;
max-width: 800px;
background-color: #AEBECE;
}
-
-h1, h2, h3, h4 {
- text-align: center;
-}
-
-h1, h2, h3, h4, strong {
- color: #900090;
-}
-
-pre {
- background-color: #CCCCCC;
-}
+h1, h2, h3, h4 { text-align: center }
+h1, h2, h3, h4, strong { color: #900090 }
+pre { background-color: #CCCCCC }
+--></style>
If there were no packets at all during fourth part of timeout, then
special heartbeat packet is sent. So VPN connection should be alive all
-the time, even if there is no traffic in corresponding TAP interfaces.
+the time, even if there is no traffic in corresponding TUN/TAP interfaces.
@strong{Beware}: this consumes traffic.
Stale peers and handshake states are cleaned up every timeout period.
@section Transport protocol
@verbatim
- NONCE = 64bit(MAC(MAC_KEY, SERIAL))
+ NONCE = 64bit(ZEROS) || 64bit(MAC(MAC_KEY, SERIAL))
PAYLOAD = DATA || PAD [|| ZEROS]
CIPHERTEXT = ENCRYPT(KEY, NONCE, PAYLOAD)
TAG = AUTH(AUTH_KEY, CIPHERTEXT || NONCE)
client (to server) messages, evens for server (to client) messages.
@code{MAC} is BLAKE2b-MAC used to obfuscate @code{SERIAL}. MAC's key
-@code{MAC_KEY} is the first 256-bit of Salsa20's output with established
+@code{MAC_KEY} is the first 256-bit of ChaCha20's output with established
common key and zero nonce (message nonces start from 1).
@verbatim
MAC_KEY = 256bit(ENCRYPT(KEY, 0))
@end verbatim
-@code{ENCRYPT} is Salsa20 stream cipher, with established session
+@code{ENCRYPT} is ChaCha20 stream cipher, with established session
@code{KEY} and obfuscated @code{SERIAL} used as a nonce. 512 bit of
-Salsa20's output is ignored and only remaining is XORed with ther data,
+ChaCha20's output is ignored and only remaining is XORed with ther data,
encrypting it.
@code{DATA} is padded using ISO/IEC 7816-4 format (@code{PAD} (0x80
conceal payload packet length.
@code{AUTH} is Poly1305 authentication function. First 256 bits of
-Salsa20's output are used as a one-time key for @code{AUTH}.
+ChaCha20's output are used as a one-time key for @code{AUTH}.
@verbatim
AUTH_KEY = 256bit(ENCRYPT(KEY, NONCE))
@ref{Contacts, contacts}.
GoVPN is split into two pieces: @ref{Client} and @ref{Server}. Each of
-them work on top of @ref{Network, UDP/TCP} and TAP virtual network
+them work on top of @ref{Network, UDP/TCP} and TUN/TAP virtual network
interfaces. GoVPN is just a tunnelling of Ethernet frames, nothing less,
nothing more. All you IP-related network management is not touched by
VPN at all. You can automate it using up and down shell scripts.
--- /dev/null
+golang.org/x/crypto/chacha20poly1305/internal/chacha20
\ No newline at end of file
// package PKG:
//
// PKG = P1 || P2
-// P1 = Salsa20(key=r, nonce=0x00, 0x00) XOR (M || BLAKE2b(r || M))
+// P1 = ChaCha20(key=r, nonce=0x00, 0x00) XOR (M || BLAKE2b(r || M))
// P2 = BLAKE2b(P1) XOR r
package aont
"crypto/subtle"
"errors"
- "github.com/dchest/blake2b"
- "golang.org/x/crypto/salsa20"
+ "chacha20"
+ "golang.org/x/crypto/blake2b"
)
const (
)
var (
- dummyNonce []byte = make([]byte, 8)
+ dummyNonce *[16]byte = new([16]byte)
)
// Encode the data, produce AONT package. Data size will be larger than
func Encode(r *[RSize]byte, in []byte) ([]byte, error) {
out := make([]byte, len(in)+HSize+RSize)
copy(out, in)
- h := blake2b.New256()
+ h, err := blake2b.New256(nil)
+ if err != nil {
+ return nil, err
+ }
h.Write(r[:])
h.Write(in)
copy(out[len(in):], h.Sum(nil))
- salsaKey := new([32]byte)
- copy(salsaKey[:], r[:])
- salsa20.XORKeyStream(out, out, dummyNonce, salsaKey)
+ chachaKey := new([32]byte)
+ copy(chachaKey[:], r[:])
+ chacha20.XORKeyStream(out, out, dummyNonce, chachaKey)
h.Reset()
h.Write(out[:len(in)+32])
for i, b := range h.Sum(nil)[:RSize] {
if len(in) < HSize+RSize {
return nil, errors.New("Too small input buffer")
}
- h := blake2b.New256()
+ h, err := blake2b.New256(nil)
+ if err != nil {
+ return nil, err
+ }
h.Write(in[:len(in)-RSize])
- salsaKey := new([32]byte)
+ chachaKey := new([32]byte)
for i, b := range h.Sum(nil)[:RSize] {
- salsaKey[i] = b ^ in[len(in)-RSize+i]
+ chachaKey[i] = b ^ in[len(in)-RSize+i]
}
h.Reset()
- h.Write(salsaKey[:RSize])
+ h.Write(chachaKey[:RSize])
out := make([]byte, len(in)-RSize)
- salsa20.XORKeyStream(out, in[:len(in)-RSize], dummyNonce, salsaKey)
+ chacha20.XORKeyStream(out, in[:len(in)-RSize], dummyNonce, chachaKey)
h.Write(out[:len(out)-HSize])
if subtle.ConstantTimeCompare(h.Sum(nil), out[len(out)-HSize:]) != 1 {
return nil, errors.New("Invalid checksum")
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")
+ ifaceName = flag.String("iface", "tap0", "TUN/TAP network interface")
verifierRaw = flag.String("verifier", "", "Verifier")
keyPath = flag.String("key", "", "Path to passphrase file")
upPath = flag.String("up", "", "Path to up-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", govpn.MTUDefault, "MTU of TAP interface")
+ mtu = flag.Int("mtu", govpn.MTUDefault, "MTU of TUN/TAP interface")
timeoutP = flag.Int("timeout", 60, "Timeout seconds")
timeSync = flag.Int("timesync", 0, "Time synchronization requirement")
noreconnect = flag.Bool("noreconnect", false, "Disable reconnection after timeout")
tap, err = govpn.TAPListen(*ifaceName, *mtu)
if err != nil {
- log.Fatalln("Can not listen on TAP interface:", err)
+ log.Fatalln("Can not listen on TUN/TAP interface:", err)
}
if *stats != "" {
// one is over "0". If bit value is 1, then first is taken over "0" and
// second is over "1".
//
-// Poly1305 uses 256-bit one-time key. We generate it using XSalsa20 for
+// Poly1305 uses 256-bit one-time key. We generate it using ChaCha20 for
// for the whole byte at once (16 MACs).
//
-// MACKey1, MACKey2, ... = XSalsa20(authKey, nonce, 0x00...)
-// nonce = prefix || 0x00... || big endian byte number
+// MACKey1, MACKey2, ... = ChaCha20(authKey, nonce, 0x00...)
+// nonce = prefix || big endian byte number
package cnw
import (
"encoding/binary"
"errors"
+ "chacha20"
"golang.org/x/crypto/poly1305"
- "golang.org/x/crypto/salsa20"
)
const (
func Chaff(authKey *[32]byte, noncePrfx, in []byte) []byte {
out := make([]byte, len(in)*EnlargeFactor)
keys := make([]byte, 8*64)
- nonce := make([]byte, 24)
+ nonce := new([16]byte)
copy(nonce[:8], noncePrfx)
var i int
var v byte
tag := new([16]byte)
macKey := new([32]byte)
for n, b := range in {
- binary.BigEndian.PutUint64(nonce[16:], uint64(n))
- salsa20.XORKeyStream(keys, keys, nonce, authKey)
+ binary.BigEndian.PutUint64(nonce[8:], uint64(n))
+ chacha20.XORKeyStream(keys, keys, nonce, authKey)
for i = 0; i < 8; i++ {
v = (b >> uint8(i)) & 1
copy(macKey[:], keys[64*i:64*i+32])
}
out := make([]byte, len(in)/EnlargeFactor)
keys := make([]byte, 8*64)
- nonce := make([]byte, 24)
+ nonce := new([16]byte)
copy(nonce[:8], noncePrfx)
var i int
var v byte
var is11 bool
var is10 bool
for n := 0; n < len(out); n++ {
- binary.BigEndian.PutUint64(nonce[16:], uint64(n))
- salsa20.XORKeyStream(keys, keys, nonce, authKey)
+ binary.BigEndian.PutUint64(nonce[8:], uint64(n))
+ chacha20.XORKeyStream(keys, keys, nonce, authKey)
v = 0
for i = 0; i < 8; i++ {
copy(macKey[:], keys[64*i:64*i+32])
// encryption nor steganography) over All-Or-Nothing-Transformed data.
// nonce is 64-bit nonce. Output data will be EnclessEnlargeSize larger.
// It also consumes 64-bits of entropy.
-func EnclessEncode(authKey *[32]byte, nonce, in []byte) ([]byte, error) {
+func EnclessEncode(authKey *[32]byte, nonce *[16]byte, in []byte) ([]byte, error) {
r := new([aont.RSize]byte)
var err error
if _, err = io.ReadFull(Rand, r[:]); err != nil {
return nil, err
}
out := append(
- cnw.Chaff(authKey, nonce, aonted[:aont.RSize]),
+ cnw.Chaff(authKey, nonce[8:], aonted[:aont.RSize]),
aonted[aont.RSize:]...,
)
SliceZero(aonted[:aont.RSize])
}
// Decode EnclessEncode-ed data.
-func EnclessDecode(authKey *[32]byte, nonce, in []byte) ([]byte, error) {
+func EnclessDecode(authKey *[32]byte, nonce *[16]byte, in []byte) ([]byte, error) {
var err error
winnowed, err := cnw.Winnow(
- authKey, nonce, in[:aont.RSize*cnw.EnlargeFactor],
+ authKey, nonce[8:], in[:aont.RSize*cnw.EnlargeFactor],
)
if err != nil {
return nil, err
}
func TestEnclessSymmetric(t *testing.T) {
- nonce := make([]byte, 8)
+ nonce := new([16]byte)
f := func(pktNum uint64, in []byte) bool {
- binary.BigEndian.PutUint64(nonce, pktNum)
+ binary.BigEndian.PutUint64(nonce[8:], pktNum)
encoded, err := EnclessEncode(testKey, nonce, in)
if err != nil {
return false
}
func BenchmarkEnclessEncode(b *testing.B) {
- nonce := make([]byte, 8)
+ nonce := new([16]byte)
data := make([]byte, 128)
- io.ReadFull(Rand, nonce)
+ io.ReadFull(Rand, nonce[8:])
io.ReadFull(Rand, data)
b.ResetTimer()
for i := 0; i < b.N; i++ {
}
func BenchmarkEnclessDecode(b *testing.B) {
- nonce := make([]byte, 8)
+ nonce := new([16]byte)
data := make([]byte, 128)
- io.ReadFull(Rand, nonce)
+ io.ReadFull(Rand, nonce[8:])
io.ReadFull(Rand, data)
encoded, _ := EnclessEncode(testKey, nonce, data)
b.ResetTimer()
"log"
"time"
+ "chacha20"
"github.com/agl/ed25519"
"github.com/agl/ed25519/extra25519"
- "github.com/dchest/blake2b"
+ "golang.org/x/crypto/blake2b"
"golang.org/x/crypto/curve25519"
- "golang.org/x/crypto/salsa20"
)
const (
Conf *PeerConf
dsaPubH *[ed25519.PublicKeySize]byte
key *[32]byte
- rNonce *[RSize]byte
+ rNonce *[16]byte
dhPriv *[32]byte // own private DH key
rServer *[RSize]byte // random string for authentication
rClient *[RSize]byte
}
}
-func (h *Handshake) rNonceNext(count uint64) []byte {
- nonce := make([]byte, RSize)
- nonceCurrent, _ := binary.Uvarint(h.rNonce[:])
- binary.PutUvarint(nonce, nonceCurrent+count)
+func (h *Handshake) rNonceNext(count uint64) *[16]byte {
+ nonce := new([16]byte)
+ nonceCurrent, _ := binary.Uvarint(h.rNonce[8:])
+ binary.PutUvarint(nonce[8:], nonceCurrent+count)
return nonce
}
enc := make([]byte, 8)
copy(enc, data)
AddTimeSync(timeSync, enc)
- mac := blake2b.NewMAC(8, id[:])
+ mac, err := blake2b.New256(id[:])
+ if err != nil {
+ panic(err)
+ }
mac.Write(enc)
mac.Sum(enc[:0])
return enc
var dhPubRepr *[32]byte
state.dhPriv, dhPubRepr = dhKeypairGen()
- state.rNonce = new([RSize]byte)
- if _, err := io.ReadFull(Rand, state.rNonce[:]); err != nil {
+ state.rNonce = new([16]byte)
+ if _, err := io.ReadFull(Rand, state.rNonce[8:]); err != nil {
log.Fatalln("Error reading random for nonce:", err)
}
var enc []byte
copy(enc, dhPubRepr[:])
if conf.Encless {
var err error
- enc, err = EnclessEncode(state.dsaPubH, state.rNonce[:], enc)
+ enc, err = EnclessEncode(state.dsaPubH, state.rNonce, enc)
if err != err {
panic(err)
}
} else {
- salsa20.XORKeyStream(enc, enc, state.rNonce[:], state.dsaPubH)
+ chacha20.XORKeyStream(enc, enc, state.rNonce, state.dsaPubH)
}
- data := append(state.rNonce[:], enc...)
- data = append(data, idTag(state.Conf.Id, state.Conf.TimeSync, state.rNonce[:])...)
+ data := append(state.rNonce[8:], enc...)
+ data = append(data, idTag(state.Conf.Id, state.Conf.TimeSync, state.rNonce[8:])...)
state.conn.Write(data)
return state
}
// R + ENC(H(DSAPub), R, El(CDHPub)) + IDtag
if h.rNonce == nil && ((!h.Conf.Encless && len(data) >= 48) ||
(h.Conf.Encless && len(data) == EnclessEnlargeSize+h.Conf.MTU)) {
- h.rNonce = new([RSize]byte)
- copy(h.rNonce[:], data[:RSize])
+ h.rNonce = new([16]byte)
+ copy(h.rNonce[8:], data[:RSize])
// Decrypt remote public key
cDHRepr := new([32]byte)
if h.Conf.Encless {
out, err := EnclessDecode(
h.dsaPubH,
- h.rNonce[:],
+ h.rNonce,
data[RSize:len(data)-8],
)
if err != nil {
}
copy(cDHRepr[:], out)
} else {
- salsa20.XORKeyStream(cDHRepr[:], data[RSize:RSize+32], h.rNonce[:], h.dsaPubH)
+ chacha20.XORKeyStream(cDHRepr[:], data[RSize:RSize+32], h.rNonce, h.dsaPubH)
}
// Generate DH keypair
}
} else {
encPub = make([]byte, 32)
- salsa20.XORKeyStream(encPub, dhPubRepr[:], h.rNonceNext(1), h.dsaPubH)
+ chacha20.XORKeyStream(encPub, dhPubRepr[:], h.rNonceNext(1), h.dsaPubH)
}
// Generate R* and encrypt them
}
copy(encRs, append(h.rServer[:], h.sServer[:]...))
if h.Conf.Encless {
- encRs, err = EnclessEncode(h.key, h.rNonce[:], encRs)
+ encRs, err = EnclessEncode(h.key, h.rNonce, encRs)
if err != nil {
panic(err)
}
} else {
- salsa20.XORKeyStream(encRs, encRs, h.rNonce[:], h.key)
+ chacha20.XORKeyStream(encRs, encRs, h.rNonce, h.key)
}
// Send that to client
dec = dec[:RSize+RSize+SSize+ed25519.SignatureSize]
} else {
dec = make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
- salsa20.XORKeyStream(
+ chacha20.XORKeyStream(
dec,
data[:RSize+RSize+SSize+ed25519.SignatureSize],
h.rNonceNext(1),
panic(err)
}
} else {
- salsa20.XORKeyStream(enc, enc, h.rNonceNext(2), h.key)
+ chacha20.XORKeyStream(enc, enc, h.rNonceNext(2), h.key)
}
h.conn.Write(append(enc, idTag(h.Conf.Id, h.Conf.TimeSync, enc)...))
}
copy(sDHRepr[:], tmp[:32])
} else {
- salsa20.XORKeyStream(sDHRepr[:], data[:32], h.rNonceNext(1), h.dsaPubH)
+ chacha20.XORKeyStream(sDHRepr[:], data[:32], h.rNonceNext(1), h.dsaPubH)
}
// Compute shared key
h.rServer = new([RSize]byte)
h.sServer = new([SSize]byte)
if h.Conf.Encless {
- tmp, err = EnclessDecode(
- h.key,
- h.rNonce[:],
- data[len(data)/2:len(data)-8],
- )
+ tmp, err = EnclessDecode(h.key, h.rNonce, data[len(data)/2:len(data)-8])
if err != nil {
log.Println("Unable to decode packet from", h.addr, err)
return nil
copy(h.sServer[:], tmp[RSize:RSize+SSize])
} else {
decRs := make([]byte, RSize+SSize)
- salsa20.XORKeyStream(decRs, data[SSize:SSize+RSize+SSize], h.rNonce[:], h.key)
+ chacha20.XORKeyStream(decRs, data[SSize:SSize+RSize+SSize], h.rNonce, h.key)
copy(h.rServer[:], decRs[:RSize])
copy(h.sServer[:], decRs[RSize:])
}
panic(err)
}
} else {
- salsa20.XORKeyStream(enc, enc, h.rNonceNext(1), h.key)
+ chacha20.XORKeyStream(enc, enc, h.rNonceNext(1), h.key)
}
// Send that to server
dec = dec[:RSize]
} else {
dec = make([]byte, RSize)
- salsa20.XORKeyStream(dec, data[:RSize], h.rNonceNext(2), h.key)
+ chacha20.XORKeyStream(dec, data[:RSize], h.rNonceNext(2), h.key)
}
if subtle.ConstantTimeCompare(dec, h.rClient[:]) != 1 {
log.Println("Invalid client's random number with", h.addr)
"sync"
"time"
- "github.com/dchest/blake2b"
+ "golang.org/x/crypto/blake2b"
)
const (
mc.cache[pid].ts = pc.TimeSync
} else {
log.Println("Adding key", pid)
+ mac, err := blake2b.New256(pid[:])
+ if err != nil {
+ panic(err)
+ }
mc.cache[pid] = &MACAndTimeSync{
- mac: blake2b.NewMAC(8, pid[:]),
+ mac: mac,
ts: pc.TimeSync,
}
}
"sync/atomic"
"time"
- "github.com/dchest/blake2b"
+ "chacha20"
+ "golang.org/x/crypto/blake2b"
"golang.org/x/crypto/poly1305"
- "golang.org/x/crypto/salsa20"
)
const (
NonceSize = 8
NonceBucketSize = 256
TagSize = poly1305.TagSize
- // S20BS is Salsa20's internal blocksize in bytes
+ // S20BS is ChaCha20's internal blocksize in bytes
S20BS = 64
// Maximal amount of bytes transfered with single key (4 GiB)
MaxBytesPerKey uint64 = 1 << 32
func newNonces(key *[32]byte, i uint64) chan *[NonceSize]byte {
macKey := make([]byte, 32)
- salsa20.XORKeyStream(macKey, make([]byte, 32), make([]byte, 8), key)
- mac := blake2b.NewMAC(NonceSize, macKey)
+ chacha20.XORKeyStream(macKey, make([]byte, 32), new([16]byte), key)
+ mac, err := blake2b.New256(macKey)
+ if err != nil {
+ panic(err)
+ }
nonces := make(chan *[NonceSize]byte, NonceBucketSize*3)
go func() {
for {
bufR []byte
tagR *[TagSize]byte
keyAuthR *[SSize]byte
+ nonceR *[16]byte
pktSizeR int
// UDP-related
bufT []byte
tagT *[TagSize]byte
keyAuthT *[SSize]byte
+ nonceT *[16]byte
frameT []byte
noncesT chan *[NonceSize]byte
}
tagR: new([TagSize]byte),
tagT: new([TagSize]byte),
keyAuthR: new([SSize]byte),
+ nonceR: new([16]byte),
keyAuthT: new([SSize]byte),
+ nonceT: new([16]byte),
}
if isClient {
}
copy(p.frameT[len(p.frameT)-NonceSize:], (<-p.noncesT)[:])
var out []byte
+ copy(p.nonceT[8:], p.frameT[len(p.frameT)-NonceSize:])
if p.Encless {
var err error
- out, err = EnclessEncode(
- p.key,
- p.frameT[len(p.frameT)-NonceSize:],
- p.frameT[:len(p.frameT)-NonceSize],
- )
+ out, err = EnclessEncode(p.key, p.nonceT, p.frameT[:len(p.frameT)-NonceSize])
if err != nil {
panic(err)
}
out = append(out, p.frameT[len(p.frameT)-NonceSize:]...)
} else {
- salsa20.XORKeyStream(
+ chacha20.XORKeyStream(
p.bufT[:S20BS+len(p.frameT)-NonceSize],
p.bufT[:S20BS+len(p.frameT)-NonceSize],
- p.frameT[len(p.frameT)-NonceSize:],
+ p.nonceT,
p.key,
)
copy(p.keyAuthT[:], p.bufT[:SSize])
}
var out []byte
p.BusyR.Lock()
+ copy(p.nonceR[8:], data[len(data)-NonceSize:])
if p.Encless {
var err error
- out, err = EnclessDecode(
- p.key,
- data[len(data)-NonceSize:],
- data[:len(data)-NonceSize],
- )
+ out, err = EnclessDecode(p.key, p.nonceR, data[:len(data)-NonceSize])
if err != nil {
p.FramesUnauth++
p.BusyR.Unlock()
p.bufR[i] = 0
}
copy(p.bufR[S20BS:], data[TagSize:])
- salsa20.XORKeyStream(
+ chacha20.XORKeyStream(
p.bufR[:S20BS+len(data)-TagSize-NonceSize],
p.bufR[:S20BS+len(data)-TagSize-NonceSize],
- data[len(data)-NonceSize:],
+ p.nonceR,
p.key,
)
copy(p.keyAuthR[:], p.bufR[:SSize])
bufZ = !bufZ
n, err = tap.dev.Read(buf)
if err != nil {
- panic("Reading TAP:" + err.Error())
+ panic("Reading TUN/TAP:" + err.Error())
}
tap.Sink <- buf[:n]
}
import (
"io"
+ "strings"
"github.com/bigeagle/water"
)
func newTAPer(ifaceName string) (io.ReadWriter, error) {
- return water.NewTAP(ifaceName)
+ if strings.HasPrefix(ifaceName, "tap") {
+ return water.NewTAP(ifaceName)
+ } else {
+ return water.NewTUN(ifaceName)
+ }
}
"encoding/base64"
"errors"
"fmt"
+ "hash"
"io/ioutil"
"log"
"os"
"cypherpunks.ru/balloon"
"github.com/agl/ed25519"
- "github.com/dchest/blake2b"
+ "golang.org/x/crypto/blake2b"
"golang.org/x/crypto/ssh/terminal"
)
return &Verifier{S: s, T: t, P: p, Id: id}
}
+func blake2bKeyless() hash.Hash {
+ h, err := blake2b.New256(nil)
+ if err != nil {
+ panic(err)
+ }
+ return h
+}
+
// Apply the password: create Ed25519 keypair based on it, save public
// key in verifier.
func (v *Verifier) PasswordApply(password string) *[ed25519.PrivateKeySize]byte {
- r := balloon.H(blake2b.New256, []byte(password), v.Id[:], v.S, v.T, v.P)
+ 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)
+++ /dev/null
-Subproject commit 3c8c640cd7bea3ca78209d812b5854442ab92fed
-Subproject commit 0e31b188fd38db611d4fbab7de9373a95f36aae5
+Subproject commit b2fa06b6af4b7c9bfeb8569ab7b17f04550717bf
git clone . $tmp/govpn-$release
repos="
+ src/cypherpunks.ru/balloon
src/github.com/agl/ed25519
src/github.com/bigeagle/water
- src/github.com/dchest/blake2b
src/github.com/go-yaml/yaml
src/golang.org/x/crypto
"
golang.org/x/crypto/LICENSE
golang.org/x/crypto/PATENTS
golang.org/x/crypto/README
+golang.org/x/crypto/blake2b
+golang.org/x/crypto/chacha20poly1305/internal/chacha20
golang.org/x/crypto/curve25519
golang.org/x/crypto/poly1305
-golang.org/x/crypto/salsa20
golang.org/x/crypto/ssh/terminal
-golang.org/x/crypto/xtea
EOF
tar cfCI - src $tmp/includes | tar xfC - $tmp
rm -fr src/golang.org
through UDP, TCP and HTTP proxies. IPv4/IPv6-compatibility.
GNU/Linux and FreeBSD support.
-----------------8<-----------------8<-----------------8<----------------
+------------------------ >8 ------------------------
The main improvements for that release are:
$(git cat-file -p $release | sed -n '6,/^.*BEGIN/p' | sed '$d')
-----------------8<-----------------8<-----------------8<----------------
+------------------------ >8 ------------------------
GoVPN's home page is: http://www.govpn.info/
also available as Tor hidden service: http://2wir2p7ibeu72jk3.onion/
реального времени. Возможность работы поверх UDP, TCP и HTTP прокси.
Совместимость с IPv4 и IPv6. Поддержка GNU/Linux и FreeBSD.
-----------------8<-----------------8<-----------------8<----------------
+------------------------ >8 ------------------------
Основные усовершенствования в этом релизе:
$(git cat-file -p $release | sed -n '6,/^.*BEGIN/p' | sed '$d')
-----------------8<-----------------8<-----------------8<----------------
+------------------------ >8 ------------------------
Домашняя страница GoVPN: http://www.govpn.info/
также доступна как скрытый сервис Tor: http://2wir2p7ibeu72jk3.onion/
$username:
up: /path/to/up.sh
- iface: or TAP interface name
+ iface: or TUN/TAP interface name
verifier: $verifierS
EOF