align / change format

This commit is contained in:
Emman 2022-01-21 08:33:01 +08:00
parent 1e51a02c60
commit 4156eb1c07
9 changed files with 3069 additions and 3069 deletions

30
.gitignore vendored
View File

@ -1,15 +1,15 @@
# Binaries for programs and plugins # Binaries for programs and plugins
*.exe *.exe
*.exe~ *.exe~
*.dll *.dll
*.so *.so
*.dylib *.dylib
# Test binary, built with `go test -c` # Test binary, built with `go test -c`
*.test *.test
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out *.out
# Dependency directories (remove the comment below to include it) # Dependency directories (remove the comment below to include it)
# vendor/ # vendor/

42
LICENSE
View File

@ -1,21 +1,21 @@
MIT License MIT License
Copyright (c) 2020 Sun Yimin Copyright (c) 2020 Sun Yimin
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.

202
README.md
View File

@ -1,101 +1,101 @@
# GM-Standards SM2/SM3/SM4 for Go # GM-Standards SM2/SM3/SM4 for Go
[![Build Status](https://travis-ci.com/emmansun/gmsm.svg?branch=main)](https://travis-ci.com/emmansun/gmsm) [![Documentation](https://godoc.org/github.com/emmansun/gmsm?status.svg)](https://godoc.org/github.com/emmansun/gmsm) [![Release](https://img.shields.io/github/release/emmansun/gmsm/all.svg)](https://github.com/emmansun/gmsm/releases) [![Build Status](https://travis-ci.com/emmansun/gmsm.svg?branch=main)](https://travis-ci.com/emmansun/gmsm) [![Documentation](https://godoc.org/github.com/emmansun/gmsm?status.svg)](https://godoc.org/github.com/emmansun/gmsm) [![Release](https://img.shields.io/github/release/emmansun/gmsm/all.svg)](https://github.com/emmansun/gmsm/releases)
This is a **SM2 sm2p256v1** implementation whose performance is similar like golang native NIST P256 under **amd64** and **arm64**, for implementation detail, please refer [SM2实现细节](https://github.com/emmansun/gmsm/wiki/SM2%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96). This is a **SM2 sm2p256v1** implementation whose performance is similar like golang native NIST P256 under **amd64** and **arm64**, for implementation detail, please refer [SM2实现细节](https://github.com/emmansun/gmsm/wiki/SM2%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96).
This is also a **SM3** implementation whose performance is similar like golang native SHA 256 with SIMD under **amd64**, for implementation detail, please refer [SM3性能优化](https://github.com/emmansun/gmsm/wiki/SM3%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96). This is also a **SM3** implementation whose performance is similar like golang native SHA 256 with SIMD under **amd64**, for implementation detail, please refer [SM3性能优化](https://github.com/emmansun/gmsm/wiki/SM3%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96).
For **SM4** implementation, SIMD & AES-NI are used under **amd64** and **arm64**, for detail please refer [SM4性能优化](https://github.com/emmansun/gmsm/wiki/SM4%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96), support CBC/CFB/OFB/CTR/GCM/CCM/XTS modes. For **SM4** implementation, SIMD & AES-NI are used under **amd64** and **arm64**, for detail please refer [SM4性能优化](https://github.com/emmansun/gmsm/wiki/SM4%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96), support CBC/CFB/OFB/CTR/GCM/CCM/XTS modes.
**SM2 encryption Benchmark** **SM2 encryption Benchmark**
CPU: i5-9500 CPU: i5-9500
P-256/SM2(No tuning) P-256/SM2(No tuning)
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: gmsm/sm2 pkg: gmsm/sm2
BenchmarkLessThan32-6 210 5665861 ns/op 0.01 MB/s 2601864 B/op 27725 allocs/op BenchmarkLessThan32-6 210 5665861 ns/op 0.01 MB/s 2601864 B/op 27725 allocs/op
PASS PASS
ok gmsm/sm2 5.629s ok gmsm/sm2 5.629s
P-256/SM2(with P256/SM2 curve pure golang implementation) P-256/SM2(with P256/SM2 curve pure golang implementation)
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: gmsm/sm2 pkg: gmsm/sm2
BenchmarkLessThan32_P256SM2-6 1027 1169516 ns/op 3874 B/op 74 allocs/op BenchmarkLessThan32_P256SM2-6 1027 1169516 ns/op 3874 B/op 74 allocs/op
PASS PASS
ok gmsm/sm2 1.564s ok gmsm/sm2 1.564s
P-256/SM2(with P256/SM2 amd64 curve implementation, i think there are still improvement space for p256Sqr function) P-256/SM2(with P256/SM2 amd64 curve implementation, i think there are still improvement space for p256Sqr function)
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: github.com/emmansun/gmsm/sm2 pkg: github.com/emmansun/gmsm/sm2
BenchmarkLessThan32_P256SM2-6 10447 115618 ns/op 2357 B/op 46 allocs/op BenchmarkLessThan32_P256SM2-6 10447 115618 ns/op 2357 B/op 46 allocs/op
PASS PASS
ok github.com/emmansun/gmsm/sm2 2.199s ok github.com/emmansun/gmsm/sm2 2.199s
P-256 (SM2 based on NIST P-256 curve) P-256 (SM2 based on NIST P-256 curve)
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: gmsm/sm2 pkg: gmsm/sm2
BenchmarkMoreThan32-6 13656 86252 ns/op 3141 B/op 50 allocs/op BenchmarkMoreThan32-6 13656 86252 ns/op 3141 B/op 50 allocs/op
PASS PASS
ok gmsm/sm2 4.139s ok gmsm/sm2 4.139s
**SM3 hash Benchmark** **SM3 hash Benchmark**
CPU: i5-9500 CPU: i5-9500
Pure golang version Pure golang version
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: github.com/emmansun/gmsm/sm3 pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K-6 27097 41112 ns/op 199.26 MB/s 0 B/op 0 allocs/op BenchmarkHash8K-6 27097 41112 ns/op 199.26 MB/s 0 B/op 0 allocs/op
PASS PASS
ok github.com/emmansun/gmsm/sm3 3.463s ok github.com/emmansun/gmsm/sm3 3.463s
ASM (non-AVX2) version ASM (non-AVX2) version
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: github.com/emmansun/gmsm/sm3 pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K-6 35080 33235 ns/op 246.49 MB/s 0 B/op 0 allocs/op BenchmarkHash8K-6 35080 33235 ns/op 246.49 MB/s 0 B/op 0 allocs/op
PASS PASS
ok github.com/emmansun/gmsm/sm3 3.102s ok github.com/emmansun/gmsm/sm3 3.102s
ASM AVX2 version ASM AVX2 version
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: github.com/emmansun/gmsm/sm3 pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K-6 53208 22223 ns/op 368.63 MB/s 0 B/op 0 allocs/op BenchmarkHash8K-6 53208 22223 ns/op 368.63 MB/s 0 B/op 0 allocs/op
PASS PASS
ok github.com/emmansun/gmsm/sm3 1.720s ok github.com/emmansun/gmsm/sm3 1.720s
SHA256 ASM AVX2 version SHA256 ASM AVX2 version
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: github.com/emmansun/gmsm/sm3 pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K_SH256-6 68352 17116 ns/op 478.63 MB/s 0 B/op 0 allocs/op BenchmarkHash8K_SH256-6 68352 17116 ns/op 478.63 MB/s 0 B/op 0 allocs/op
PASS PASS
ok github.com/emmansun/gmsm/sm3 3.043s ok github.com/emmansun/gmsm/sm3 3.043s
**SM4 Benchmark** **SM4 Benchmark**
CPU: i5-9500 CPU: i5-9500
Pure golang version Pure golang version
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: github.com/emmansun/gmsm/sm4 pkg: github.com/emmansun/gmsm/sm4
BenchmarkEncrypt-6 2671431 441 ns/op 36.28 MB/s 0 B/op 0 allocs/op BenchmarkEncrypt-6 2671431 441 ns/op 36.28 MB/s 0 B/op 0 allocs/op
BenchmarkDecrypt-6 2709132 440 ns/op 36.40 MB/s 0 B/op 0 allocs/op BenchmarkDecrypt-6 2709132 440 ns/op 36.40 MB/s 0 B/op 0 allocs/op
BenchmarkExpand-6 2543746 471 ns/op 16 B/op 1 allocs/op BenchmarkExpand-6 2543746 471 ns/op 16 B/op 1 allocs/op
ASM AES-NI version ASM AES-NI version
goos: windows goos: windows
goarch: amd64 goarch: amd64
pkg: github.com/emmansun/gmsm/sm4 pkg: github.com/emmansun/gmsm/sm4
BenchmarkEncrypt-6 5881989 206 ns/op 77.75 MB/s 0 B/op 0 allocs/op BenchmarkEncrypt-6 5881989 206 ns/op 77.75 MB/s 0 B/op 0 allocs/op
BenchmarkDecrypt-6 5853994 204 ns/op 78.45 MB/s 0 B/op 0 allocs/op BenchmarkDecrypt-6 5853994 204 ns/op 78.45 MB/s 0 B/op 0 allocs/op
BenchmarkExpand-6 5985129 200 ns/op 0 B/op 0 allocs/op BenchmarkExpand-6 5985129 200 ns/op 0 B/op 0 allocs/op
PASS PASS
ok github.com/emmansun/gmsm/sm4 6.193s ok github.com/emmansun/gmsm/sm4 6.193s

16
go.mod
View File

@ -1,8 +1,8 @@
module github.com/emmansun/gmsm module github.com/emmansun/gmsm
go 1.15 go 1.15
require ( require (
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
) )

View File

@ -1,328 +1,328 @@
package sm2 package sm2
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"math/big" "math/big"
"reflect" "reflect"
"testing" "testing"
"github.com/emmansun/gmsm/sm3" "github.com/emmansun/gmsm/sm3"
) )
func Test_kdf(t *testing.T) { func Test_kdf(t *testing.T) {
x2, _ := new(big.Int).SetString("64D20D27D0632957F8028C1E024F6B02EDF23102A566C932AE8BD613A8E865FE", 16) x2, _ := new(big.Int).SetString("64D20D27D0632957F8028C1E024F6B02EDF23102A566C932AE8BD613A8E865FE", 16)
y2, _ := new(big.Int).SetString("58D225ECA784AE300A81A2D48281A828E1CEDF11C4219099840265375077BF78", 16) y2, _ := new(big.Int).SetString("58D225ECA784AE300A81A2D48281A828E1CEDF11C4219099840265375077BF78", 16)
expected := "006e30dae231b071dfad8aa379e90264491603" expected := "006e30dae231b071dfad8aa379e90264491603"
result, success := kdf(append(x2.Bytes(), y2.Bytes()...), 19) result, success := kdf(append(x2.Bytes(), y2.Bytes()...), 19)
if !success { if !success {
t.Fatalf("failed") t.Fatalf("failed")
} }
resultStr := hex.EncodeToString(result) resultStr := hex.EncodeToString(result)
if expected != resultStr { if expected != resultStr {
t.Fatalf("expected %s, real value %s", expected, resultStr) t.Fatalf("expected %s, real value %s", expected, resultStr)
} }
} }
func Test_SplicingOrder(t *testing.T) { func Test_SplicingOrder(t *testing.T) {
priv, _ := GenerateKey(rand.Reader) priv, _ := GenerateKey(rand.Reader)
tests := []struct { tests := []struct {
name string name string
plainText string plainText string
from ciphertextSplicingOrder from ciphertextSplicingOrder
to ciphertextSplicingOrder to ciphertextSplicingOrder
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
{"less than 32 1", "encryption standard", C1C2C3, C1C3C2}, {"less than 32 1", "encryption standard", C1C2C3, C1C3C2},
{"less than 32 2", "encryption standard", C1C3C2, C1C2C3}, {"less than 32 2", "encryption standard", C1C3C2, C1C2C3},
{"equals 32 1", "encryption standard encryption ", C1C2C3, C1C3C2}, {"equals 32 1", "encryption standard encryption ", C1C2C3, C1C3C2},
{"equals 32 2", "encryption standard encryption ", C1C3C2, C1C2C3}, {"equals 32 2", "encryption standard encryption ", C1C3C2, C1C2C3},
{"long than 32 1", "encryption standard encryption standard", C1C2C3, C1C3C2}, {"long than 32 1", "encryption standard encryption standard", C1C2C3, C1C3C2},
{"long than 32 2", "encryption standard encryption standard", C1C3C2, C1C2C3}, {"long than 32 2", "encryption standard encryption standard", C1C3C2, C1C2C3},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), NewPlainEncrypterOpts(MarshalUncompressed, tt.from)) ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), NewPlainEncrypterOpts(MarshalUncompressed, tt.from))
if err != nil { if err != nil {
t.Fatalf("encrypt failed %v", err) t.Fatalf("encrypt failed %v", err)
} }
plaintext, err := priv.Decrypt(rand.Reader, ciphertext, NewPlainDecrypterOpts(tt.from)) plaintext, err := priv.Decrypt(rand.Reader, ciphertext, NewPlainDecrypterOpts(tt.from))
if err != nil { if err != nil {
t.Fatalf("decrypt failed %v", err) t.Fatalf("decrypt failed %v", err)
} }
if !reflect.DeepEqual(string(plaintext), tt.plainText) { if !reflect.DeepEqual(string(plaintext), tt.plainText) {
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText) t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
} }
//Adjust splicing order //Adjust splicing order
ciphertext, err = AdjustCiphertextSplicingOrder(ciphertext, tt.from, tt.to) ciphertext, err = AdjustCiphertextSplicingOrder(ciphertext, tt.from, tt.to)
if err != nil { if err != nil {
t.Fatalf("adjust splicing order failed %v", err) t.Fatalf("adjust splicing order failed %v", err)
} }
plaintext, err = priv.Decrypt(rand.Reader, ciphertext, NewPlainDecrypterOpts(tt.to)) plaintext, err = priv.Decrypt(rand.Reader, ciphertext, NewPlainDecrypterOpts(tt.to))
if err != nil { if err != nil {
t.Fatalf("decrypt failed after adjust splicing order %v", err) t.Fatalf("decrypt failed after adjust splicing order %v", err)
} }
if !reflect.DeepEqual(string(plaintext), tt.plainText) { if !reflect.DeepEqual(string(plaintext), tt.plainText) {
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText) t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
} }
}) })
} }
} }
func Test_encryptDecrypt_ASN1(t *testing.T) { func Test_encryptDecrypt_ASN1(t *testing.T) {
priv, _ := GenerateKey(rand.Reader) priv, _ := GenerateKey(rand.Reader)
tests := []struct { tests := []struct {
name string name string
plainText string plainText string
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
{"less than 32", "encryption standard"}, {"less than 32", "encryption standard"},
{"equals 32", "encryption standard encryption "}, {"equals 32", "encryption standard encryption "},
{"long than 32", "encryption standard encryption standard"}, {"long than 32", "encryption standard encryption standard"},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
encrypterOpts := ASN1EncrypterOpts encrypterOpts := ASN1EncrypterOpts
ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), encrypterOpts) ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), encrypterOpts)
if err != nil { if err != nil {
t.Fatalf("encrypt failed %v", err) t.Fatalf("encrypt failed %v", err)
} }
plaintext, err := priv.Decrypt(rand.Reader, ciphertext, ASN1DecrypterOpts) plaintext, err := priv.Decrypt(rand.Reader, ciphertext, ASN1DecrypterOpts)
if err != nil { if err != nil {
t.Fatalf("decrypt failed %v", err) t.Fatalf("decrypt failed %v", err)
} }
if !reflect.DeepEqual(string(plaintext), tt.plainText) { if !reflect.DeepEqual(string(plaintext), tt.plainText) {
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText) t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
} }
}) })
} }
} }
func Test_Ciphertext2ASN1(t *testing.T) { func Test_Ciphertext2ASN1(t *testing.T) {
priv, _ := GenerateKey(rand.Reader) priv, _ := GenerateKey(rand.Reader)
tests := []struct { tests := []struct {
name string name string
plainText string plainText string
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
{"less than 32", "encryption standard"}, {"less than 32", "encryption standard"},
{"equals 32", "encryption standard encryption "}, {"equals 32", "encryption standard encryption "},
{"long than 32", "encryption standard encryption standard"}, {"long than 32", "encryption standard encryption standard"},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), nil) ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), nil)
if err != nil { if err != nil {
t.Fatalf("encrypt failed %v", err) t.Fatalf("encrypt failed %v", err)
} }
ciphertext, err = PlainCiphertext2ASN1(ciphertext, C1C3C2) ciphertext, err = PlainCiphertext2ASN1(ciphertext, C1C3C2)
if err != nil { if err != nil {
t.Fatalf("convert to ASN.1 failed %v", err) t.Fatalf("convert to ASN.1 failed %v", err)
} }
plaintext, err := priv.Decrypt(rand.Reader, ciphertext, ASN1DecrypterOpts) plaintext, err := priv.Decrypt(rand.Reader, ciphertext, ASN1DecrypterOpts)
if err != nil { if err != nil {
t.Fatalf("decrypt failed %v", err) t.Fatalf("decrypt failed %v", err)
} }
if !reflect.DeepEqual(string(plaintext), tt.plainText) { if !reflect.DeepEqual(string(plaintext), tt.plainText) {
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText) t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
} }
}) })
} }
} }
func Test_ASN1Ciphertext2Plain(t *testing.T) { func Test_ASN1Ciphertext2Plain(t *testing.T) {
priv, _ := GenerateKey(rand.Reader) priv, _ := GenerateKey(rand.Reader)
tests := []struct { tests := []struct {
name string name string
plainText string plainText string
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
{"less than 32", "encryption standard"}, {"less than 32", "encryption standard"},
{"equals 32", "encryption standard encryption "}, {"equals 32", "encryption standard encryption "},
{"long than 32", "encryption standard encryption standard"}, {"long than 32", "encryption standard encryption standard"},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
ciphertext, err := EncryptASN1(rand.Reader, &priv.PublicKey, []byte(tt.plainText)) ciphertext, err := EncryptASN1(rand.Reader, &priv.PublicKey, []byte(tt.plainText))
if err != nil { if err != nil {
t.Fatalf("encrypt failed %v", err) t.Fatalf("encrypt failed %v", err)
} }
ciphertext, err = ASN1Ciphertext2Plain(ciphertext, nil) ciphertext, err = ASN1Ciphertext2Plain(ciphertext, nil)
if err != nil { if err != nil {
t.Fatalf("convert to plain failed %v", err) t.Fatalf("convert to plain failed %v", err)
} }
plaintext, err := priv.Decrypt(rand.Reader, ciphertext, nil) plaintext, err := priv.Decrypt(rand.Reader, ciphertext, nil)
if err != nil { if err != nil {
t.Fatalf("decrypt failed %v", err) t.Fatalf("decrypt failed %v", err)
} }
if !reflect.DeepEqual(string(plaintext), tt.plainText) { if !reflect.DeepEqual(string(plaintext), tt.plainText) {
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText) t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
} }
}) })
} }
} }
func Test_encryptDecrypt(t *testing.T) { func Test_encryptDecrypt(t *testing.T) {
priv, _ := GenerateKey(rand.Reader) priv, _ := GenerateKey(rand.Reader)
tests := []struct { tests := []struct {
name string name string
plainText string plainText string
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
{"less than 32", "encryption standard"}, {"less than 32", "encryption standard"},
{"equals 32", "encryption standard encryption "}, {"equals 32", "encryption standard encryption "},
{"long than 32", "encryption standard encryption standard"}, {"long than 32", "encryption standard encryption standard"},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), nil) ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), nil)
if err != nil { if err != nil {
t.Fatalf("encrypt failed %v", err) t.Fatalf("encrypt failed %v", err)
} }
plaintext, err := Decrypt(priv, ciphertext) plaintext, err := Decrypt(priv, ciphertext)
if err != nil { if err != nil {
t.Fatalf("decrypt failed %v", err) t.Fatalf("decrypt failed %v", err)
} }
if !reflect.DeepEqual(string(plaintext), tt.plainText) { if !reflect.DeepEqual(string(plaintext), tt.plainText) {
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText) t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
} }
// compress mode // compress mode
encrypterOpts := NewPlainEncrypterOpts(MarshalCompressed, C1C3C2) encrypterOpts := NewPlainEncrypterOpts(MarshalCompressed, C1C3C2)
ciphertext, err = Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), encrypterOpts) ciphertext, err = Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), encrypterOpts)
if err != nil { if err != nil {
t.Fatalf("encrypt failed %v", err) t.Fatalf("encrypt failed %v", err)
} }
plaintext, err = Decrypt(priv, ciphertext) plaintext, err = Decrypt(priv, ciphertext)
if err != nil { if err != nil {
t.Fatalf("decrypt failed %v", err) t.Fatalf("decrypt failed %v", err)
} }
if !reflect.DeepEqual(string(plaintext), tt.plainText) { if !reflect.DeepEqual(string(plaintext), tt.plainText) {
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText) t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
} }
// mixed mode // mixed mode
encrypterOpts = NewPlainEncrypterOpts(MarshalMixed, C1C3C2) encrypterOpts = NewPlainEncrypterOpts(MarshalMixed, C1C3C2)
ciphertext, err = Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), encrypterOpts) ciphertext, err = Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), encrypterOpts)
if err != nil { if err != nil {
t.Fatalf("encrypt failed %v", err) t.Fatalf("encrypt failed %v", err)
} }
plaintext, err = Decrypt(priv, ciphertext) plaintext, err = Decrypt(priv, ciphertext)
if err != nil { if err != nil {
t.Fatalf("decrypt failed %v", err) t.Fatalf("decrypt failed %v", err)
} }
if !reflect.DeepEqual(string(plaintext), tt.plainText) { if !reflect.DeepEqual(string(plaintext), tt.plainText) {
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText) t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
} }
}) })
} }
} }
func Test_signVerify(t *testing.T) { func Test_signVerify(t *testing.T) {
priv, _ := GenerateKey(rand.Reader) priv, _ := GenerateKey(rand.Reader)
tests := []struct { tests := []struct {
name string name string
plainText string plainText string
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
{"less than 32", "encryption standard"}, {"less than 32", "encryption standard"},
{"equals 32", "encryption standard encryption "}, {"equals 32", "encryption standard encryption "},
{"long than 32", "encryption standard encryption standard"}, {"long than 32", "encryption standard encryption standard"},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
hash := sm3.Sum([]byte(tt.plainText)) hash := sm3.Sum([]byte(tt.plainText))
signature, err := priv.Sign(rand.Reader, hash[:], nil) signature, err := priv.Sign(rand.Reader, hash[:], nil)
if err != nil { if err != nil {
t.Fatalf("sign failed %v", err) t.Fatalf("sign failed %v", err)
} }
result := VerifyASN1(&priv.PublicKey, hash[:], signature) result := VerifyASN1(&priv.PublicKey, hash[:], signature)
if !result { if !result {
t.Fatal("verify failed") t.Fatal("verify failed")
} }
}) })
} }
} }
// Check that signatures are safe even with a broken entropy source. // Check that signatures are safe even with a broken entropy source.
func TestNonceSafety(t *testing.T) { func TestNonceSafety(t *testing.T) {
priv, _ := GenerateKey(rand.Reader) priv, _ := GenerateKey(rand.Reader)
hashed := []byte("testing") hashed := []byte("testing")
r0, s0, err := Sign(zeroReader, &priv.PrivateKey, hashed) r0, s0, err := Sign(zeroReader, &priv.PrivateKey, hashed)
if err != nil { if err != nil {
t.Errorf("SM2: error signing: %s", err) t.Errorf("SM2: error signing: %s", err)
return return
} }
hashed = []byte("testing...") hashed = []byte("testing...")
r1, s1, err := Sign(zeroReader, &priv.PrivateKey, hashed) r1, s1, err := Sign(zeroReader, &priv.PrivateKey, hashed)
if err != nil { if err != nil {
t.Errorf("SM2: error signing: %s", err) t.Errorf("SM2: error signing: %s", err)
return return
} }
if s0.Cmp(s1) == 0 { if s0.Cmp(s1) == 0 {
// This should never happen. // This should never happen.
t.Error("SM2: the signatures on two different messages were the same") t.Error("SM2: the signatures on two different messages were the same")
} }
if r0.Cmp(r1) == 0 { if r0.Cmp(r1) == 0 {
t.Error("SM2: the nonce used for two diferent messages was the same") t.Error("SM2: the nonce used for two diferent messages was the same")
} }
} }
// Check that signatures remain non-deterministic with a functional entropy source. // Check that signatures remain non-deterministic with a functional entropy source.
func TestINDCCA(t *testing.T) { func TestINDCCA(t *testing.T) {
priv, _ := GenerateKey(rand.Reader) priv, _ := GenerateKey(rand.Reader)
hashed := []byte("testing") hashed := []byte("testing")
r0, s0, err := Sign(rand.Reader, &priv.PrivateKey, hashed) r0, s0, err := Sign(rand.Reader, &priv.PrivateKey, hashed)
if err != nil { if err != nil {
t.Errorf("SM2: error signing: %s", err) t.Errorf("SM2: error signing: %s", err)
return return
} }
r1, s1, err := Sign(rand.Reader, &priv.PrivateKey, hashed) r1, s1, err := Sign(rand.Reader, &priv.PrivateKey, hashed)
if err != nil { if err != nil {
t.Errorf("SM2: error signing: %s", err) t.Errorf("SM2: error signing: %s", err)
return return
} }
if s0.Cmp(s1) == 0 { if s0.Cmp(s1) == 0 {
t.Error("SM2: two signatures of the same message produced the same result") t.Error("SM2: two signatures of the same message produced the same result")
} }
if r0.Cmp(r1) == 0 { if r0.Cmp(r1) == 0 {
t.Error("SM2: two signatures of the same message produced the same nonce") t.Error("SM2: two signatures of the same message produced the same nonce")
} }
} }
func benchmarkEncrypt(b *testing.B, curve elliptic.Curve, plaintext string) { func benchmarkEncrypt(b *testing.B, curve elliptic.Curve, plaintext string) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
priv, _ := ecdsa.GenerateKey(curve, rand.Reader) priv, _ := ecdsa.GenerateKey(curve, rand.Reader)
Encrypt(rand.Reader, &priv.PublicKey, []byte(plaintext), nil) Encrypt(rand.Reader, &priv.PublicKey, []byte(plaintext), nil)
} }
} }
func BenchmarkLessThan32_P256(b *testing.B) { func BenchmarkLessThan32_P256(b *testing.B) {
benchmarkEncrypt(b, elliptic.P256(), "encryption standard") benchmarkEncrypt(b, elliptic.P256(), "encryption standard")
} }
func BenchmarkLessThan32_P256SM2(b *testing.B) { func BenchmarkLessThan32_P256SM2(b *testing.B) {
benchmarkEncrypt(b, P256(), "encryption standard") benchmarkEncrypt(b, P256(), "encryption standard")
} }
func BenchmarkMoreThan32_P256(b *testing.B) { func BenchmarkMoreThan32_P256(b *testing.B) {
benchmarkEncrypt(b, elliptic.P256(), "encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard") benchmarkEncrypt(b, elliptic.P256(), "encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard")
} }
func BenchmarkMoreThan32_P256SM2(b *testing.B) { func BenchmarkMoreThan32_P256SM2(b *testing.B) {
benchmarkEncrypt(b, P256(), "encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard") benchmarkEncrypt(b, P256(), "encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard")
} }

