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

42
LICENSE
View File

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

202
README.md
View File

@ -1,101 +1,101 @@
# 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)
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).
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**
CPU: i5-9500
P-256/SM2(No tuning)
goos: windows
goarch: amd64
pkg: gmsm/sm2
BenchmarkLessThan32-6 210 5665861 ns/op 0.01 MB/s 2601864 B/op 27725 allocs/op
PASS
ok gmsm/sm2 5.629s
P-256/SM2(with P256/SM2 curve pure golang implementation)
goos: windows
goarch: amd64
pkg: gmsm/sm2
BenchmarkLessThan32_P256SM2-6 1027 1169516 ns/op 3874 B/op 74 allocs/op
PASS
ok gmsm/sm2 1.564s
P-256/SM2(with P256/SM2 amd64 curve implementation, i think there are still improvement space for p256Sqr function)
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm2
BenchmarkLessThan32_P256SM2-6 10447 115618 ns/op 2357 B/op 46 allocs/op
PASS
ok github.com/emmansun/gmsm/sm2 2.199s
P-256 (SM2 based on NIST P-256 curve)
goos: windows
goarch: amd64
pkg: gmsm/sm2
BenchmarkMoreThan32-6 13656 86252 ns/op 3141 B/op 50 allocs/op
PASS
ok gmsm/sm2 4.139s
**SM3 hash Benchmark**
CPU: i5-9500
Pure golang version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K-6 27097 41112 ns/op 199.26 MB/s 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm3 3.463s
ASM (non-AVX2) version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K-6 35080 33235 ns/op 246.49 MB/s 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm3 3.102s
ASM AVX2 version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K-6 53208 22223 ns/op 368.63 MB/s 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm3 1.720s
SHA256 ASM AVX2 version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K_SH256-6 68352 17116 ns/op 478.63 MB/s 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm3 3.043s
**SM4 Benchmark**
CPU: i5-9500
Pure golang version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm4
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
BenchmarkExpand-6 2543746 471 ns/op 16 B/op 1 allocs/op
ASM AES-NI version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm4
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
BenchmarkExpand-6 5985129 200 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm4 6.193s
# 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)
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).
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**
CPU: i5-9500
P-256/SM2(No tuning)
goos: windows
goarch: amd64
pkg: gmsm/sm2
BenchmarkLessThan32-6 210 5665861 ns/op 0.01 MB/s 2601864 B/op 27725 allocs/op
PASS
ok gmsm/sm2 5.629s
P-256/SM2(with P256/SM2 curve pure golang implementation)
goos: windows
goarch: amd64
pkg: gmsm/sm2
BenchmarkLessThan32_P256SM2-6 1027 1169516 ns/op 3874 B/op 74 allocs/op
PASS
ok gmsm/sm2 1.564s
P-256/SM2(with P256/SM2 amd64 curve implementation, i think there are still improvement space for p256Sqr function)
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm2
BenchmarkLessThan32_P256SM2-6 10447 115618 ns/op 2357 B/op 46 allocs/op
PASS
ok github.com/emmansun/gmsm/sm2 2.199s
P-256 (SM2 based on NIST P-256 curve)
goos: windows
goarch: amd64
pkg: gmsm/sm2
BenchmarkMoreThan32-6 13656 86252 ns/op 3141 B/op 50 allocs/op
PASS
ok gmsm/sm2 4.139s
**SM3 hash Benchmark**
CPU: i5-9500
Pure golang version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K-6 27097 41112 ns/op 199.26 MB/s 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm3 3.463s
ASM (non-AVX2) version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K-6 35080 33235 ns/op 246.49 MB/s 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm3 3.102s
ASM AVX2 version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K-6 53208 22223 ns/op 368.63 MB/s 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm3 1.720s
SHA256 ASM AVX2 version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm3
BenchmarkHash8K_SH256-6 68352 17116 ns/op 478.63 MB/s 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm3 3.043s
**SM4 Benchmark**
CPU: i5-9500
Pure golang version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm4
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
BenchmarkExpand-6 2543746 471 ns/op 16 B/op 1 allocs/op
ASM AES-NI version
goos: windows
goarch: amd64
pkg: github.com/emmansun/gmsm/sm4
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
BenchmarkExpand-6 5985129 200 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/emmansun/gmsm/sm4 6.193s

16
go.mod
View File

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

View File

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

View File

