From: Sergey Matveev Date: Tue, 30 Dec 2025 11:02:09 +0000 (+0300) Subject: Raise copyright years X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;p=udpobfs.git Raise copyright years --- diff --git a/chacha20poly1305/chacha20poly1305.go b/chacha20poly1305/chacha20poly1305.go new file mode 100644 index 0000000..5fce5b9 --- /dev/null +++ b/chacha20poly1305/chacha20poly1305.go @@ -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 index 0000000..9c61084 --- /dev/null +++ b/chacha20poly1305/chacha20poly1305_amd64.go @@ -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 index 0000000..d3c1ce5 --- /dev/null +++ b/chacha20poly1305/chacha20poly1305_generic.go @@ -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 index 0000000..c5c7983 --- /dev/null +++ b/chacha20poly1305/chacha20poly1305_noasm.go @@ -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) +} diff --git a/cmd/init/main.go b/cmd/init/main.go index d18a311..aac1a89 100644 --- a/cmd/init/main.go +++ b/cmd/init/main.go @@ -1,5 +1,5 @@ // udpobfs -- simple point-to-point UDP obfuscation proxy -// Copyright (C) 2023-2025 Sergey Matveev +// Copyright (C) 2023-2026 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 diff --git a/cmd/resp/main.go b/cmd/resp/main.go index 9a6af96..03e4d35 100644 --- a/cmd/resp/main.go +++ b/cmd/resp/main.go @@ -1,5 +1,5 @@ // udpobfs -- simple point-to-point UDP obfuscation proxy -// Copyright (C) 2023-2025 Sergey Matveev +// Copyright (C) 2023-2026 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 diff --git a/crypto.go b/crypto.go index d440bb5..c1f5fda 100644 --- a/crypto.go +++ b/crypto.go @@ -1,5 +1,5 @@ // udpobfs -- simple point-to-point UDP obfuscation proxy -// Copyright (C) 2023-2025 Sergey Matveev +// Copyright (C) 2023-2026 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 diff --git a/foo/main.go b/foo/main.go new file mode 100644 index 0000000..e6e2a8c --- /dev/null +++ b/foo/main.go @@ -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 index 0000000..b41b404 --- /dev/null +++ b/foo_test.go @@ -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) + } +} diff --git a/utils.go b/utils.go index b48d27e..4db7c87 100644 --- a/utils.go +++ b/utils.go @@ -1,5 +1,5 @@ // udpobfs -- simple point-to-point UDP obfuscation proxy -// Copyright (C) 2023-2025 Sergey Matveev +// Copyright (C) 2023-2026 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 diff --git a/x509.go b/x509.go index e472457..9cac55e 100644 --- a/x509.go +++ b/x509.go @@ -1,5 +1,5 @@ // udpobfs -- simple point-to-point UDP obfuscation proxy -// Copyright (C) 2023-2025 Sergey Matveev +// Copyright (C) 2023-2026 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