]> Cypherpunks.ru repositories - govpn.git/commitdiff
Replace (X)Salsa20 with ChaCha20
authorSergey Matveev <stargrave@stargrave.org>
Sat, 29 Oct 2016 13:42:01 +0000 (16:42 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sat, 29 Oct 2016 14:14:45 +0000 (17:14 +0300)
Theoreticall it is more faster and secure.

14 files changed:
VERSION
doc/developer.texi
doc/encless.texi
doc/news.ru.texi
doc/news.texi
doc/transport.texi
src/chacha20 [new symlink]
src/cypherpunks.ru/govpn/aont/oaep.go
src/cypherpunks.ru/govpn/cnw/cnw.go
src/cypherpunks.ru/govpn/encless.go
src/cypherpunks.ru/govpn/encless_test.go
src/cypherpunks.ru/govpn/handshake.go
src/cypherpunks.ru/govpn/peer.go
utils/makedist.sh

diff --git a/VERSION b/VERSION
index e0ea36feef6e828ce8587989537a827d0c3c98ed..4fedf1d20e15761409d6e4e3bf99c0beb499fdfe 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.0
+7.0
index b12d5e15d8e860cb2d05f5895378f282e2ca948b..15e87800a314b44604730747b9a0610ab91c8f02 100644 (file)
@@ -5,7 +5,7 @@ Pay attention how to get @ref{Sources, development source code}.
 
 @table @asis
 @item Data encryption
 
 @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{https://cr.yp.to/mac.html, Poly1305}.
 @item Nonce and identity obfuscation
 @item Message authentication
     @url{https://cr.yp.to/mac.html, Poly1305}.
 @item Nonce and identity obfuscation
@@ -25,7 +25,7 @@ Pay attention how to get @ref{Sources, development source code}.
     @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
     @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
     @url{http://crypto.stanford.edu/~dabo/abstracts/saep.html, SAEP+}
     checksums) data with 128-bits of feeded random.
 @item Packet overhead
index 6d694b2a984217740f0dff2c321aaa088c28d4c3..9513d6ce67f5bd8b473b0a0cb44cabd478e3666f 100644 (file)
@@ -8,7 +8,7 @@ some countries forbids usage of encryption (but again not the
 authentication).
 
 GoVPN provides special encryptionless mode of operation. In this mode it
 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
 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
index 47ba43bc1607d386173505a9fd3ccbbc483e5746..db4a6edfea4c2c2208dc58e593dd87711c6054e5 100644 (file)
@@ -1,6 +1,13 @@
 @node Новости
 @section Новости
 
 @node Новости
 @section Новости
 
+@node Релиз 7.0
+@subsection Релиз 7.0
+@itemize
+@item (X)Salsa20 заменён на ChaCha20. Теоретически он должен быть
+быстрее и более безопасным.
+@end itemize
+
 @node Релиз 6.0
 @subsection Релиз 6.0
 @itemize
 @node Релиз 6.0
 @subsection Релиз 6.0
 @itemize
index 631c5940ac541920570e9a02f9e807d232a872fe..10a2aab6d134519e72530c49d4fb0f33d7dff6e0 100644 (file)
@@ -3,6 +3,13 @@
 
 See also this page @ref{Новости, on russian}.
 
 
 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.
+@end itemize
+
 @node Release 6.0
 @section Release 6.0
 @itemize
 @node Release 6.0
 @section Release 6.0
 @itemize
index 812322528f03019d4b882dab6e925ebdd386afa4..e5f5abba9eba15dec245489f2aa53c807d007b5f 100644 (file)
@@ -2,7 +2,7 @@
 @section Transport protocol
 
 @verbatim
 @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)
    PAYLOAD = DATA || PAD [|| ZEROS]
 CIPHERTEXT = ENCRYPT(KEY, NONCE, PAYLOAD)
        TAG = AUTH(AUTH_KEY, CIPHERTEXT || NONCE)
@@ -13,16 +13,16 @@ CIPHERTEXT = ENCRYPT(KEY, NONCE, PAYLOAD)
 client (to server) messages, evens for server (to client) messages.
 
 @code{MAC} is BLAKE2b-MAC used to obfuscate @code{SERIAL}. MAC's key
 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
 
 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
 @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
 encrypting it.
 
 @code{DATA} is padded using ISO/IEC 7816-4 format (@code{PAD} (0x80
@@ -30,7 +30,7 @@ byte) with optional @code{ZEROS} following), to fill up packet to
 conceal payload packet length.
 
 @code{AUTH} is Poly1305 authentication function. First 256 bits of
 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))
 
 @verbatim
 AUTH_KEY = 256bit(ENCRYPT(KEY, NONCE))