@ -1,144 +1,144 @@
package sm3
import (
"bytes"
"crypto/sha256"
"encoding"
"encoding/base64"
"fmt"
"hash"
"io"
"testing"
"golang.org/x/sys/cpu"
)
type sm3Test struct {
out string
in string
halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal
}
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"},
{"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!"},
{"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"},
}
func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ {
g := golden[i]
h := Sum([]byte(g.in))
s := fmt.Sprintf("%x", h)
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(h[:]))
if s != g.out {
t.Fatalf("SM3 function: sm3(%s) = %s want %s", g.in, s, g.out)
}
c := New()
for j := 0; j < 3; j++ {
if j < 2 {
io.WriteString(c, g.in)
} else {
io.WriteString(c, g.in[0:len(g.in)/2])
c.Sum(nil)
io.WriteString(c, g.in[len(g.in)/2:])
}
s := fmt.Sprintf("%x", c.Sum(nil))
if s != g.out {
t.Fatalf("sm3[%d](%s) = %s want %s", j, g.in, s, g.out)
}
c.Reset()
}
}
}
func TestGoldenMarshal(t *testing.T) {
tests := []struct {
name string
newHash func() hash.Hash
gold []sm3Test
}{
{"", New, golden},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for _, g := range tt.gold {
h := tt.newHash()
h2 := tt.newHash()
io.WriteString(h, g.in[:len(g.in)/2])
state, err := h.(encoding.BinaryMarshaler).MarshalBinary()
if err != nil {
t.Errorf("could not marshal: %v", err)
continue
}
if string(state) != g.halfState {
t.Errorf("sm3%s(%q) state = %q, want %q", tt.name, g.in, state, g.halfState)
continue
}
if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err != nil {
t.Errorf("could not unmarshal: %v", err)
continue
}
io.WriteString(h, 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) {
t.Errorf("sm3%s(%q) = 0x%x != marshaled 0x%x", tt.name, g.in, actual, actual2)
}
}
})
}
}
func TestSize(t *testing.T) {
c := New()
if got := c.Size(); got != Size {
t.Errorf("Size = %d; want %d", got, Size)
}
}
func TestBlockSize(t *testing.T) {
c := New()
if got := c.BlockSize(); 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)
}
var bench = New()
var benchSH256 = sha256.New()
var buf = make([]byte, 8192)
func benchmarkSize(hash hash.Hash, b *testing.B, size int) {
b.SetBytes(int64(size))
sum := make([]byte, bench.Size())
for i := 0; i < b.N; i++ {
hash.Reset()
hash.Write(buf[:size])
hash.Sum(sum[:0])
}
}
func BenchmarkHash8Bytes(b *testing.B) {
benchmarkSize(bench, b, 8)
}
func BenchmarkHash1K(b *testing.B) {
benchmarkSize(bench, b, 1024)
}
func BenchmarkHash8K(b *testing.B) {
benchmarkSize(bench, b, 8192)
}
func BenchmarkHash8K_SH256(b *testing.B) {
benchmarkSize(benchSH256, b, 8192)
}
package sm3
import (
"bytes"
"crypto/sha256"
"encoding"
"encoding/base64"
"fmt"
"hash"
"io"
"testing"
"golang.org/x/sys/cpu"
)
type sm3Test struct {
out string
in string
halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal
}
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"},
{"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!"},
{"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"},
}
func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ {
g := golden[i]
h := Sum([]byte(g.in))
s := fmt.Sprintf("%x", h)
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(h[:]))
if s != g.out {
t.Fatalf("SM3 function: sm3(%s) = %s want %s", g.in, s, g.out)
}
c := New()
for j := 0; j < 3; j++ {
if j < 2 {
io.WriteString(c, g.in)
} else {
io.WriteString(c, g.in[0:len(g.in)/2])
c.Sum(nil)
io.WriteString(c, g.in[len(g.in)/2:])
}
s := fmt.Sprintf("%x", c.Sum(nil))
if s != g.out {
t.Fatalf("sm3[%d](%s) = %s want %s", j, g.in, s, g.out)
}
c.Reset()
}
}
}
func TestGoldenMarshal(t *testing.T) {
tests := []struct {
name string
newHash func() hash.Hash
gold []sm3Test
}{
{"", New, golden},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for _, g := range tt.gold {
h := tt.newHash()
h2 := tt.newHash()
io.WriteString(h, g.in[:len(g.in)/2])
state, err := h.(encoding.BinaryMarshaler).MarshalBinary()
if err != nil {
t.Errorf("could not marshal: %v", err)
continue
}
if string(state) != g.halfState {
t.Errorf("sm3%s(%q) state = %q, want %q", tt.name, g.in, state, g.halfState)
continue
}
if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err != nil {
t.Errorf("could not unmarshal: %v", err)
continue
}
io.WriteString(h, 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) {
t.Errorf("sm3%s(%q) = 0x%x != marshaled 0x%x", tt.name, g.in, actual, actual2)
}
}
})
}
}
func TestSize(t *testing.T) {
c := New()
if got := c.Size(); got != Size {
t.Errorf("Size = %d; want %d", got, Size)
}
}
func TestBlockSize(t *testing.T) {
c := New()
if got := c.BlockSize(); 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)
}
var bench = New()
var benchSH256 = sha256.New()
var buf = make([]byte, 8192)
func benchmarkSize(hash hash.Hash, b *testing.B, size int) {
b.SetBytes(int64(size))
sum := make([]byte, bench.Size())
for i := 0; i < b.N; i++ {
hash.Reset()
hash.Write(buf[:size])
hash.Sum(sum[:0])
}
}
func BenchmarkHash8Bytes(b *testing.B) {
benchmarkSize(bench, b, 8)
}
func BenchmarkHash1K(b *testing.B) {
benchmarkSize(bench, b, 1024)
}
func BenchmarkHash8K(b *testing.B) {
benchmarkSize(bench, b, 8192)
}
func BenchmarkHash8K_SH256(b *testing.B) {
benchmarkSize(benchSH256, b, 8192)
}

