-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathchunk_aead.go
129 lines (112 loc) · 3.19 KB
/
chunk_aead.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package vmess
import (
"crypto/cipher"
"encoding/binary"
"io"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
N "github.com/sagernet/sing/common/network"
)
type AEADReader struct {
upstream N.ExtendedReader
cipher cipher.AEAD
nonce []byte
nonceCount uint16
}
func NewAEADReader(upstream io.Reader, cipher cipher.AEAD, nonce []byte) *AEADReader {
readNonce := make([]byte, cipher.NonceSize())
copy(readNonce, nonce)
return &AEADReader{
upstream: bufio.NewExtendedReader(upstream),
cipher: cipher,
nonce: readNonce,
}
}
func NewAes128GcmReader(upstream io.Reader, key []byte, nonce []byte) *AEADReader {
return NewAEADReader(upstream, newAesGcm(key), nonce)
}
func NewChacha20Poly1305Reader(upstream io.Reader, key []byte, nonce []byte) *AEADReader {
return NewAEADReader(upstream, newChacha20Poly1305(GenerateChacha20Poly1305Key(key)), nonce)
}
func (r *AEADReader) Read(p []byte) (n int, err error) {
n, err = r.upstream.Read(p)
if err != nil {
return
}
binary.BigEndian.PutUint16(r.nonce, r.nonceCount)
r.nonceCount += 1
_, err = r.cipher.Open(p[:0], r.nonce, p[:n], nil)
if err != nil {
return
}
n -= CipherOverhead
return
}
func (r *AEADReader) ReadBuffer(buffer *buf.Buffer) error {
err := r.upstream.ReadBuffer(buffer)
if err != nil {
return err
}
binary.BigEndian.PutUint16(r.nonce, r.nonceCount)
r.nonceCount += 1
_, err = r.cipher.Open(buffer.Index(0), r.nonce, buffer.Bytes(), nil)
if err != nil {
return err
}
buffer.Truncate(buffer.Len() - CipherOverhead)
return nil
}
func (r *AEADReader) Upstream() any {
return r.upstream
}
type AEADWriter struct {
upstream N.ExtendedWriter
cipher cipher.AEAD
nonce []byte
nonceCount uint16
}
func NewAEADWriter(upstream io.Writer, cipher cipher.AEAD, nonce []byte) *AEADWriter {
writeNonce := make([]byte, cipher.NonceSize())
copy(writeNonce, nonce)
return &AEADWriter{
upstream: bufio.NewExtendedWriter(upstream),
cipher: cipher,
nonce: writeNonce,
}
}
func NewAes128GcmWriter(upstream io.Writer, key []byte, nonce []byte) *AEADWriter {
return NewAEADWriter(upstream, newAesGcm(key), nonce)
}
func NewChacha20Poly1305Writer(upstream io.Writer, key []byte, nonce []byte) *AEADWriter {
return NewAEADWriter(upstream, newChacha20Poly1305(GenerateChacha20Poly1305Key(key)), nonce)
}
func (w *AEADWriter) Write(p []byte) (n int, err error) {
// TODO: fix stack buffer
return bufio.WriteBuffer(w, buf.As(p))
/*_buffer := buf.StackNewSize(len(p) + CipherOverhead)
defer common.KeepAlive(_buffer)
buffer := _buffer
defer buffer.Release()
binary.BigEndian.PutUint16(w.nonce, w.nonceCount)
w.nonceCount += 1
w.cipher.Seal(buffer.Index(0), w.nonce, p, nil)
buffer.Truncate(buffer.FreeLen())
_, err = w.upstream.Write(buffer.Bytes())
if err == nil {
n = len(p)
}
return*/
}
func (w *AEADWriter) WriteBuffer(buffer *buf.Buffer) error {
binary.BigEndian.PutUint16(w.nonce, w.nonceCount)
w.nonceCount += 1
w.cipher.Seal(buffer.Index(0), w.nonce, buffer.Bytes(), nil)
buffer.Extend(CipherOverhead)
return w.upstream.WriteBuffer(buffer)
}
func (w *AEADWriter) RearHeadroom() int {
return CipherOverhead
}
func (w *AEADWriter) Upstream() any {
return w.upstream
}