diff --git a/src/chacha20 b/src/chacha20
new file mode 120000 (symlink)
index 0000000..95f85aa
--- /dev/null
@@ -0,0 +1 @@
+golang.org/x/crypto/chacha20poly1305/internal/chacha20
\ No newline at end of file
index 3d1a1c6731722eecef657ffa3a6e9074b7368d6e..4b780ba427ed2e6f87e8d5724ed2488b4f8e8f17 100644 (file)
@@ -30,7 +30,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // package PKG:
 //
 //     PKG = P1 || P2
 // 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
 
 //      P2 = BLAKE2b(P1) XOR r
 package aont
 
@@ -38,8 +38,8 @@ import (
        "crypto/subtle"
        "errors"
 
        "crypto/subtle"
        "errors"
 
+       "chacha20"
        "golang.org/x/crypto/blake2b"
        "golang.org/x/crypto/blake2b"
-       "golang.org/x/crypto/salsa20"
 )
 
 const (
 )
 
 const (
@@ -48,7 +48,7 @@ const (
 )
 
 var (
 )
 
 var (
-       dummyNonce []byte = make([]byte, 8)
+       dummyNonce *[16]byte = new([16]byte)
 )
 
 // Encode the data, produce AONT package. Data size will be larger than
 )
 
 // Encode the data, produce AONT package. Data size will be larger than
