gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/sm3/sm3_test.go (about)

     1  // Copyright (c) 2022 zhaochun
     2  // core-gm is licensed under Mulan PSL v2.
     3  // You can use this software according to the terms and conditions of the Mulan PSL v2.
     4  // You may obtain a copy of Mulan PSL v2 at:
     5  //          http://license.coscl.org.cn/MulanPSL2
     6  // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
     7  // See the Mulan PSL v2 for more details.
     8  
     9  package sm3
    10  
    11  import (
    12  	"bytes"
    13  	"crypto/sha256"
    14  	"encoding"
    15  	"encoding/base64"
    16  	"encoding/hex"
    17  	"fmt"
    18  	"github.com/stretchr/testify/assert"
    19  	"hash"
    20  	"io"
    21  	"io/ioutil"
    22  	"os"
    23  	"testing"
    24  
    25  	"golang.org/x/sys/cpu"
    26  )
    27  
    28  type sm3Test struct {
    29  	out       string
    30  	in        string
    31  	halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal
    32  }
    33  
    34  var golden = []sm3Test{
    35  	{"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"},
    36  	{"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 "},
    37  	{"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!"},
    38  	{"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@"},
    39  	{"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"},
    40  }
    41  
    42  func TestGolden(t *testing.T) {
    43  	for i := 0; i < len(golden); i++ {
    44  		g := golden[i]
    45  		h := Sm3Sum([]byte(g.in))
    46  		s := fmt.Sprintf("%x", h)
    47  		fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(h[:]))
    48  		if s != g.out {
    49  			t.Fatalf("SM3 function: sm3(%s) = %s want %s", g.in, s, g.out)
    50  		}
    51  		c := New()
    52  		for j := 0; j < 3; j++ {
    53  			if j < 2 {
    54  				_, err := io.WriteString(c, g.in)
    55  				if err != nil {
    56  					t.Fatal(err)
    57  				}
    58  			} else {
    59  				_, err := io.WriteString(c, g.in[0:len(g.in)/2])
    60  				if err != nil {
    61  					t.Fatal(err)
    62  				}
    63  				c.Sum(nil)
    64  				_, err = io.WriteString(c, g.in[len(g.in)/2:])
    65  				if err != nil {
    66  					t.Fatal(err)
    67  				}
    68  			}
    69  			s := fmt.Sprintf("%x", c.Sum(nil))
    70  			if s != g.out {
    71  				t.Fatalf("sm3[%d](%s) = %s want %s", j, g.in, s, g.out)
    72  			}
    73  			c.Reset()
    74  		}
    75  	}
    76  }
    77  
    78  func TestGoldenMarshal(t *testing.T) {
    79  	tests := []struct {
    80  		name    string
    81  		newHash func() hash.Hash
    82  		gold    []sm3Test
    83  	}{
    84  		{"", New, golden},
    85  	}
    86  
    87  	for _, tt := range tests {
    88  		t.Run(tt.name, func(t *testing.T) {
    89  			for _, g := range tt.gold {
    90  				h := tt.newHash()
    91  				h2 := tt.newHash()
    92  
    93  				_, err := io.WriteString(h, g.in[:len(g.in)/2])
    94  				if err != nil {
    95  					t.Fatal(err)
    96  				}
    97  
    98  				state, err := h.(encoding.BinaryMarshaler).MarshalBinary()
    99  				if err != nil {
   100  					t.Errorf("could not marshal: %v", err)
   101  					continue
   102  				}
   103  
   104  				if string(state) != g.halfState {
   105  					t.Errorf("sm3%s(%q) state = %q, want %q", tt.name, g.in, state, g.halfState)
   106  					continue
   107  				}
   108  
   109  				if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err != nil {
   110  					t.Errorf("could not unmarshal: %v", err)
   111  					continue
   112  				}
   113  
   114  				_, err = io.WriteString(h, g.in[len(g.in)/2:])
   115  				if err != nil {
   116  					t.Fatal(err)
   117  				}
   118  				_, err = io.WriteString(h2, g.in[len(g.in)/2:])
   119  				if err != nil {
   120  					t.Fatal(err)
   121  				}
   122  
   123  				if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) {
   124  					t.Errorf("sm3%s(%q) = 0x%x != marshaled 0x%x", tt.name, g.in, actual, actual2)
   125  				}
   126  			}
   127  		})
   128  	}
   129  }
   130  
   131  func TestSize(t *testing.T) {
   132  	c := New()
   133  	if got := c.Size(); got != Size {
   134  		t.Errorf("Size = %d; want %d", got, Size)
   135  	}
   136  }
   137  
   138  func TestBlockSize(t *testing.T) {
   139  	c := New()
   140  	if got := c.BlockSize(); got != BlockSize {
   141  		t.Errorf("BlockSize = %d want %d", got, BlockSize)
   142  	}
   143  	switch cpuType {
   144  	case "arm64":
   145  		fmt.Printf("arm64 has sm3 %v, has sm4 %v, has aes %v\n", cpu.ARM64.HasSM3, cpu.ARM64.HasSM4, cpu.ARM64.HasAES)
   146  	case "amd64":
   147  		fmt.Printf("amd64 has AVX2 %v, has BMI2 %v\n", cpu.X86.HasAVX2, cpu.X86.HasBMI2)
   148  	}
   149  }
   150  
   151  var bench = New()
   152  var benchSH256 = sha256.New()
   153  var buf = make([]byte, 8192)
   154  
   155  func benchmarkSize(hash hash.Hash, b *testing.B, size int) {
   156  	b.SetBytes(int64(size))
   157  	sum := make([]byte, bench.Size())
   158  	for i := 0; i < b.N; i++ {
   159  		hash.Reset()
   160  		hash.Write(buf[:size])
   161  		hash.Sum(sum[:0])
   162  	}
   163  }
   164  
   165  func BenchmarkHash8Bytes(b *testing.B) {
   166  	benchmarkSize(bench, b, 8)
   167  }
   168  
   169  func BenchmarkHash1K(b *testing.B) {
   170  	benchmarkSize(bench, b, 1024)
   171  }
   172  
   173  func BenchmarkHash8K(b *testing.B) {
   174  	benchmarkSize(bench, b, 8192)
   175  }
   176  
   177  func BenchmarkHash8K_SH256(b *testing.B) {
   178  	benchmarkSize(benchSH256, b, 8192)
   179  }
   180  
   181  func TestSm3(t *testing.T) {
   182  	msg := []byte("天行健君子以自强不息")
   183  	// 生成msg文件
   184  	err := ioutil.WriteFile("testdata/msg", msg, os.FileMode(0644))
   185  	if err != nil {
   186  		t.Fatal(err)
   187  	}
   188  	// 读取msg文件
   189  	msg, err = ioutil.ReadFile("testdata/msg")
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  	fmt.Printf("读取到的文件内容: %s\n", string(msg))
   194  
   195  	// 散列计算方式1:sm3.New(),Write,Sum
   196  	//
   197  	hw := New()
   198  	// 添加散列内容
   199  	hw.Write(msg)
   200  	// 散列计算
   201  	sum := hw.Sum(nil)
   202  	fmt.Println("sum值: ", sum)
   203  	fmt.Printf("sum长度 : %d\n", len(sum))
   204  	fmt.Printf("sum字符串 : %s\n", hex.EncodeToString(sum))
   205  
   206  	// 散列计算方式2:直接sm3计算
   207  	hash1 := Sm3Sum(msg)
   208  	fmt.Println("hash1值: ", hash1)
   209  	fmt.Printf("hash1长度 : %d\n", len(hash1))
   210  	fmt.Printf("hash1字符串 : %s\n", hex.EncodeToString(hash1))
   211  	assert.Equal(t, sum, hash1)
   212  
   213  	// 散列计算方式3:hw.reset,Write,Sum
   214  	hw.Reset()
   215  	hw.Write(msg)
   216  	sum2 := hw.Sum(nil)
   217  	fmt.Println("sum2值: ", sum2)
   218  	fmt.Printf("sum2长度 : %d\n", len(sum2))
   219  	fmt.Printf("sum2字符串 : %s\n", hex.EncodeToString(sum2))
   220  	assert.Equal(t, sum, sum2)
   221  }
   222  
   223  func BenchmarkSm3(t *testing.B) {
   224  	t.ReportAllocs()
   225  	msg := []byte("天行健君子以自强不息")
   226  	hw := New()
   227  	for i := 0; i < t.N; i++ {
   228  		hw.Reset()
   229  		hw.Write(msg)
   230  		hw.Sum(nil)
   231  	}
   232  }
   233  
   234  func BenchmarkSha256(t *testing.B) {
   235  	t.ReportAllocs()
   236  	msg := []byte("天行健君子以自强不息")
   237  	hw := sha256.New()
   238  	for i := 0; i < t.N; i++ {
   239  		hw.Reset()
   240  		hw.Write(msg)
   241  		hw.Sum(nil)
   242  	}
   243  }