View File

@ -1,79 +1,79 @@
package sm2 package sm2
import ( import (
"crypto/elliptic" "crypto/elliptic"
"encoding/hex" "encoding/hex"
"math/big" "math/big"
"reflect" "reflect"
"testing" "testing"
) )
func Test_toBytes(t *testing.T) { func Test_toBytes(t *testing.T) {
type args struct { type args struct {
value string value string
} }
tests := []struct { tests := []struct {
name string name string
args args args args
want string want string
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
{"less than 32", args{"d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, "00d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, {"less than 32", args{"d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, "00d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"},
{"equals 32", args{"58d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, "58d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, {"equals 32", args{"58d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, "58d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
v, _ := new(big.Int).SetString(tt.args.value, 16) v, _ := new(big.Int).SetString(tt.args.value, 16)
if got := toBytes(elliptic.P256(), v); !reflect.DeepEqual(hex.EncodeToString(got), tt.want) { if got := toBytes(elliptic.P256(), v); !reflect.DeepEqual(hex.EncodeToString(got), tt.want) {
t.Errorf("toBytes() = %v, want %v", hex.EncodeToString(got), tt.want) t.Errorf("toBytes() = %v, want %v", hex.EncodeToString(got), tt.want)
} }
}) })
} }
} }
func Test_getLastBitOfY(t *testing.T) { func Test_getLastBitOfY(t *testing.T) {
type args struct { type args struct {
y string y string
} }
tests := []struct { tests := []struct {
name string name string
args args args args
want uint want uint
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
{"0", args{"d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, 0}, {"0", args{"d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, 0},
{"1", args{"d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865ff"}, 1}, {"1", args{"d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865ff"}, 1},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
y, _ := new(big.Int).SetString(tt.args.y, 16) y, _ := new(big.Int).SetString(tt.args.y, 16)
if got := getLastBitOfY(y, y); got != tt.want { if got := getLastBitOfY(y, y); got != tt.want {
t.Errorf("getLastBitOfY() = %v, want %v", got, tt.want) t.Errorf("getLastBitOfY() = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func Test_toPointXY(t *testing.T) { func Test_toPointXY(t *testing.T) {
type args struct { type args struct {
bytes string bytes string
} }
tests := []struct { tests := []struct {
name string name string
args args args args
want string want string
}{ }{
// TODO: Add test cases. // TODO: Add test cases.
{"has zero padding", args{"00d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, "d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, {"has zero padding", args{"00d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, "d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"},
{"no zero padding", args{"58d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, "58d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, {"no zero padding", args{"58d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"}, "58d20d27d0632957f8028c1e024f6b02edf23102a566c932ae8bd613a8e865fe"},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
bytes, _ := hex.DecodeString(tt.args.bytes) bytes, _ := hex.DecodeString(tt.args.bytes)
expectedInt, _ := new(big.Int).SetString(tt.want, 16) expectedInt, _ := new(big.Int).SetString(tt.want, 16)
if got := toPointXY(bytes); !reflect.DeepEqual(got, expectedInt) { if got := toPointXY(bytes); !reflect.DeepEqual(got, expectedInt) {
t.Errorf("toPointXY() = %v, want %v", got, expectedInt) t.Errorf("toPointXY() = %v, want %v", got, expectedInt)
} }
}) })
} }
} }

View File

@ -1,144 +1,144 @@
package sm3 package sm3
import ( import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"encoding" "encoding"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"hash" "hash"
"io" "io"
"testing" "testing"
"golang.org/x/sys/cpu" "golang.org/x/sys/cpu"
) )
type sm3Test struct { type sm3Test struct {
out string out string
in string in string
halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal
} }
var golden = []sm3Test{ var golden = []sm3Test{
{"66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0", "abc", "sm3\x03s\x80\x16oI\x14\xb2\xb9\x17$B\xd7ڊ\x06\x00\xa9o0\xbc\x1618\xaa\xe3\x8d\xeeM\xb0\xfb\x0eNa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"}, {"66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0", "abc", "sm3\x03s\x80\x16oI\x14\xb2\xb9\x17$B\xd7ڊ\x06\x00\xa9o0\xbc\x1618\xaa\xe3\x8d\xeeM\xb0\xfb\x0eNa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"},
{"debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd", "sm3\x03s\x80\x16oI\x14\xb2\xb9\x17$B\xd7ڊ\x06\x00\xa9o0\xbc\x1618\xaa\xe3\x8d\xeeM\xb0\xfb\x0eNabcdabcdabcdabcdabcdabcdabcdabcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 "}, {"debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd", "sm3\x03s\x80\x16oI\x14\xb2\xb9\x17$B\xd7ڊ\x06\x00\xa9o0\xbc\x1618\xaa\xe3\x8d\xeeM\xb0\xfb\x0eNabcdabcdabcdabcdabcdabcdabcdabcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 "},
{"952eb84cacee9c10bde4d6882d29d63140ba72af6fe485085095dccd5b872453", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabc", "sm3\x03s\x80\x16oI\x14\xb2\xb9\x17$B\xd7ڊ\x06\x00\xa9o0\xbc\x1618\xaa\xe3\x8d\xeeM\xb0\xfb\x0eNabcdabcdabcdabcdabcdabcdabcdabcda\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!"}, {"952eb84cacee9c10bde4d6882d29d63140ba72af6fe485085095dccd5b872453", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabc", "sm3\x03s\x80\x16oI\x14\xb2\xb9\x17$B\xd7ڊ\x06\x00\xa9o0\xbc\x1618\xaa\xe3\x8d\xeeM\xb0\xfb\x0eNabcdabcdabcdabcdabcdabcdabcdabcda\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!"},
{"90d52a2e85631a8d6035262626941fa11b85ce570cec1e3e991e2dd7ed258148", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd", "sm3\x03YPށF\x86d\xebB\xfdL\x86\x1e|\xa0\n\xc0\xa5\x91\v\xae\x9aU\xea\x1aۍ\x17v<\xa2\"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@"}, {"90d52a2e85631a8d6035262626941fa11b85ce570cec1e3e991e2dd7ed258148", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd", "sm3\x03YPށF\x86d\xebB\xfdL\x86\x1e|\xa0\n\xc0\xa5\x91\v\xae\x9aU\xea\x1aۍ\x17v<\xa2\"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@"},
{"e1c53f367a9c5d19ab6ddd30248a7dafcc607e74e6bcfa52b00e0ba35e470421", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabc", "sm3\x03YPށF\x86d\xebB\xfdL\x86\x1e|\xa0\n\xc0\xa5\x91\v\xae\x9aU\xea\x1aۍ\x17v<\xa2\"a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A"}, {"e1c53f367a9c5d19ab6ddd30248a7dafcc607e74e6bcfa52b00e0ba35e470421", "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabc", "sm3\x03YPށF\x86d\xebB\xfdL\x86\x1e|\xa0\n\xc0\xa5\x91\v\xae\x9aU\xea\x1aۍ\x17v<\xa2\"a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A"},
} }
func TestGolden(t *testing.T) { func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ { for i := 0; i < len(golden); i++ {
g := golden[i] g := golden[i]
h := Sum([]byte(g.in)) h := Sum([]byte(g.in))
s := fmt.Sprintf("%x", h) s := fmt.Sprintf("%x", h)
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(h[:])) fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(h[:]))
if s != g.out { if s != g.out {
t.Fatalf("SM3 function: sm3(%s) = %s want %s", g.in, s, g.out) t.Fatalf("SM3 function: sm3(%s) = %s want %s", g.in, s, g.out)
} }
c := New() c := New()
for j := 0; j < 3; j++ { for j := 0; j < 3; j++ {
if j < 2 { if j < 2 {
io.WriteString(c, g.in) io.WriteString(c, g.in)
} else { } else {
io.WriteString(c, g.in[0:len(g.in)/2]) io.WriteString(c, g.in[0:len(g.in)/2])
c.Sum(nil) c.Sum(nil)
io.WriteString(c, g.in[len(g.in)/2:]) io.WriteString(c, g.in[len(g.in)/2:])
} }
s := fmt.Sprintf("%x", c.Sum(nil)) s := fmt.Sprintf("%x", c.Sum(nil))
if s != g.out { if s != g.out {
t.Fatalf("sm3[%d](%s) = %s want %s", j, g.in, s, g.out) t.Fatalf("sm3[%d](%s) = %s want %s", j, g.in, s, g.out)
} }
c.Reset() c.Reset()
} }
} }
} }
func TestGoldenMarshal(t *testing.T) { func TestGoldenMarshal(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
newHash func() hash.Hash newHash func() hash.Hash
gold []sm3Test gold []sm3Test
}{ }{
{"", New, golden}, {"", New, golden},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
for _, g := range tt.gold { for _, g := range tt.gold {
h := tt.newHash() h := tt.newHash()
h2 := tt.newHash() h2 := tt.newHash()
io.WriteString(h, g.in[:len(g.in)/2]) io.WriteString(h, g.in[:len(g.in)/2])
state, err := h.(encoding.BinaryMarshaler).MarshalBinary() state, err := h.(encoding.BinaryMarshaler).MarshalBinary()
if err != nil { if err != nil {
t.Errorf("could not marshal: %v", err) t.Errorf("could not marshal: %v", err)
continue continue
} }
if string(state) != g.halfState { if string(state) != g.halfState {
t.Errorf("sm3%s(%q) state = %q, want %q", tt.name, g.in, state, g.halfState) t.Errorf("sm3%s(%q) state = %q, want %q", tt.name, g.in, state, g.halfState)
continue continue
} }
if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err != nil { if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err != nil {
t.Errorf("could not unmarshal: %v", err) t.Errorf("could not unmarshal: %v", err)
continue continue
} }
io.WriteString(h, g.in[len(g.in)/2:]) io.WriteString(h, g.in[len(g.in)/2:])
io.WriteString(h2, g.in[len(g.in)/2:]) io.WriteString(h2, g.in[len(g.in)/2:])
if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) { if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) {
t.Errorf("sm3%s(%q) = 0x%x != marshaled 0x%x", tt.name, g.in, actual, actual2) t.Errorf("sm3%s(%q) = 0x%x != marshaled 0x%x", tt.name, g.in, actual, actual2)
} }
} }
}) })
} }
} }
func TestSize(t *testing.T) { func TestSize(t *testing.T) {
c := New() c := New()
if got := c.Size(); got != Size { if got := c.Size(); got != Size {
t.Errorf("Size = %d; want %d", got, Size) t.Errorf("Size = %d; want %d", got, Size)
} }
} }
func TestBlockSize(t *testing.T) { func TestBlockSize(t *testing.T) {
c := New() c := New()
if got := c.BlockSize(); got != BlockSize { if got := c.BlockSize(); got != BlockSize {
t.Errorf("BlockSize = %d want %d", got, BlockSize) t.Errorf("BlockSize = %d want %d", got, BlockSize)
} }
fmt.Printf("ARM64 has sm3 %v, has sm4 %v, has aes %v\n", cpu.ARM64.HasSM3, cpu.ARM64.HasSM4, cpu.ARM64.HasAES) fmt.Printf("ARM64 has sm3 %v, has sm4 %v, has aes %v\n", cpu.ARM64.HasSM3, cpu.ARM64.HasSM4, cpu.ARM64.HasAES)
} }
var bench = New() var bench = New()
var benchSH256 = sha256.New() var benchSH256 = sha256.New()
var buf = make([]byte, 8192) var buf = make([]byte, 8192)
func benchmarkSize(hash hash.Hash, b *testing.B, size int) { func benchmarkSize(hash hash.Hash, b *testing.B, size int) {
b.SetBytes(int64(size)) b.SetBytes(int64(size))
sum := make([]byte, bench.Size()) sum := make([]byte, bench.Size())
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
hash.Reset() hash.Reset()
hash.Write(buf[:size]) hash.Write(buf[:size])
hash.Sum(sum[:0]) hash.Sum(sum[:0])
} }
} }
func BenchmarkHash8Bytes(b *testing.B) { func BenchmarkHash8Bytes(b *testing.B) {
benchmarkSize(bench, b, 8) benchmarkSize(bench, b, 8)
} }
func BenchmarkHash1K(b *testing.B) { func BenchmarkHash1K(b *testing.B) {
benchmarkSize(bench, b, 1024) benchmarkSize(bench, b, 1024)
} }
func BenchmarkHash8K(b *testing.B) { func BenchmarkHash8K(b *testing.B) {
benchmarkSize(bench, b, 8192) benchmarkSize(bench, b, 8192)
} }
func BenchmarkHash8K_SH256(b *testing.B) { func BenchmarkHash8K_SH256(b *testing.B) {
benchmarkSize(benchSH256, b, 8192) benchmarkSize(benchSH256, b, 8192)
} }

