Skip to content

Commit

Permalink
Merge pull request #83 from genzj/add-salsa20-dev
Browse files Browse the repository at this point in the history
Add salsa20 crypto
  • Loading branch information
cyfdecyf committed Apr 6, 2015
2 parents ec0eca9 + 5fcd2fd commit 86278f4
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 0 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -4,6 +4,7 @@ go:
install:
- go get golang.org/x/crypto/blowfish
- go get golang.org/x/crypto/cast5
- go get golang.org/x/crypto/salsa20
- go install ./cmd/shadowsocks-local
- go install ./cmd/shadowsocks-server
script:
Expand Down
27 changes: 27 additions & 0 deletions shadowsocks/encrypt.go
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"golang.org/x/crypto/blowfish"
"golang.org/x/crypto/cast5"
"golang.org/x/crypto/salsa20/salsa"
"crypto/aes"
"crypto/cipher"
"crypto/des"
Expand Down Expand Up @@ -137,6 +138,31 @@ func newRC4MD5Stream(key, iv []byte, _ DecOrEnc) (cipher.Stream, error) {
return rc4.NewCipher(rc4key)
}

type salsaStreamCipher struct {
nonce [8]byte
key [32]byte
counter int
}

func (c *salsaStreamCipher) XORKeyStream(dst, src []byte) {
var subNonce [16]byte
padlen := c.counter % 64
buf := make([]byte, padlen+len(src))
copy(buf[padlen:], src[:])
copy(subNonce[:], c.nonce[:])
binary.LittleEndian.PutUint64(subNonce[len(c.nonce):], uint64(c.counter / 64))
salsa.XORKeyStream(buf, buf, &subNonce, &c.key)
copy(dst, buf[padlen:])
c.counter += len(src)
}

func newSalsa20Stream(key, iv []byte, _ DecOrEnc) (cipher.Stream, error) {
var c salsaStreamCipher
copy(c.nonce[:], iv[:8])
copy(c.key[:], key[:32])
return &c, nil
}

type cipherInfo struct {
keyLen int
ivLen int
Expand All @@ -153,6 +179,7 @@ var cipherMethod = map[string]*cipherInfo{
"rc4-md5": {16, 16, newRC4MD5Stream},
"rc4": {16, 0, nil},
"table": {16, 0, nil},
"salsa20": {32, 8, newSalsa20Stream},
}

func CheckCipherMethod(method string) error {
Expand Down
127 changes: 127 additions & 0 deletions shadowsocks/encrypt_test.go
Expand Up @@ -3,6 +3,8 @@ package shadowsocks
import (
"crypto/rc4"
"reflect"
"io"
"crypto/rand"
"testing"
)

Expand Down Expand Up @@ -144,11 +146,15 @@ func TestRC4MD5(t *testing.T) {
}

var cipherKey = make([]byte, 64)
var cipherIv = make([]byte, 64)

const CIPHER_BENCHMARK_BUFFER_LEN = 4096

func init() {
for i := 0; i < len(cipherKey); i++ {
cipherKey[i] = byte(i)
}
io.ReadFull(rand.Reader, cipherIv)
}

func BenchmarkRC4Init(b *testing.B) {
Expand Down Expand Up @@ -200,3 +206,124 @@ func BenchmarkRC4MD5Init(b *testing.B) {
ci := cipherMethod["rc4-md5"]
benchmarkCipherInit(b, ci)
}

func BenchmarkSalsa20Init(b *testing.B) {
ci := cipherMethod["salsa20"]
benchmarkCipherInit(b, ci)
}

func benchmarkCipherEncrypt(b *testing.B, ci *cipherInfo) {
key := cipherKey[:ci.keyLen]
iv := cipherIv[:ci.ivLen]
enc, err := ci.newStream(key, iv, Encrypt)
if err != nil {
b.Error(err)
}
src := make([]byte, CIPHER_BENCHMARK_BUFFER_LEN)
dst := make([]byte, CIPHER_BENCHMARK_BUFFER_LEN)
io.ReadFull(rand.Reader, src)
for i := 0; i < b.N; i++ {
enc.XORKeyStream(dst, src)
}
}

func BenchmarkAES128Encrypt(b *testing.B) {
ci := cipherMethod["aes-128-cfb"]
benchmarkCipherEncrypt(b, ci)
}

func BenchmarkAES192Encrypt(b *testing.B) {
ci := cipherMethod["aes-192-cfb"]
benchmarkCipherEncrypt(b, ci)
}

func BenchmarkAES256Encrypt(b *testing.B) {
ci := cipherMethod["aes-256-cfb"]
benchmarkCipherEncrypt(b, ci)
}

func BenchmarkBlowFishEncrypt(b *testing.B) {
ci := cipherMethod["bf-cfb"]
benchmarkCipherEncrypt(b, ci)
}

func BenchmarkCast5Encrypt(b *testing.B) {
ci := cipherMethod["bf-cfb"]
benchmarkCipherEncrypt(b, ci)
}

func BenchmarkDESEncrypt(b *testing.B) {
ci := cipherMethod["des-cfb"]
benchmarkCipherEncrypt(b, ci)
}

func BenchmarkRC4MD5Encrypt(b *testing.B) {
ci := cipherMethod["rc4-md5"]
benchmarkCipherEncrypt(b, ci)
}

func BenchmarkSalsa20Encrypt(b *testing.B) {
ci := cipherMethod["salsa20"]
benchmarkCipherEncrypt(b, ci)
}

func benchmarkCipherDecrypt(b *testing.B, ci *cipherInfo) {
key := cipherKey[:ci.keyLen]
iv := cipherIv[:ci.ivLen]
enc, err := ci.newStream(key, iv, Encrypt)
if err != nil {
b.Error(err)
}
dec, err := ci.newStream(key, iv, Decrypt)
if err != nil {
b.Error(err)
}
src := make([]byte, CIPHER_BENCHMARK_BUFFER_LEN)
dst := make([]byte, CIPHER_BENCHMARK_BUFFER_LEN)
io.ReadFull(rand.Reader, src)
enc.XORKeyStream(dst, src)
for i := 0; i < b.N; i++ {
dec.XORKeyStream(src, dst)
}
}

func BenchmarkAES128Decrypt(b *testing.B) {
ci := cipherMethod["aes-128-cfb"]
benchmarkCipherDecrypt(b, ci)
}

func BenchmarkAES192Decrypt(b *testing.B) {
ci := cipherMethod["aes-192-cfb"]
benchmarkCipherDecrypt(b, ci)
}

func BenchmarkAES256Decrypt(b *testing.B) {
ci := cipherMethod["aes-256-cfb"]
benchmarkCipherDecrypt(b, ci)
}

func BenchmarkBlowFishDecrypt(b *testing.B) {
ci := cipherMethod["bf-cfb"]
benchmarkCipherDecrypt(b, ci)
}

func BenchmarkCast5Decrypt(b *testing.B) {
ci := cipherMethod["bf-cfb"]
benchmarkCipherDecrypt(b, ci)
}

func BenchmarkDESDecrypt(b *testing.B) {
ci := cipherMethod["des-cfb"]
benchmarkCipherDecrypt(b, ci)
}

func BenchmarkRC4MD5Decrypt(b *testing.B) {
ci := cipherMethod["rc4-md5"]
benchmarkCipherDecrypt(b, ci)
}

func BenchmarkSalsa20Decrypt(b *testing.B) {
ci := cipherMethod["salsa20"]
benchmarkCipherDecrypt(b, ci)
}

0 comments on commit 86278f4

Please sign in to comment.