]> Cypherpunks repositories - udpobfs.git/commitdiff
Raise copyright years master
authorSergey Matveev <stargrave@stargrave.org>
Tue, 30 Dec 2025 11:02:09 +0000 (14:02 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Tue, 30 Dec 2025 11:02:09 +0000 (14:02 +0300)
chacha20poly1305/chacha20poly1305.go [new file with mode: 0644]
chacha20poly1305/chacha20poly1305_amd64.go [new file with mode: 0644]
chacha20poly1305/chacha20poly1305_generic.go [new file with mode: 0644]
chacha20poly1305/chacha20poly1305_noasm.go [new file with mode: 0644]
cmd/init/main.go
cmd/resp/main.go
crypto.go
foo/main.go [new file with mode: 0644]
foo_test.go [new file with mode: 0644]
utils.go
x509.go

diff --git a/chacha20poly1305/chacha20poly1305.go b/chacha20poly1305/chacha20poly1305.go
new file mode 100644 (file)
index 0000000..5fce5b9
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its
+// extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and
+// draft-irtf-cfrg-xchacha-01.
+package chacha20poly1305
+
+import (
+       "crypto/cipher"
+       "errors"
+)
+
+const (
+       // KeySize is the size of the key used by this AEAD, in bytes.
+       KeySize = 32
+
+       // NonceSize is the size of the nonce used with the standard variant of this
+       // AEAD, in bytes.
+       //
+       // Note that this is too short to be safely generated at random if the same
+       // key is reused more than 2³² times.
+       NonceSize = 12
+
+       // NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305
+       // variant of this AEAD, in bytes.
+       NonceSizeX = 24
+
+       // Overhead is the size of the Poly1305 authentication tag, and the
+       // difference between a ciphertext length and its plaintext.
+       Overhead = 16
+)
+
+type chacha20poly1305 struct {
+       key [KeySize]byte
+}
+
+// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key.
+func New(key []byte) (cipher.AEAD, error) {
+       if len(key) != KeySize {
+               return nil, errors.New("chacha20poly1305: bad key length")
+       }
+       ret := new(chacha20poly1305)
+       copy(ret.key[:], key)
+       return ret, nil
+}
+
+func (c *chacha20poly1305) NonceSize() int {
+       return NonceSize
+}
+
+func (c *chacha20poly1305) Overhead() int {
+       return Overhead
+}
+
+func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
+       if len(nonce) != NonceSize {
+               panic("chacha20poly1305: bad nonce length passed to Seal")
+       }
+
+       if uint64(len(plaintext)) > (1<<38)-64 {
+               panic("chacha20poly1305: plaintext too large")
+       }
+
+       return c.seal(dst, nonce, plaintext, additionalData)
+}
+
+var errOpen = errors.New("chacha20poly1305: message authentication failed")
+
+func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+       if len(nonce) != NonceSize {
+               panic("chacha20poly1305: bad nonce length passed to Open")
+       }
+       if len(ciphertext) < 16 {
+               return nil, errOpen
+       }
+       if uint64(len(ciphertext)) > (1<<38)-48 {
+               panic("chacha20poly1305: ciphertext too large")
+       }
+
+       return c.open(dst, nonce, ciphertext, additionalData)
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+       if total := len(in) + n; cap(in) >= total {
+               head = in[:total]
+       } else {
+               head = make([]byte, total)
+               copy(head, in)
+       }
+       tail = head[len(in):]
+       return
+}
diff --git a/chacha20poly1305/chacha20poly1305_amd64.go b/chacha20poly1305/chacha20poly1305_amd64.go
new file mode 100644 (file)
index 0000000..9c61084
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build gc && !purego
+
+package chacha20poly1305
+
+import (
+       "encoding/binary"
+
+       "golang.org/x/sys/cpu"
+)
+
+//go:noescape
+func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
+
+//go:noescape
+func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
+
+var (
+       useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
+)
+
+// setupState writes a ChaCha20 input matrix to state. See
+// https://tools.ietf.org/html/rfc7539#section-2.3.
+func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
+       state[0] = 0x61707865
+       state[1] = 0x3320646e
+       state[2] = 0x79622d32
+       state[3] = 0x6b206574
+
+       state[4] = binary.LittleEndian.Uint32(key[0:4])
+       state[5] = binary.LittleEndian.Uint32(key[4:8])
+       state[6] = binary.LittleEndian.Uint32(key[8:12])
+       state[7] = binary.LittleEndian.Uint32(key[12:16])
+       state[8] = binary.LittleEndian.Uint32(key[16:20])
+       state[9] = binary.LittleEndian.Uint32(key[20:24])
+       state[10] = binary.LittleEndian.Uint32(key[24:28])
+       state[11] = binary.LittleEndian.Uint32(key[28:32])
+
+       state[12] = 0
+       state[13] = binary.LittleEndian.Uint32(nonce[0:4])
+       state[14] = binary.LittleEndian.Uint32(nonce[4:8])
+       state[15] = binary.LittleEndian.Uint32(nonce[8:12])
+}
+
+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
+       if !cpu.X86.HasSSSE3 {
+               return c.sealGeneric(dst, nonce, plaintext, additionalData)
+       }
+
+       var state [16]uint32
+       setupState(&state, &c.key, nonce)
+
+       ret, out := sliceForAppend(dst, len(plaintext)+16)
+       chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
+       return ret
+}
+
+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+       if !cpu.X86.HasSSSE3 {
+               return c.openGeneric(dst, nonce, ciphertext, additionalData)
+       }
+
+       var state [16]uint32
+       setupState(&state, &c.key, nonce)
+
+       ciphertext = ciphertext[:len(ciphertext)-16]
+       ret, out := sliceForAppend(dst, len(ciphertext))
+       chacha20Poly1305Open(out, state[:], ciphertext, additionalData)
+       return ret, nil
+}
diff --git a/chacha20poly1305/chacha20poly1305_generic.go b/chacha20poly1305/chacha20poly1305_generic.go
new file mode 100644 (file)
index 0000000..d3c1ce5
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package chacha20poly1305
+
+import (
+       "golang.org/x/crypto/chacha20"
+)
+
+func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
+       ret, out := sliceForAppend(dst, len(plaintext)+16)
+       ciphertext, _ := out[:len(plaintext)], out[len(plaintext):]
+       s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
+       s.SetCounter(1) // set the counter to 1, skipping 32 bytes
+       s.XORKeyStream(ciphertext, plaintext)
+       return ret
+}
+
+func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+       ciphertext = ciphertext[:len(ciphertext)-16]
+       s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
+       s.SetCounter(1) // set the counter to 1, skipping 32 bytes
+       ret, out := sliceForAppend(dst, len(ciphertext))
+       s.XORKeyStream(out, ciphertext)
+       return ret, nil
+}
diff --git a/chacha20poly1305/chacha20poly1305_noasm.go b/chacha20poly1305/chacha20poly1305_noasm.go
new file mode 100644 (file)
index 0000000..c5c7983
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !amd64 || !gc || purego
+
+package chacha20poly1305
+
+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
+       return c.sealGeneric(dst, nonce, plaintext, additionalData)
+}
+
+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+       return c.openGeneric(dst, nonce, ciphertext, additionalData)
+}
index d18a311212cfb4c674a63eeeabf0f149141b35e7e1dbf04aec2fe7336283c3ce..aac1a895cb1cd3057154dd9386699e9fb46b11a533e6639ea57e187f2ad40a7a 100644 (file)
@@ -1,5 +1,5 @@
 // udpobfs -- simple point-to-point UDP obfuscation proxy