@@ -63,9 +63,9 @@ func Encode(r *[RSize]byte, in []byte) ([]byte, error) {
        h.Write(r[:])
        h.Write(in)
        copy(out[len(in):], h.Sum(nil))
        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] {
        h.Reset()
        h.Write(out[:len(in)+32])
        for i, b := range h.Sum(nil)[:RSize] {
@@ -85,14 +85,14 @@ func Decode(in []byte) ([]byte, error) {
                return nil, err
        }
        h.Write(in[:len(in)-RSize])
                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] {
        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.Reset()
-       h.Write(salsaKey[:RSize])
+       h.Write(chachaKey[:RSize])
        out := make([]byte, len(in)-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")
        h.Write(out[:len(out)-HSize])
        if subtle.ConstantTimeCompare(h.Sum(nil), out[len(out)-HSize:]) != 1 {
                return nil, errors.New("Invalid checksum")
index 931a0d11d62905ade2afad22227347254b0d54d2..c5d41a635afb3440558f19b3c351ccc1035a0229 100644 (file)
@@ -34,11 +34,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // one is over "0". If bit value is 1, then first is taken over "0" and
 // second is over "1".
 //
 // 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).
 //
 // 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 (
 package cnw
 
 import (
@@ -46,8 +46,8 @@ import (
        "encoding/binary"
        "errors"
 
        "encoding/binary"
        "errors"
 
+       "chacha20"
        "golang.org/x/crypto/poly1305"
        "golang.org/x/crypto/poly1305"
-       "golang.org/x/crypto/salsa20"
 )
 
 const (
 )
 
 const (
@@ -65,15 +65,15 @@ func zero(in []byte) {
 func Chaff(authKey *[32]byte, noncePrfx, in []byte) []byte {
        out := make([]byte, len(in)*EnlargeFactor)
        keys := make([]byte, 8*64)
 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 {
        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])
                for i = 0; i < 8; i++ {
                        v = (b >> uint8(i)) & 1
                        copy(macKey[:], keys[64*i:64*i+32])
@@ -104,7 +104,7 @@ func Winnow(authKey *[32]byte, noncePrfx, in []byte) ([]byte, error) {
        }
        out := make([]byte, len(in)/EnlargeFactor)
        keys := make([]byte, 8*64)
        }
        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
        copy(nonce[:8], noncePrfx)
        var i int
        var v byte
@@ -116,8 +116,8 @@ func Winnow(authKey *[32]byte, noncePrfx, in []byte) ([]byte, error) {
        var is11 bool
        var is10 bool
        for n := 0; n < len(out); n++ {
        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])
                v = 0
                for i = 0; i < 8; i++ {
                        copy(macKey[:], keys[64*i:64*i+32])
index f9d9bbfe075e587e6fd16fd9e023a62a5f343537..bd42f1d5729349e1a4c3bf6fe2bb813445ee6249 100644 (file)
@@ -35,7 +35,7 @@ const (
 // 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.
 // 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 {
        r := new([aont.RSize]byte)
        var err error
        if _, err = io.ReadFull(Rand, r[:]); err != nil {
@@ -46,7 +46,7 @@ func EnclessEncode(authKey *[32]byte, nonce, in []byte) ([]byte, error) {
                return nil, err
        }
        out := append(
                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])
                aonted[aont.RSize:]...,
        )
        SliceZero(aonted[:aont.RSize])
@@ -54,10 +54,10 @@ func EnclessEncode(authKey *[32]byte, nonce, in []byte) ([]byte, error) {
 }
 
 // Decode EnclessEncode-ed data.
 }
 
 // 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(
        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
        )
        if err != nil {
                return nil, err
index 1f9fece30e3207999ec3a01a6d779888299d15e6..fc00d2708d753735bb501e3886c1ee8d4df1cde5 100644 (file)
@@ -35,9 +35,9 @@ func init() {
 }
 
 func TestEnclessSymmetric(t *testing.T) {
 }
 
 func TestEnclessSymmetric(t *testing.T) {
-       nonce := make([]byte, 8)
+       nonce := new([16]byte)
        f := func(pktNum uint64, in []byte) bool {
        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
                encoded, err := EnclessEncode(testKey, nonce, in)
                if err != nil {
                        return false
@@ -54,9 +54,9 @@ func TestEnclessSymmetric(t *testing.T) {
 }
 
 func BenchmarkEnclessEncode(b *testing.B) {
 }
 
 func BenchmarkEnclessEncode(b *testing.B) {
-       nonce := make([]byte, 8)
+       nonce := new([16]byte)
        data := make([]byte, 128)
        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++ {
        io.ReadFull(Rand, data)
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
@@ -65,9 +65,9 @@ func BenchmarkEnclessEncode(b *testing.B) {
 }
 
 func BenchmarkEnclessDecode(b *testing.B) {
 }
 
 func BenchmarkEnclessDecode(b *testing.B) {
-       nonce := make([]byte, 8)
+       nonce := new([16]byte)
        data := make([]byte, 128)
        data := make([]byte, 128)
-       io.ReadFull(Rand, nonce)
+       io.ReadFull(Rand, nonce[8:])
        io.ReadFull(Rand, data)
        encoded, _ := EnclessEncode(testKey, nonce, data)
        b.ResetTimer()
        io.ReadFull(Rand, data)
        encoded, _ := EnclessEncode(testKey, nonce, data)
        b.ResetTimer()
index fb486f592aa86ff76417a4dcad8e732cd843878c..a3ef2b5cf536397c176678d38c8fcd4fff70d1d8 100644 (file)
@@ -25,11 +25,11 @@ import (
        "log"
        "time"
 
        "log"
        "time"
 
+       "chacha20"
        "github.com/agl/ed25519"
        "github.com/agl/ed25519/extra25519"
        "golang.org/x/crypto/blake2b"
        "golang.org/x/crypto/curve25519"
        "github.com/agl/ed25519"
        "github.com/agl/ed25519/extra25519"
        "golang.org/x/crypto/blake2b"
        "golang.org/x/crypto/curve25519"
-       "golang.org/x/crypto/salsa20"
 )
 
 const (
 )
 
 const (
@@ -44,7 +44,7 @@ type Handshake struct {
        Conf     *PeerConf
        dsaPubH  *[ed25519.PublicKeySize]byte
        key      *[32]byte
        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
        dhPriv   *[32]byte    // own private DH key
        rServer  *[RSize]byte // random string for authentication
        rClient  *[RSize]byte
@@ -88,10 +88,10 @@ func (h *Handshake) Zero() {
        }
 }
 
        }
 }
 
-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
 }
 
        return nonce
 }
 
@@ -153,8 +153,8 @@ func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake {
        var dhPubRepr *[32]byte
        state.dhPriv, dhPubRepr = dhKeypairGen()
 
        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
                log.Fatalln("Error reading random for nonce:", err)
        }
        var enc []byte
@@ -166,15 +166,15 @@ func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake {
        copy(enc, dhPubRepr[:])
        if conf.Encless {
                var err error
        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 {
                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
 }
        state.conn.Write(data)
        return state
 }
@@ -188,15 +188,15 @@ func (h *Handshake) Server(data []byte) *Peer {
        // 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)) {
        // 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,
 
                // 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 {
                                data[RSize:len(data)-8],
                        )
                        if err != nil {
@@ -205,7 +205,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                        }
                        copy(cDHRepr[:], out)
                } else {
                        }
                        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
                }
 
                // Generate DH keypair
@@ -228,7 +228,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                        }
                } else {
                        encPub = make([]byte, 32)
                        }
                } 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
                }
 
                // Generate R* and encrypt them
@@ -250,12 +250,12 @@ func (h *Handshake) Server(data []byte) *Peer {
                }
                copy(encRs, append(h.rServer[:], h.sServer[:]...))
                if h.Conf.Encless {
                }
                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 {
                        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
                }
 
                // Send that to client
@@ -282,7 +282,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                        dec = dec[:RSize+RSize+SSize+ed25519.SignatureSize]
                } else {
                        dec = make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
                        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),
                                dec,
                                data[:RSize+RSize+SSize+ed25519.SignatureSize],
                                h.rNonceNext(1),
@@ -314,7 +314,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                                panic(err)
                        }
                } else {
                                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)...))
 
                }
                h.conn.Write(append(enc, idTag(h.Conf.Id, h.Conf.TimeSync, enc)...))
 