View File

@ -1,94 +1,94 @@
package sm4
import (
"reflect"
"testing"
)
type CryptTest struct {
key []byte
in []byte
out []byte
}
var encryptTests = []CryptTest{
{
// 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{0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46},
},
}
func Test_sample1(t *testing.T) {
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}
c, err := NewCipher(src)
if err != nil {
t.Fatal(err)
}
dst := make([]byte, 16)
c.Encrypt(dst, src)
if !reflect.DeepEqual(dst, expected) {
t.Errorf("expected=%v, result=%v\n", expected, dst)
}
c.Decrypt(dst, expected)
if !reflect.DeepEqual(dst, src) {
t.Errorf("expected=%v, result=%v\n", src, dst)
}
}
func Test_sample2(t *testing.T) {
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}
c, err := NewCipher(src)
if err != nil {
t.Fatal(err)
}
dst := make([]byte, 16)
copy(dst, src)
for i := 0; i < 1000000; i++ {
c.Encrypt(dst, dst)
}
if !reflect.DeepEqual(dst, expected) {
t.Errorf("expected=%v, result=%v\n", expected, dst)
}
}
func BenchmarkEncrypt(b *testing.B) {
tt := encryptTests[0]
c, err := NewCipher(tt.key)
if err != nil {
b.Fatal("NewCipher:", err)
}
out := make([]byte, len(tt.in))
b.SetBytes(int64(len(out)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
c.Encrypt(out, tt.in)
}
}
func BenchmarkDecrypt(b *testing.B) {
tt := encryptTests[0]
c, err := NewCipher(tt.key)
if err != nil {
b.Fatal("NewCipher:", err)
}
out := make([]byte, len(tt.out))
b.SetBytes(int64(len(out)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
c.Decrypt(out, tt.out)
}
}
func BenchmarkExpand(b *testing.B) {
tt := encryptTests[0]
c := &sm4Cipher{make([]uint32, rounds), make([]uint32, rounds)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
expandKey(tt.key, c.enc, c.dec)
}
}
package sm4
import (
"reflect"
"testing"
)
type CryptTest struct {
key []byte
in []byte
out []byte
}
var encryptTests = []CryptTest{
{
// 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{0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46},
},
}
func Test_sample1(t *testing.T) {
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}
c, err := NewCipher(src)
if err != nil {
t.Fatal(err)
}
dst := make([]byte, 16)
c.Encrypt(dst, src)
if !reflect.DeepEqual(dst, expected) {
t.Errorf("expected=%v, result=%v\n", expected, dst)
}
c.Decrypt(dst, expected)
if !reflect.DeepEqual(dst, src) {
t.Errorf("expected=%v, result=%v\n", src, dst)
}
}
func Test_sample2(t *testing.T) {
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}
c, err := NewCipher(src)
if err != nil {
t.Fatal(err)
}
dst := make([]byte, 16)
copy(dst, src)
for i := 0; i < 1000000; i++ {
c.Encrypt(dst, dst)
}
if !reflect.DeepEqual(dst, expected) {
t.Errorf("expected=%v, result=%v\n", expected, dst)
}
}
func BenchmarkEncrypt(b *testing.B) {
tt := encryptTests[0]
c, err := NewCipher(tt.key)
if err != nil {
b.Fatal("NewCipher:", err)
}
out := make([]byte, len(tt.in))
b.SetBytes(int64(len(out)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
c.Encrypt(out, tt.in)
}
}
func BenchmarkDecrypt(b *testing.B) {
tt := encryptTests[0]
c, err := NewCipher(tt.key)
if err != nil {
b.Fatal("NewCipher:", err)
}
out := make([]byte, len(tt.out))
b.SetBytes(int64(len(out)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
c.Decrypt(out, tt.out)
}
}
func BenchmarkExpand(b *testing.B) {
tt := encryptTests[0]
c := &sm4Cipher{make([]uint32, rounds), make([]uint32, rounds)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
expandKey(tt.key, c.enc, c.dec)
}
}

File diff suppressed because it is too large Load Diff