1
1
package crypto
2
2
3
3
import (
4
- "crypto/cipher"
5
- "io"
6
- "errors"
7
4
"crypto/aes"
5
+ "errors"
6
+ "io"
7
+ "net"
8
+ "crypto/cipher"
8
9
)
9
10
10
11
type readWriter struct {
@@ -68,36 +69,35 @@ func (ed *StreamEncryptDecrypter) initCipherStream() error {
68
69
// corresponding ciphertext io.ReadWriter. Any ciphertext write to returned
69
70
// io.ReadWriter will be decrypted and write to plaintext. Any plaintext read
70
71
// from plaintext will be encrypted and write to returned io.ReadWriter.
71
- func (ed * StreamEncryptDecrypter ) Ciphertext (plaintext io. ReadWriter ) (io. ReadWriter , error ) {
72
+ func (ed * StreamEncryptDecrypter ) Ciphertext (plaintext net. Conn ) (net. Conn , error ) {
72
73
if err := ed .initCipherStream (); err != nil {
73
74
return nil , err
74
75
}
75
76
76
77
// logic here could be simpler if golang has a built-in duplex pipe.
77
- // net.Pipe is a solution, but seems too heavy,
78
- // with possibility of causing memory leak if not careful
79
78
cipherRdIn , cipherWtOut := io .Pipe ()
80
79
cipherRdOut , cipherWtIn := io .Pipe ()
81
80
82
- ciphertext := & readWriter {
83
- cipherRdOut ,
84
- cipherWtOut ,
81
+ ciphertext := & CipherConn {
82
+ & readWriter {
83
+ cipherRdOut ,
84
+ cipherWtOut ,
85
+ },
86
+ plaintext ,
85
87
}
86
88
87
89
// decrypt ciphertext to plaintext
88
90
go func () {
89
91
decrypter := & cipher.StreamReader {S : ed .DecryptStream , R : cipherRdIn }
90
92
io .Copy (plaintext , decrypter )
91
- cipherWtOut .Close ()
92
- cipherRdIn .Close ()
93
+ ciphertext .Close () // which close the underlying plaintext
93
94
}()
94
95
95
96
// encrypt plaintext to ciphertext
96
97
go func () {
97
98
encrypter := & cipher.StreamWriter {S : ed .EncryptStream , W : cipherWtIn }
98
99
io .Copy (encrypter , plaintext )
99
- cipherWtIn .Close ()
100
- cipherRdOut .Close ()
100
+ ciphertext .Close ()
101
101
}()
102
102
103
103
return ciphertext , nil
@@ -107,34 +107,55 @@ func (ed *StreamEncryptDecrypter) Ciphertext(plaintext io.ReadWriter) (io.ReadWr
107
107
// corresponding plaintext io.ReadWriter. Any plaintext write to returned
108
108
// io.ReadWriter will be encrypted and write to ciphertext. Any ciphertext read
109
109
// from ciphertext will be decrypted and write to returned io.ReadWriter.
110
- func (ed * StreamEncryptDecrypter ) Plaintext (ciphertext io. ReadWriter ) (io. ReadWriter , error ) {
110
+ func (ed * StreamEncryptDecrypter ) Plaintext (ciphertext net. Conn ) (net. Conn , error ) {
111
111
if err := ed .initCipherStream (); err != nil {
112
112
return nil , err
113
113
}
114
114
115
115
plainRdIn , plainWtOut := io .Pipe ()
116
116
plainRdOut , plainWtIn := io .Pipe ()
117
117
118
- plaintext := & readWriter {
119
- plainRdOut ,
120
- plainWtOut ,
118
+ plaintext := & CipherConn {
119
+ & readWriter {
120
+ plainRdOut ,
121
+ plainWtOut ,
122
+ },
123
+ ciphertext ,
121
124
}
122
125
123
126
// encrypt plaintext to ciphertext
124
127
go func () {
125
128
encrypter := & cipher.StreamWriter {S : ed .EncryptStream , W : ciphertext }
126
129
io .Copy (encrypter , plainRdIn )
127
- plainWtIn .Close ()
128
- plainRdOut .Close ()
130
+ plaintext .Close ()
129
131
}()
130
132
131
133
// decrypt ciphertext to plaintext
132
134
go func () {
133
135
decrypter := & cipher.StreamReader {S : ed .DecryptStream , R : ciphertext }
134
136
io .Copy (plainWtIn , decrypter )
135
- plainWtOut .Close ()
136
- plainRdIn .Close ()
137
+ plaintext .Close ()
137
138
}()
138
139
139
140
return plaintext , nil
140
- }
141
+ }
142
+
143
+ // CipherConn implements net.Conn interface, with a underlying io.ReadWriter.
144
+ type CipherConn struct {
145
+ io.ReadWriter
146
+ net.Conn
147
+ }
148
+
149
+ func (c * CipherConn ) Read (b []byte ) (n int , err error ) {
150
+ if _ , err := c .Conn .Read ([]byte {}); err != nil {
151
+ return 0 , err
152
+ }
153
+ return c .ReadWriter .Read (b )
154
+ }
155
+
156
+ func (c * CipherConn ) Write (b []byte ) (n int , err error ) {
157
+ if _ , err := c .Conn .Write ([]byte {}); err != nil {
158
+ return 0 , err
159
+ }
160
+ return c .ReadWriter .Write (b )
161
+ }
0 commit comments