View File

@ -1,94 +1,94 @@
package sm4 package sm4
import ( import (
"reflect" "reflect"
"testing" "testing"
) )
type CryptTest struct { type CryptTest struct {
key []byte key []byte
in []byte in []byte
out []byte out []byte
} }
var encryptTests = []CryptTest{ var encryptTests = []CryptTest{
{ {
// Appendix 1. // Appendix 1.
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
[]byte{0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46}, []byte{0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46},
}, },
} }
func Test_sample1(t *testing.T) { func Test_sample1(t *testing.T) {
src := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10} src := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
expected := []byte{0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46} expected := []byte{0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46}
c, err := NewCipher(src) c, err := NewCipher(src)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
dst := make([]byte, 16) dst := make([]byte, 16)
c.Encrypt(dst, src) c.Encrypt(dst, src)
if !reflect.DeepEqual(dst, expected) { if !reflect.DeepEqual(dst, expected) {
t.Errorf("expected=%v, result=%v\n", expected, dst) t.Errorf("expected=%v, result=%v\n", expected, dst)
} }
c.Decrypt(dst, expected) c.Decrypt(dst, expected)
if !reflect.DeepEqual(dst, src) { if !reflect.DeepEqual(dst, src) {
t.Errorf("expected=%v, result=%v\n", src, dst) t.Errorf("expected=%v, result=%v\n", src, dst)
} }
} }
func Test_sample2(t *testing.T) { func Test_sample2(t *testing.T) {
src := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10} src := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
expected := []byte{0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66} expected := []byte{0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66}
c, err := NewCipher(src) c, err := NewCipher(src)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
dst := make([]byte, 16) dst := make([]byte, 16)
copy(dst, src) copy(dst, src)
for i := 0; i < 1000000; i++ { for i := 0; i < 1000000; i++ {
c.Encrypt(dst, dst) c.Encrypt(dst, dst)
} }
if !reflect.DeepEqual(dst, expected) { if !reflect.DeepEqual(dst, expected) {
t.Errorf("expected=%v, result=%v\n", expected, dst) t.Errorf("expected=%v, result=%v\n", expected, dst)
} }
} }
func BenchmarkEncrypt(b *testing.B) { func BenchmarkEncrypt(b *testing.B) {
tt := encryptTests[0] tt := encryptTests[0]
c, err := NewCipher(tt.key) c, err := NewCipher(tt.key)
if err != nil { if err != nil {
b.Fatal("NewCipher:", err) b.Fatal("NewCipher:", err)
} }
out := make([]byte, len(tt.in)) out := make([]byte, len(tt.in))
b.SetBytes(int64(len(out))) b.SetBytes(int64(len(out)))
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
c.Encrypt(out, tt.in) c.Encrypt(out, tt.in)
} }
} }
func BenchmarkDecrypt(b *testing.B) { func BenchmarkDecrypt(b *testing.B) {
tt := encryptTests[0] tt := encryptTests[0]
c, err := NewCipher(tt.key) c, err := NewCipher(tt.key)
if err != nil { if err != nil {
b.Fatal("NewCipher:", err) b.Fatal("NewCipher:", err)
} }
out := make([]byte, len(tt.out)) out := make([]byte, len(tt.out))
b.SetBytes(int64(len(out))) b.SetBytes(int64(len(out)))
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
c.Decrypt(out, tt.out) c.Decrypt(out, tt.out)
} }
} }
func BenchmarkExpand(b *testing.B) { func BenchmarkExpand(b *testing.B) {
tt := encryptTests[0] tt := encryptTests[0]
c := &sm4Cipher{make([]uint32, rounds), make([]uint32, rounds)} c := &sm4Cipher{make([]uint32, rounds), make([]uint32, rounds)}
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
expandKey(tt.key, c.enc, c.dec) expandKey(tt.key, c.enc, c.dec)
} }
} }

File diff suppressed because it is too large Load Diff