Skip to content

Commit 8d12322

Browse files
committed
fixed
1 parent 5ab4b51 commit 8d12322

File tree

4 files changed

+206
-14
lines changed

4 files changed

+206
-14
lines changed

cipher/salsa20/salsa20.go

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,20 @@ type Cipher struct {
1818

1919
// key is 32 bytes, nonce is 8 bytes.
2020
func NewCipher(key, nonce []byte) (cipher.Stream, error) {
21-
var fixedSizedKey [32]byte
22-
if len(key) != 32 {
23-
return nil, errors.New("go-cryptobin/salsa20: key size must be 32")
24-
}
25-
26-
copy(fixedSizedKey[:], key)
27-
28-
return &Cipher{
29-
key: fixedSizedKey,
30-
nonce: nonce,
31-
}, nil
21+
return NewCipherWithCounter(key, nonce, 0)
3222
}
3323

3424
// key is 32 bytes, nonce is 8 bytes.
3525
func NewCipherWithCounter(key, nonce []byte, counter uint64) (cipher.Stream, error) {
36-
var fixedSizedKey [32]byte
3726
if len(key) != 32 {
3827
return nil, errors.New("go-cryptobin/salsa20: key size must be 32")
3928
}
4029

30+
if len(nonce) != 8 {
31+
return nil, errors.New("go-cryptobin/salsa20: nonce size must be 8 bytes")
32+
}
33+
34+
var fixedSizedKey [32]byte
4135
copy(fixedSizedKey[:], key)
4236

4337
return &Cipher{

cipher/salsa20/salsa20_test.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"math/rand"
77
)
88

9-
func Test_Salsa20(t *testing.T) {
9+
func Test_NewCipher(t *testing.T) {
1010
random := rand.New(rand.NewSource(99))
1111
max := 5000
1212

@@ -18,7 +18,7 @@ func Test_Salsa20(t *testing.T) {
1818
random.Read(key)
1919
value := make([]byte, 12)
2020
random.Read(value)
21-
nonce := make([]byte, 16)
21+
nonce := make([]byte, 8)
2222
random.Read(nonce)
2323

2424
cipher1, err := NewCipher(key, nonce)
@@ -44,3 +44,42 @@ func Test_Salsa20(t *testing.T) {
4444
}
4545
}
4646
}
47+
48+
func Test_NewCipherWithCounter(t *testing.T) {
49+
random := rand.New(rand.NewSource(99))
50+
max := 5000
51+
52+
var encrypted [12]byte
53+
var decrypted [12]byte
54+
55+
for i := 0; i < max; i++ {
56+
key := make([]byte, 32)
57+
random.Read(key)
58+
value := make([]byte, 12)
59+
random.Read(value)
60+
nonce := make([]byte, 8)
61+
random.Read(nonce)
62+
63+
cipher1, err := NewCipherWithCounter(key, nonce, 1)
64+
if err != nil {
65+
t.Fatal(err.Error())
66+
}
67+
68+
cipher1.XORKeyStream(encrypted[:], value)
69+
70+
if bytes.Equal(encrypted[:], value[:]) {
71+
t.Errorf("fail: encrypted equal value\n")
72+
}
73+
74+
cipher2, err := NewCipherWithCounter(key, nonce, 1)
75+
if err != nil {
76+
t.Fatal(err.Error())
77+
}
78+
79+
cipher2.XORKeyStream(decrypted[:], encrypted[:])
80+
81+
if !bytes.Equal(decrypted[:], value[:]) {
82+
t.Errorf("encryption/decryption failed: % 02x != % 02x\n", decrypted, value)
83+
}
84+
}
85+
}

cipher/xsalsa20/xsalsa20.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package xsalsa20
2+
3+
import (
4+
"errors"
5+
"crypto/cipher"
6+
"encoding/binary"
7+
8+
"golang.org/x/crypto/salsa20/salsa"
9+
10+
"github.com/deatil/go-cryptobin/tool/alias"
11+
)
12+
13+
type Cipher struct {
14+
nonce []byte
15+
key [32]byte
16+
counter uint64
17+
}
18+
19+
// key is 32 bytes, nonce is 24 bytes.
20+
func NewCipher(key, nonce []byte) (cipher.Stream, error) {
21+
return NewCipherWithCounter(key, nonce, 0)
22+
}
23+
24+
// key is 32 bytes, nonce is 24 bytes.
25+
func NewCipherWithCounter(key, nonce []byte, counter uint64) (cipher.Stream, error) {
26+
if len(key) != 32 {
27+
return nil, errors.New("go-cryptobin/xsalsa20: key size must be 32")
28+
}
29+
30+
if len(nonce) != 24 {
31+
return nil, errors.New("go-cryptobin/xsalsa20: nonce size must be 24 bytes")
32+
}
33+
34+
var fixedSizedKey [32]byte
35+
copy(fixedSizedKey[:], key)
36+
37+
var subKey [32]byte
38+
var hNonce [16]byte
39+
copy(hNonce[:], nonce[:16])
40+
salsa.HSalsa20(&subKey, &hNonce, &fixedSizedKey, &salsa.Sigma)
41+
nonce = nonce[16:]
42+
fixedSizedKey = subKey
43+
44+
return &Cipher{
45+
key: fixedSizedKey,
46+
nonce: nonce,
47+
counter: counter,
48+
}, nil
49+
}
50+
51+
func (c *Cipher) XORKeyStream(dst, src []byte) {
52+
if len(src) == 0 {
53+
return
54+
}
55+
if len(dst) < len(src) {
56+
panic("go-cryptobin/xsalsa20: output smaller than input")
57+
}
58+
if alias.InexactOverlap(dst[:len(src)], src) {
59+
panic("go-cryptobin/xsalsa20: invalid buffer overlap")
60+
}
61+
62+
paddingLength := int(c.counter % 64)
63+
buf := make([]byte, len(src)+paddingLength)
64+
65+
var subNonce [16]byte
66+
copy(subNonce[:], c.nonce)
67+
binary.LittleEndian.PutUint64(subNonce[8:], c.counter/64)
68+
69+
copy(buf[paddingLength:], src)
70+
salsa.XORKeyStream(buf, buf, &subNonce, &c.key)
71+
copy(dst, buf[paddingLength:])
72+
73+
c.counter += uint64(len(src))
74+
}

cipher/xsalsa20/xsalsa20_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package xsalsa20
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
"math/rand"
7+
)
8+
9+
func Test_NewCipher(t *testing.T) {
10+
random := rand.New(rand.NewSource(99))
11+
max := 5000
12+
13+
var encrypted [12]byte
14+
var decrypted [12]byte
15+
16+
for i := 0; i < max; i++ {
17+
key := make([]byte, 32)
18+
random.Read(key)
19+
value := make([]byte, 12)
20+
random.Read(value)
21+
nonce := make([]byte, 24)
22+
random.Read(nonce)
23+
24+
cipher1, err := NewCipher(key, nonce)
25+
if err != nil {
26+
t.Fatal(err.Error())
27+
}
28+
29+
cipher1.XORKeyStream(encrypted[:], value)
30+
31+
if bytes.Equal(encrypted[:], value[:]) {
32+
t.Errorf("fail: encrypted equal value\n")
33+
}
34+
35+
cipher2, err := NewCipher(key, nonce)
36+
if err != nil {
37+
t.Fatal(err.Error())
38+
}
39+
40+
cipher2.XORKeyStream(decrypted[:], encrypted[:])
41+
42+
if !bytes.Equal(decrypted[:], value[:]) {
43+
t.Errorf("encryption/decryption failed: % 02x != % 02x\n", decrypted, value)
44+
}
45+
}
46+
}
47+
48+
func Test_NewCipherWithCounter(t *testing.T) {
49+
random := rand.New(rand.NewSource(99))
50+
max := 5000
51+
52+
var encrypted [12]byte
53+
var decrypted [12]byte
54+
55+
for i := 0; i < max; i++ {
56+
key := make([]byte, 32)
57+
random.Read(key)
58+
value := make([]byte, 12)
59+
random.Read(value)
60+
nonce := make([]byte, 24)
61+
random.Read(nonce)
62+
63+
cipher1, err := NewCipherWithCounter(key, nonce, 2)
64+
if err != nil {
65+
t.Fatal(err.Error())
66+
}
67+
68+
cipher1.XORKeyStream(encrypted[:], value)
69+
70+
if bytes.Equal(encrypted[:], value[:]) {
71+
t.Errorf("fail: encrypted equal value\n")
72+
}
73+
74+
cipher2, err := NewCipherWithCounter(key, nonce, 2)
75+
if err != nil {
76+
t.Fatal(err.Error())
77+
}
78+
79+
cipher2.XORKeyStream(decrypted[:], encrypted[:])
80+
81+
if !bytes.Equal(decrypted[:], value[:]) {
82+
t.Errorf("encryption/decryption failed: % 02x != % 02x\n", decrypted, value)
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)