-// Copyright (C) 2023-2025 Sergey Matveev <stargrave@stargrave.org>
+// Copyright (C) 2023-2026 Sergey Matveev <stargrave@stargrave.org>
 //
 // 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
index 9a6af9687e0252a3ec48b7339cb13abbebdadcf2cd478b153f1afcdaedfc4289..03e4d35b160ecc80e27e2294ae7d4c1b9e546e81e54d95e460ba361d42a55122 100644 (file)
@@ -1,5 +1,5 @@
 // udpobfs -- simple point-to-point UDP obfuscation proxy
-// Copyright (C) 2023-2025 Sergey Matveev <stargrave@stargrave.org>
+// Copyright (C) 2023-2026 Sergey Matveev <stargrave@stargrave.org>
 //
 // 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
index d440bb54aea9e25684c1fdfb5d154bbd203ac533882e3935ca5454930f55c6f1..c1f5fdaacf451ef61eab6332b0a1f087ad0fcf9401f5caa8535205aa9a790b5f 100644 (file)
--- a/crypto.go
+++ b/crypto.go
@@ -1,5 +1,5 @@
 // udpobfs -- simple point-to-point UDP obfuscation proxy
-// Copyright (C) 2023-2025 Sergey Matveev <stargrave@stargrave.org>
+// Copyright (C) 2023-2026 Sergey Matveev <stargrave@stargrave.org>
 //
 // 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
