Skip to content
This repository was archived by the owner on Apr 9, 2020. It is now read-only.

Commit 6a03846

Browse files
authored
Merge pull request #477 from ssoxer/independent-ivs
Generate independent IVs in the server
2 parents ac922d1 + 1c9f757 commit 6a03846

File tree

3 files changed

+92
-24
lines changed

3 files changed

+92
-24
lines changed

Diff for: shadowsocks/conn.go

-15
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,6 @@ func Dial(addr, server string, cipher *Cipher) (c *Conn, err error) {
7878
return DialWithRawAddr(ra, server, cipher)
7979
}
8080

81-
func (c *Conn) GetIv() (iv []byte) {
82-
iv = make([]byte, len(c.iv))
83-
copy(iv, c.iv)
84-
return
85-
}
86-
87-
func (c *Conn) GetKey() (key []byte) {
88-
key = make([]byte, len(c.key))
89-
copy(key, c.key)
90-
return
91-
}
92-
9381
func (c *Conn) Read(b []byte) (n int, err error) {
9482
if c.dec == nil {
9583
iv := make([]byte, c.info.ivLen)
@@ -99,9 +87,6 @@ func (c *Conn) Read(b []byte) (n int, err error) {
9987
if err = c.initDecrypt(iv); err != nil {
10088
return
10189
}
102-
if len(c.iv) == 0 {
103-
c.iv = iv
104-
}
10590
}
10691

10792
cipherData := c.readBuf

Diff for: shadowsocks/conn_test.go

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package shadowsocks
2+
3+
import (
4+
"bytes"
5+
"io"
6+
"net"
7+
"testing"
8+
)
9+
10+
func mustNewCipher(method string) *Cipher {
11+
const testPassword = "password"
12+
cipher, err := NewCipher(method, testPassword)
13+
if err != nil {
14+
panic(err)
15+
}
16+
return cipher
17+
}
18+
19+
type transcriptConn struct {
20+
net.Conn
21+
ReadTranscript []byte
22+
}
23+
24+
func (conn *transcriptConn) Read(p []byte) (int, error) {
25+
n, err := conn.Conn.Read(p)
26+
conn.ReadTranscript = append(conn.ReadTranscript, p[:n]...)
27+
return n, err
28+
}
29+
30+
func connIVs(method string) (clientIV, serverIV []byte, err error) {
31+
// underlying network connection
32+
clientConn, serverConn := net.Pipe()
33+
// make a transcript of bytes at the network level
34+
clientTranscriptConn := &transcriptConn{Conn: clientConn}
35+
serverTranscriptConn := &transcriptConn{Conn: serverConn}
36+
// connection at the ShadowSocks level
37+
clientSSConn := NewConn(clientTranscriptConn, mustNewCipher(method))
38+
serverSSConn := NewConn(serverTranscriptConn, mustNewCipher(method))
39+
40+
clientToServerData := []byte("clientToServerData")
41+
serverToClientData := []byte("serverToClientData")
42+
43+
go func() {
44+
defer serverSSConn.Close()
45+
buf := make([]byte, len(clientToServerData))
46+
// read the client IV
47+
_, err := io.ReadFull(serverSSConn, buf)
48+
if err != nil {
49+
return
50+
}
51+
// send the server IV
52+
_, err = serverSSConn.Write(serverToClientData)
53+
if err != nil {
54+
return
55+
}
56+
}()
57+
58+
// send the client IV
59+
_, err = clientSSConn.Write(clientToServerData)
60+
if err != nil {
61+
return
62+
}
63+
// read the server IV
64+
buf := make([]byte, len(serverToClientData))
65+
_, err = io.ReadFull(clientSSConn, buf)
66+
if err != nil {
67+
return
68+
}
69+
70+
// pull the IVs out of the network transcripts
71+
clientIV = serverTranscriptConn.ReadTranscript[:clientSSConn.Cipher.info.ivLen]
72+
serverIV = clientTranscriptConn.ReadTranscript[:serverSSConn.Cipher.info.ivLen]
73+
74+
return
75+
}
76+
77+
func TestIndependentIVs(t *testing.T) {
78+
for method := range cipherMethod {
79+
clientIV, serverIV, err := connIVs(method)
80+
if err != nil {
81+
t.Errorf("%s connection error: %s", method, err)
82+
continue
83+
}
84+
if bytes.Equal(clientIV, serverIV) {
85+
t.Errorf("%s equal client and server IVs", method)
86+
continue
87+
}
88+
}
89+
}

Diff for: shadowsocks/encrypt.go

+3-9
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ type Cipher struct {
188188
dec cipher.Stream
189189
key []byte
190190
info *cipherInfo
191-
iv []byte
192191
}
193192

194193
// NewCipher creates a cipher that can be used in Dial() etc.
@@ -215,14 +214,9 @@ func NewCipher(method, password string) (c *Cipher, err error) {
215214

216215
// Initializes the block cipher with CFB mode, returns IV.
217216
func (c *Cipher) initEncrypt() (iv []byte, err error) {
218-
if c.iv == nil {
219-
iv = make([]byte, c.info.ivLen)
220-
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
221-
return nil, err
222-
}
223-
c.iv = iv
224-
} else {
225-
iv = c.iv
217+
iv = make([]byte, c.info.ivLen)
218+
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
219+
return nil, err
226220
}
227221
c.enc, err = c.info.newStream(c.key, iv, Encrypt)
228222
return

0 commit comments

Comments
 (0)