@@ -359,7 +359,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                        }
                        copy(sDHRepr[:], tmp[:32])
                } else {
                        }
                        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
                }
 
                // Compute shared key
@@ -371,11 +371,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                h.rServer = new([RSize]byte)
                h.sServer = new([SSize]byte)
                if h.Conf.Encless {
                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
                        if err != nil {
                                log.Println("Unable to decode packet from", h.addr, err)
                                return nil
@@ -384,7 +380,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                        copy(h.sServer[:], tmp[RSize:RSize+SSize])
                } else {
                        decRs := make([]byte, RSize+SSize)
                        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:])
                }
                        copy(h.rServer[:], decRs[:RSize])
                        copy(h.sServer[:], decRs[RSize:])
                }
@@ -416,7 +412,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                                panic(err)
                        }
                } else {
                                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
                }
 
                // Send that to server
@@ -438,7 +434,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                        dec = dec[:RSize]
                } else {
                        dec = make([]byte, RSize)
                        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)
                }
                if subtle.ConstantTimeCompare(dec, h.rClient[:]) != 1 {
                        log.Println("Invalid client's random number with", h.addr)
index 213e8174786df4db45d72abfa40a20043851b9a4..22c893c80fb51d3bb0bb1affbfa395e32a137257 100644 (file)
@@ -28,16 +28,16 @@ import (
        "sync/atomic"
        "time"
 
        "sync/atomic"
        "time"
 
+       "chacha20"
        "golang.org/x/crypto/blake2b"
        "golang.org/x/crypto/poly1305"
        "golang.org/x/crypto/blake2b"
        "golang.org/x/crypto/poly1305"
-       "golang.org/x/crypto/salsa20"
 )
 
 const (
        NonceSize       = 8
        NonceBucketSize = 256
        TagSize         = poly1305.TagSize
 )
 
 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
        S20BS = 64
        // Maximal amount of bytes transfered with single key (4 GiB)
        MaxBytesPerKey uint64 = 1 << 32
@@ -51,7 +51,7 @@ const (
 
 func newNonces(key *[32]byte, i uint64) chan *[NonceSize]byte {
        macKey := make([]byte, 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)
+       chacha20.XORKeyStream(macKey, make([]byte, 32), new([16]byte), key)
        mac, err := blake2b.New256(macKey)
        if err != nil {
                panic(err)
        mac, err := blake2b.New256(macKey)
        if err != nil {
                panic(err)
@@ -108,6 +108,7 @@ type Peer struct {
        bufR     []byte
        tagR     *[TagSize]byte
        keyAuthR *[SSize]byte
        bufR     []byte
        tagR     *[TagSize]byte
        keyAuthR *[SSize]byte
+       nonceR   *[16]byte
        pktSizeR int
 
        // UDP-related
        pktSizeR int
 
        // UDP-related
@@ -126,6 +127,7 @@ type Peer struct {
        bufT     []byte
        tagT     *[TagSize]byte
        keyAuthT *[SSize]byte
        bufT     []byte
        tagT     *[TagSize]byte
        keyAuthT *[SSize]byte
+       nonceT   *[16]byte
        frameT   []byte
        noncesT  chan *[NonceSize]byte
 }
        frameT   []byte
        noncesT  chan *[NonceSize]byte
 }
@@ -201,7 +203,9 @@ func newPeer(isClient bool, addr string, conn io.Writer, conf *PeerConf, key *[S
                tagR:     new([TagSize]byte),
                tagT:     new([TagSize]byte),
                keyAuthR: new([SSize]byte),
                tagR:     new([TagSize]byte),
                tagT:     new([TagSize]byte),
                keyAuthR: new([SSize]byte),
+               nonceR:   new([16]byte),
                keyAuthT: new([SSize]byte),
                keyAuthT: new([SSize]byte),
+               nonceT:   new([16]byte),
        }
 
        if isClient {
        }
 
        if isClient {
@@ -271,22 +275,19 @@ func (p *Peer) EthProcess(data []byte) {
        }
        copy(p.frameT[len(p.frameT)-NonceSize:], (<-p.noncesT)[:])
        var out []byte
        }
        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
        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 {
                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.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])
                        p.key,
                )
                copy(p.keyAuthT[:], p.bufT[:SSize])
@@ -308,13 +309,10 @@ func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool {
        }
        var out []byte
        p.BusyR.Lock()
        }
        var out []byte
        p.BusyR.Lock()
+       copy(p.nonceR[8:], data[len(data)-NonceSize:])
        if p.Encless {
                var err error
        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()
                if err != nil {
                        p.FramesUnauth++
                        p.BusyR.Unlock()
@@ -325,10 +323,10 @@ func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool {
                        p.bufR[i] = 0
                }
                copy(p.bufR[S20BS:], data[TagSize:])
                        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],
                        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])
                        p.key,
                )
                copy(p.keyAuthR[:], p.bufR[:SSize])
index 8a494f982dddc6f3e7b69111bc9219c1ac30752b..7be321b344336bb77ad88a8c9165799214a4ecde 100755 (executable)
@@ -27,9 +27,9 @@ golang.org/x/crypto/LICENSE
 golang.org/x/crypto/PATENTS
 golang.org/x/crypto/README
 golang.org/x/crypto/blake2b
 golang.org/x/crypto/PATENTS
 golang.org/x/crypto/README
 golang.org/x/crypto/blake2b
+golang.org/x/crypto/chacha20poly1305
 golang.org/x/crypto/curve25519
 golang.org/x/crypto/poly1305
 golang.org/x/crypto/curve25519
 golang.org/x/crypto/poly1305
-golang.org/x/crypto/salsa20
 golang.org/x/crypto/ssh/terminal
 EOF
 tar cfCI - src $tmp/includes | tar xfC - $tmp
 golang.org/x/crypto/ssh/terminal
 EOF
 tar cfCI - src $tmp/includes | tar xfC - $tmp