diff --git a/foo/main.go b/foo/main.go
new file mode 100644 (file)
index 0000000..e6e2a8c
--- /dev/null
@@ -0,0 +1,33 @@
+package main
+
+import (
+       "crypto/cipher"
+       "crypto/rand"
+       "io"
+       "os"
+
+       "github.com/dchest/threefish"
+)
+
+func main() {
+       key := make([]byte, 64)
+       tweak := make([]byte, 16)
+       iv := make([]byte, 64)
+       rand.Read(key)
+       rand.Read(tweak)
+       rand.Read(iv)
+       c, err := threefish.NewCipher(key, tweak)
+       if err != nil {
+               panic(err)
+       }
+       var b cipher.BlockMode
+       buf := make([]byte, 1024*1024)
+       for {
+               if _, err = io.ReadFull(os.Stdin, buf); err != nil {
+                       panic(err)
+               }
+               b = cipher.NewCBCEncrypter(c, iv)
+               b.CryptBlocks(buf, buf)
+               os.Stdout.Write(buf)
+       }
+}
diff --git a/foo_test.go b/foo_test.go
new file mode 100644 (file)
index 0000000..b41b404
--- /dev/null
@@ -0,0 +1,270 @@
+package udpobfs
+
+import (
+       "crypto/cipher"
+       "crypto/rand"
+       "crypto/rc4"
+       "encoding/binary"
+       "io"
+       "sync"
+       "testing"
+
+       "github.com/dchest/threefish"
+       "golang.org/x/crypto/blowfish"
+       "golang.org/x/crypto/cast5"
+       "golang.org/x/crypto/chacha20"
+       "golang.org/x/crypto/chacha20poly1305"
+       "golang.org/x/crypto/xtea"
+       "lukechampine.com/blake3"
+)
+
+func BenchmarkChaCha20Poly1305(b *testing.B) {
+       var key [32]byte
+       rand.Read(key[:])
+       var nonce [12]byte
+       rand.Read(nonce[:])
+       dst := make([]byte, 1500)
+       src := make([]byte, 500)
+       rand.Read(src)
+       c, err := chacha20poly1305.New(key[:])
+       if err != nil {
+               panic(err)
+       }
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               c.Seal(dst[:0], nonce[:], src, nil)
+       }
+}
+
+func BenchmarkChaCha20(b *testing.B) {
+       var key [32]byte
+       rand.Read(key[:])
+       var nonce [12]byte
+       rand.Read(nonce[:])
+       dst := make([]byte, 1500)
+       src := make([]byte, 500)
+       rand.Read(src)
+       c, err := chacha20.NewUnauthenticatedCipher(key[:], nonce[:])
+       if err != nil {
+               panic(err)
+       }
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               c.XORKeyStream(dst, src)
+       }
+}
+
+func BenchmarkBLAKE3(b *testing.B) {
+       var key [32]byte
+       rand.Read(key[:])
+       h := blake3.New(32, key[:])
+       var nonce [8]byte
+       rand.Read(nonce[:])
+       dst := make([]byte, 500)
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               h.Reset()
+               MustWrite(h, nonce[:])
+               if _, err := io.ReadFull(h.XOF(), dst); err != nil {
+                       panic(err)
+               }
+               h.Reset()
+               MustWrite(h, dst)
+       }
+}
+
+func BenchmarkBLAKE3Seek(b *testing.B) {
+       var key [32]byte
+       rand.Read(key[:])
+       h := blake3.New(32, key[:])
+       var nonce [8]byte
+       rand.Read(nonce[:])
+       n := int64(binary.BigEndian.Uint64(nonce[:]))
+       if n < 0 {
+               n = -n
+       }
+       dst := make([]byte, 1500)
+       b.ResetTimer()
+       var xof *blake3.OutputReader
+       var err error
+       for i := 0; i < b.N; i++ {
+               h.Reset()
+               xof = h.XOF()
+               if _, err = xof.Seek(n, io.SeekStart); err != nil {
+                       panic(err)
+               }
+               // MustWrite(h, nonce[:])
+               if _, err := io.ReadFull(h.XOF(), dst); err != nil {
+                       panic(err)
+               }
+               h.Reset()
+               MustWrite(h, dst)
+       }
+}
+
+func BenchmarkBlowfish(b *testing.B) {
+       var key [32]byte
+       rand.Read(key[:])
+       dst := make([]byte, 8)
+       src := make([]byte, 8)
+       rand.Read(src)
+       c, err := blowfish.NewCipher(key[:])
+       if err != nil {
+               panic(err)
+       }
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               c.Encrypt(dst, src)
+       }
+}
+
+func BenchmarkXTEA(b *testing.B) {
+       var key [16]byte
+       rand.Read(key[:])
+       dst := make([]byte, 8)
+       src := make([]byte, 8)
+       rand.Read(src)
+       c, err := xtea.NewCipher(key[:])
+       if err != nil {
+               panic(err)
+       }
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               c.Encrypt(dst, src)
+       }
+}
+
+func BenchmarkCAST5(b *testing.B) {
+       var key [16]byte
+       rand.Read(key[:])
+       dst := make([]byte, 8)
+       src := make([]byte, 8)
+       rand.Read(src)
+       c, err := cast5.NewCipher(key[:])
+       if err != nil {
+               panic(err)
+       }
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               c.Encrypt(dst, src)
+       }
+}
+
+func BenchmarkRLock(b *testing.B) {
+       var l sync.RWMutex
+       b.ResetTimer()
+       a := 0
+       for i := 0; i < b.N; i++ {
+               l.RLock()
+               a++
+               l.RUnlock()
+       }
+}
+
+func BenchmarkBigBlow(b *testing.B) {
+       var key [32]byte
+       rand.Read(key[:])
+       dst := make([]byte, 1500)
+       src := make([]byte, 504)
+       rand.Read(src)
+       c, err := blowfish.NewCipher(key[:])
+       if err != nil {
+               panic(err)
+       }
+       for b.Loop() {
+               for i := 0; i < len(src); i += 8 {
+                       c.Encrypt(dst[i:], src[i:])
+               }
+       }
+}
+
+func BenchmarkRC4(b *testing.B) {
+       var key [32]byte
+       rand.Read(key[:])
+       dst := make([]byte, 1500)
+       src := make([]byte, 504)
+       rand.Read(src)
+       c, err := rc4.NewCipher(key[:])
+       if err != nil {
+               panic(err)
+       }
+       for b.Loop() {
+               c.XORKeyStream(dst, src)
+       }
+}
+
+func BenchmarkThreefish(b *testing.B) {
+       var tweak [16]byte
+       var key [64]byte
+       rand.Read(key[:])
+       dst := make([]byte, 1500)
+       src := make([]byte, 512)
+       rand.Read(src)
+       c, err := threefish.NewCipher(key[:], tweak[:])
+       if err != nil {
+               panic(err)
+       }
+       for b.Loop() {
+               for i := 0; i < len(src); i += 64 {
+                       c.Encrypt(dst[i:i+64], src[i:i+64])
+               }
+       }
+}
+
+func BenchmarkThreefishCFB(b *testing.B) {
+       var tweak [16]byte
+       var iv [64]byte
+       var key [64]byte
+       rand.Read(key[:])
+       rand.Read(iv[:])
+       dst := make([]byte, 1500)
+       src := make([]byte, 500)
+       rand.Read(src)
+       c, err := threefish.NewCipher(key[:], tweak[:])
+       if err != nil {
+               panic(err)
+       }
+       for b.Loop() {
+               s := cipher.NewCFBDecrypter(c, iv[:])
+               s.XORKeyStream(dst, src)
+       }
+}
+
+func BenchmarkThreefishCBC(b *testing.B) {
+       var tweak [16]byte
+       var iv [64]byte
+       var key [64]byte
+       rand.Read(key[:])
+       rand.Read(iv[:])
+       dst := make([]byte, 1500)
+       src := make([]byte, 512)
+       rand.Read(src)
+       c, err := threefish.NewCipher(key[:], tweak[:])
+       if err != nil {
+               panic(err)
+       }
+       for b.Loop() {
+               s := cipher.NewCBCDecrypter(c, iv[:])
+               s.CryptBlocks(dst, src)
+       }
+}
+
+
+func BenchmarkThreefishCBCE(b *testing.B) {
+       var tweak [16]byte
+       var iv [64]byte
+       var key [64]byte
+       rand.Read(key[:])
+       rand.Read(iv[:])
+       dst := make([]byte, 1500)
+       src := make([]byte, 512)
+       rand.Read(src)
+       c, err := threefish.NewCipher(key[:], tweak[:])
+       if err != nil {
+               panic(err)
+       }
+       for b.Loop() {
+               s := cipher.NewCBCEncrypter(c, iv[:])
+               s.CryptBlocks(dst, src)
+       }
+}
index b48d27e439bcd3d23f451bb1f9f397d19fccb6b3f2ebd66108379748efc4e4a6..4db7c875dde2d19628310230f59320e6eedd0f17d517d5ed5f2c0f4667e74f2c 100644 (file)
--- a/utils.go
+++ b/utils.go
@@ -1,5 +1,5 @@
 // udpobfs -- simple point-to-point UDP obfuscation proxy
-// Copyright (C) 2023-2025 Sergey Matveev <stargrave@stargrave.org>
+// Copyright (C) 2023-2026 Sergey Matveev <stargrave@stargrave.org>
 //
 // 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
diff --git a/x509.go b/x509.go
index e472457a38a00b727778ac75e2eee16f41d8d21abd2dcbcd6d39c1778e41d609..9cac55edc5907e4f26d278d4e0f3e2e1464c80b5f3bb5c48737188e284f0d48a 100644 (file)
--- a/x509.go
+++ b/x509.go
@@ -1,5 +1,5 @@
 // udpobfs -- simple point-to-point UDP obfuscation proxy
-// Copyright (C) 2023-2025 Sergey Matveev <stargrave@stargrave.org>
+// Copyright (C) 2023-2026 Sergey Matveev <stargrave@stargrave.org>
 //
 // 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