From: Sergey Matveev <stargrave@stargrave.org>
Date: Wed, 28 May 2025 10:32:07 +0000 (+0300)
Subject: Faster ChaCha20 implementation
X-Git-Tag: v4.0.0~3
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=a10ab85ccc760aa1c1cad08bfe0c1ac74fc84e6ebed05e7a1ac0342683186372;p=vors.git

Faster ChaCha20 implementation
---

diff --git a/cmd/client/main.go b/cmd/client/main.go
index a8f4e27..9ff8be6 100644
--- a/cmd/client/main.go
+++ b/cmd/client/main.go
@@ -32,6 +32,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/aead/chacha20"
 	"github.com/dchest/siphash"
 	"github.com/flynn/noise"
 	"github.com/jroimartin/gocui"
@@ -39,7 +40,6 @@ import (
 	"go.stargrave.org/opus/v2"
 	vors "go.stargrave.org/vors/v3/internal"
 	"golang.org/x/crypto/blake2s"
-	"golang.org/x/crypto/chacha20"
 )
 
 type Stream struct {
@@ -316,17 +316,17 @@ Magenta "S" means that peer is locally muted.`)
 	var keyMACOur []byte
 	{
 		var xof blake2s.XOF
-		xof, err = blake2s.NewXOF(chacha20.KeySize+16, nil)
+		xof, err = blake2s.NewXOF(vors.ChaCha20KeySize+vors.SipHash24KeySize, nil)
 		if err != nil {
 			log.Fatalln(err)
 		}
 		xof.Write([]byte(vors.NoisePrologue))
 		xof.Write(hs.ChannelBinding())
-		buf := make([]byte, chacha20.KeySize+16)
+		buf := make([]byte, vors.ChaCha20KeySize+vors.SipHash24KeySize)
 		if _, err = io.ReadFull(xof, buf); err != nil {
 			log.Fatalln(err)
 		}
-		keyCiphOur, keyMACOur = buf[:chacha20.KeySize], buf[chacha20.KeySize:]
+		keyCiphOur, keyMACOur = buf[:vors.ChaCha20KeySize], buf[vors.ChaCha20KeySize:]
 	}
 
 	seen := time.Now()
@@ -423,7 +423,7 @@ Magenta "S" means that peer is locally muted.`)
 				sid := sidRaw[0]
 				printBell()
 				log.Println("add", string(name), "sid:", sid)
-				keyCiph, keyMAC := key[:chacha20.KeySize], key[chacha20.KeySize:]
+				keyCiph, keyMAC := key[:vors.ChaCha20KeySize], key[vors.ChaCha20KeySize:]
 				stream := &Stream{
 					name:  string(name),
 					in:    make(chan []byte, 1<<10),
@@ -476,7 +476,6 @@ Magenta "S" means that peer is locally muted.`)
 						}()
 					}
 
-					var ciph *chacha20.Cipher
 					mac := siphash.New(keyMAC)
 					tag := make([]byte, siphash.Size)
 					var ctr uint32
@@ -501,14 +500,8 @@ Magenta "S" means that peer is locally muted.`)
 							stream.stats.bads++
 							continue
 						}
-						ciph, err = chacha20.NewUnauthenticatedCipher(
-							keyCiph, nonce,
-						)
-						if err != nil {
-							log.Fatal(err)
-						}
 						pkt = buf[4+3 : len(buf)-siphash.Size]
-						ciph.XORKeyStream(pkt, pkt)
+						chacha20.XORKeyStream(pkt, pkt, nonce, keyCiph)
 
 						ctr = binary.BigEndian.Uint32(nonce[len(nonce)-4:])
 						if lost == -1 {
@@ -678,7 +671,6 @@ Magenta "S" means that peer is locally muted.`)
 			return
 		}
 		<-LoggerReady
-		var ciph *chacha20.Cipher
 		mac := siphash.New(keyMACOur)
 		tag := make([]byte, siphash.Size)
 		buf := make([]byte, 2*vors.FrameLen)
@@ -716,13 +708,10 @@ Magenta "S" means that peer is locally muted.`)
 			incr(nonce[len(nonce)-3:])
 			copy(buf, nonce[len(nonce)-4:])
 			copy(buf[4:], actr)
-			ciph, err = chacha20.NewUnauthenticatedCipher(keyCiphOur, nonce)
-			if err != nil {
-				log.Fatal(err)
-			}
-			ciph.XORKeyStream(
+			chacha20.XORKeyStream(
 				buf[4+len(actr):4+len(actr)+n],
 				buf[4+len(actr):4+len(actr)+n],
+				nonce, keyCiphOur,
 			)
 			mac.Reset()
 			if _, err = mac.Write(buf[:4+len(actr)+n]); err != nil {
diff --git a/cmd/server/main.go b/cmd/server/main.go
index a2488a9..a7af83d 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -36,7 +36,6 @@ import (
 	"github.com/jroimartin/gocui"
 	vors "go.stargrave.org/vors/v3/internal"
 	"golang.org/x/crypto/blake2s"
-	"golang.org/x/crypto/chacha20"
 )
 
 var (
@@ -270,17 +269,17 @@ func newPeer(conn *net.TCPConn) {
 	room.peersM.RUnlock()
 
 	{
-		xof, err := blake2s.NewXOF(chacha20.KeySize+16, nil)
+		xof, err := blake2s.NewXOF(vors.ChaCha20KeySize+vors.SipHash24KeySize, nil)
 		if err != nil {
 			log.Fatalln(err)
 		}
 		xof.Write([]byte(vors.NoisePrologue))
 		xof.Write(hs.ChannelBinding())
-		peer.key = make([]byte, chacha20.KeySize+16)
+		peer.key = make([]byte, vors.ChaCha20KeySize+vors.SipHash24KeySize)
 		if _, err = io.ReadFull(xof, peer.key); err != nil {
 			log.Fatalln(err)
 		}
-		peer.mac = siphash.New(peer.key[chacha20.KeySize:])
+		peer.mac = siphash.New(peer.key[vors.ChaCha20KeySize:])
 	}
 
 	{
diff --git a/go.mod b/go.mod
index 0ae87a9..b73f35c 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module go.stargrave.org/vors/v3
 go 1.21
 
 require (
+	github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da
 	github.com/dchest/siphash v1.2.3
 	github.com/dustin/go-humanize v1.0.1
 	github.com/flynn/noise v1.1.0
diff --git a/go.sum b/go.sum
index 7da0a8d..1b2db1b 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,5 @@
+github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
+github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
 github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
 github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=