Skip to content

Commit 5edcb0f

Browse files
authored
sm4: move implementation detail to internal
1 parent 65a69ad commit 5edcb0f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+156
-0
lines changed
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

sm4/sm4.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Package sm4 implements ShangMi(SM) sm4 symmetric encryption algorithm.
2+
package sm4
3+
4+
import (
5+
"crypto/cipher"
6+
"strconv"
7+
8+
"github.com/emmansun/gmsm/internal/sm4"
9+
)
10+
11+
// BlockSize the sm4 block size in bytes.
12+
const BlockSize = 16
13+
14+
type KeySizeError int
15+
16+
func (k KeySizeError) Error() string {
17+
return "sm4: invalid key size " + strconv.Itoa(int(k))
18+
}
19+
20+
// NewCipher creates and returns a new [cipher.Block] implementation.
21+
// The key argument should be the SM4 key, must be 16 bytes long.
22+
func NewCipher(key []byte) (cipher.Block, error) {
23+
k := len(key)
24+
switch k {
25+
default:
26+
return nil, KeySizeError(k)
27+
case 16:
28+
break
29+
}
30+
return sm4.NewCipher(key)
31+
}

sm4/sm4_test.go

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package sm4
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
"github.com/emmansun/gmsm/internal/cryptotest"
8+
)
9+
10+
type CryptTest struct {
11+
key []byte
12+
in []byte
13+
out []byte
14+
}
15+
16+
var encryptTests = []CryptTest{
17+
{
18+
// Appendix 1.
19+
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
20+
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
21+
[]byte{0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46},
22+
},
23+
}
24+
25+
func Test_sample1(t *testing.T) {
26+
src := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
27+
expected := []byte{0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46}
28+
c, err := NewCipher(src)
29+
if err != nil {
30+
t.Fatal(err)
31+
}
32+
dst := make([]byte, 16)
33+
c.Encrypt(dst, src)
34+
if !reflect.DeepEqual(dst, expected) {
35+
t.Errorf("expected=%x, result=%x\n", expected, dst)
36+
}
37+
c.Decrypt(dst, expected)
38+
if !reflect.DeepEqual(dst, src) {
39+
t.Errorf("expected=%x, result=%x\n", src, dst)
40+
}
41+
}
42+
43+
func Test_sample2(t *testing.T) {
44+
src := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
45+
expected := []byte{0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66}
46+
c, err := NewCipher(src)
47+
if err != nil {
48+
t.Fatal(err)
49+
}
50+
dst := make([]byte, 16)
51+
copy(dst, src)
52+
n := 1000000
53+
if testing.Short() {
54+
n = 1000
55+
expected = []byte{215, 53, 233, 28, 197, 104, 156, 243, 18, 188, 193, 239, 183, 64, 232, 19}
56+
}
57+
for i := 0; i < n; i++ {
58+
c.Encrypt(dst, dst)
59+
}
60+
if !reflect.DeepEqual(dst, expected) {
61+
t.Errorf("expected=%x, result=%x\n", expected, dst)
62+
}
63+
}
64+
65+
func TestEncryptDecryptPanic(t *testing.T) {
66+
key := make([]byte, 16)
67+
src := make([]byte, 15)
68+
dst := make([]byte, 16)
69+
c, err := NewCipher(key)
70+
if err != nil {
71+
t.Fatal(err)
72+
}
73+
shouldPanic(t, func() { c.Encrypt(dst, src) })
74+
shouldPanic(t, func() { c.Encrypt(src, dst) })
75+
shouldPanic(t, func() { c.Decrypt(dst, src) })
76+
shouldPanic(t, func() { c.Decrypt(src, dst) })
77+
78+
src = make([]byte, 32)
79+
shouldPanic(t, func() { c.Encrypt(src, src[1:]) })
80+
shouldPanic(t, func() { c.Encrypt(src[1:], src) })
81+
shouldPanic(t, func() { c.Decrypt(src, src[1:]) })
82+
shouldPanic(t, func() { c.Decrypt(src[1:], src) })
83+
}
84+
85+
func shouldPanic(t *testing.T, f func()) {
86+
t.Helper()
87+
defer func() { _ = recover() }()
88+
f()
89+
t.Errorf("should have panicked")
90+
}
91+
92+
// Test SM4 against the general cipher.Block interface tester
93+
func TestSM4Block(t *testing.T) {
94+
t.Run("SM4", func(t *testing.T) {
95+
cryptotest.TestBlock(t, 16, NewCipher)
96+
})
97+
}
98+
99+
func BenchmarkEncrypt(b *testing.B) {
100+
tt := encryptTests[0]
101+
c, err := NewCipher(tt.key)
102+
if err != nil {
103+
b.Fatal("NewCipher:", err)
104+
}
105+
out := make([]byte, len(tt.in))
106+
b.SetBytes(int64(len(out)))
107+
b.ResetTimer()
108+
for i := 0; i < b.N; i++ {
109+
c.Encrypt(out, tt.in)
110+
}
111+
}
112+
113+
func BenchmarkDecrypt(b *testing.B) {
114+
tt := encryptTests[0]
115+
c, err := NewCipher(tt.key)
116+
if err != nil {
117+
b.Fatal("NewCipher:", err)
118+
}
119+
out := make([]byte, len(tt.out))
120+
b.SetBytes(int64(len(out)))
121+
b.ResetTimer()
122+
for i := 0; i < b.N; i++ {
123+
c.Decrypt(out, tt.out)
124+
}
125+
}

0 commit comments

Comments
 (0)