gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/sm3soft/sm3_soft.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  /*
    10  sm3soft 是sm3的纯软实现,基于tjfoc国密算法库`tjfoc/gmsm`做了少量修改。
    11  对应版权声明: thrid_licenses/github.com/tjfoc/gmsm/版权声明
    12  */
    13  
    14  package sm3soft
    15  
    16  /*
    17  sm3/sm3.go SM3实现
    18  */
    19  
    20  import (
    21  	"encoding/binary"
    22  	"hash"
    23  )
    24  
    25  // Size SM3散列结果的字节长度,对应bit长度为256位
    26  const Size = 32
    27  
    28  // BlockSize SM3散列时一个Block的字节长度,对应bit长度为512位
    29  const BlockSize = 64
    30  
    31  type SM3 struct {
    32  	digest      [8]uint32 // digest represents the partial evaluation of V
    33  	length      uint64    // length of the message
    34  	unhandleMsg []byte    // uint8  //
    35  }
    36  
    37  // 布尔函数FF,SM3压缩函数内部迭代在[0,15]区间时使用
    38  func (sm3 *SM3) ff0(x, y, z uint32) uint32 { return x ^ y ^ z }
    39  
    40  // 布尔函数FF,SM3压缩函数内部迭代在[16,63]区间时使用
    41  func (sm3 *SM3) ff1(x, y, z uint32) uint32 { return (x & y) | (x & z) | (y & z) }
    42  
    43  // 布尔函数GG,SM3压缩函数内部迭代在[0,15]区间时使用
    44  func (sm3 *SM3) gg0(x, y, z uint32) uint32 { return x ^ y ^ z }
    45  
    46  // 布尔函数GG,SM3压缩函数内部迭代在[16,63]区间时使用
    47  func (sm3 *SM3) gg1(x, y, z uint32) uint32 { return (x & y) | (^x & z) }
    48  
    49  // 置换函数P0
    50  func (sm3 *SM3) p0(x uint32) uint32 { return x ^ sm3.leftRotate(x, 9) ^ sm3.leftRotate(x, 17) }
    51  
    52  // 置换函数P1
    53  func (sm3 *SM3) p1(x uint32) uint32 { return x ^ sm3.leftRotate(x, 15) ^ sm3.leftRotate(x, 23) }
    54  
    55  // 循环左移
    56  func (sm3 *SM3) leftRotate(x uint32, i uint32) uint32 { return x<<(i%32) | x>>(32-i%32) }
    57  
    58  func (sm3 *SM3) pad() []byte {
    59  	msg := sm3.unhandleMsg
    60  	msg = append(msg, 0x80) // Append '1'
    61  	blockSize := 64         // Append until the resulting message length (in bits) is congruent to 448 (mod 512)
    62  	for len(msg)%blockSize != 56 {
    63  		msg = append(msg, 0x00)
    64  	}
    65  	// append message length
    66  	msg = append(msg, uint8(sm3.length>>56&0xff))
    67  	msg = append(msg, uint8(sm3.length>>48&0xff))
    68  	msg = append(msg, uint8(sm3.length>>40&0xff))
    69  	msg = append(msg, uint8(sm3.length>>32&0xff))
    70  	msg = append(msg, uint8(sm3.length>>24&0xff))
    71  	msg = append(msg, uint8(sm3.length>>16&0xff))
    72  	msg = append(msg, uint8(sm3.length>>8&0xff))
    73  	msg = append(msg, uint8(sm3.length>>0&0xff))
    74  
    75  	if len(msg)%64 != 0 {
    76  		panic("------SM3 Pad: error msgLen =")
    77  	}
    78  	return msg
    79  }
    80  
    81  func (sm3 *SM3) update(msg []byte) {
    82  	var w [68]uint32
    83  	var w1 [64]uint32
    84  
    85  	a, b, c, d, e, f, g, h := sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7]
    86  	for len(msg) >= 64 {
    87  		for i := 0; i < 16; i++ {
    88  			w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
    89  		}
    90  		for i := 16; i < 68; i++ {
    91  			w[i] = sm3.p1(w[i-16]^w[i-9]^sm3.leftRotate(w[i-3], 15)) ^ sm3.leftRotate(w[i-13], 7) ^ w[i-6]
    92  		}
    93  		for i := 0; i < 64; i++ {
    94  			w1[i] = w[i] ^ w[i+4]
    95  		}
    96  		A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
    97  		for i := 0; i < 16; i++ {
    98  			SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
    99  			SS2 := SS1 ^ sm3.leftRotate(A, 12)
   100  			TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
   101  			TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
   102  			D = C
   103  			C = sm3.leftRotate(B, 9)
   104  			B = A
   105  			A = TT1
   106  			H = G
   107  			G = sm3.leftRotate(F, 19)
   108  			F = E
   109  			E = sm3.p0(TT2)
   110  		}
   111  		for i := 16; i < 64; i++ {
   112  			SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
   113  			SS2 := SS1 ^ sm3.leftRotate(A, 12)
   114  			TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
   115  			TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
   116  			D = C
   117  			C = sm3.leftRotate(B, 9)
   118  			B = A
   119  			A = TT1
   120  			H = G
   121  			G = sm3.leftRotate(F, 19)
   122  			F = E
   123  			E = sm3.p0(TT2)
   124  		}
   125  		a ^= A
   126  		b ^= B
   127  		c ^= C
   128  		d ^= D
   129  		e ^= E
   130  		f ^= F
   131  		g ^= G
   132  		h ^= H
   133  		msg = msg[64:]
   134  	}
   135  	sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7] = a, b, c, d, e, f, g, h
   136  }
   137  func (sm3 *SM3) update2(msg []byte) [8]uint32 {
   138  	var w [68]uint32
   139  	var w1 [64]uint32
   140  
   141  	a, b, c, d, e, f, g, h := sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7]
   142  	for len(msg) >= 64 {
   143  		for i := 0; i < 16; i++ {
   144  			w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
   145  		}
   146  		for i := 16; i < 68; i++ {
   147  			w[i] = sm3.p1(w[i-16]^w[i-9]^sm3.leftRotate(w[i-3], 15)) ^ sm3.leftRotate(w[i-13], 7) ^ w[i-6]
   148  		}
   149  		for i := 0; i < 64; i++ {
   150  			w1[i] = w[i] ^ w[i+4]
   151  		}
   152  		A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
   153  		for i := 0; i < 16; i++ {
   154  			SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
   155  			SS2 := SS1 ^ sm3.leftRotate(A, 12)
   156  			TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
   157  			TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
   158  			D = C
   159  			C = sm3.leftRotate(B, 9)
   160  			B = A
   161  			A = TT1
   162  			H = G
   163  			G = sm3.leftRotate(F, 19)
   164  			F = E
   165  			E = sm3.p0(TT2)
   166  		}
   167  		for i := 16; i < 64; i++ {
   168  			SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
   169  			SS2 := SS1 ^ sm3.leftRotate(A, 12)
   170  			TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
   171  			TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
   172  			D = C
   173  			C = sm3.leftRotate(B, 9)
   174  			B = A
   175  			A = TT1
   176  			H = G
   177  			G = sm3.leftRotate(F, 19)
   178  			F = E
   179  			E = sm3.p0(TT2)
   180  		}
   181  		a ^= A
   182  		b ^= B
   183  		c ^= C
   184  		d ^= D
   185  		e ^= E
   186  		f ^= F
   187  		g ^= G
   188  		h ^= H
   189  		msg = msg[64:]
   190  	}
   191  	var digest [8]uint32
   192  	digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7] = a, b, c, d, e, f, g, h
   193  	return digest
   194  }
   195  
   196  // New 创建哈希计算实例
   197  func New() hash.Hash {
   198  	var sm3 SM3
   199  
   200  	sm3.Reset()
   201  	return &sm3
   202  }
   203  
   204  // BlockSize returns the hash's underlying block size.
   205  // The Write method must be able to accept any amount
   206  // of data, but it may operate more efficiently if all writes
   207  // are a multiple of the block size.
   208  func (sm3 *SM3) BlockSize() int { return BlockSize }
   209  
   210  // Size returns the number of bytes Sum will return.
   211  func (sm3 *SM3) Size() int { return Size }
   212  
   213  // Reset clears the internal state by zeroing bytes in the state buffer.
   214  // This can be skipped for a newly-created hash state; the default zero-allocated state is correct.
   215  func (sm3 *SM3) Reset() {
   216  	// Reset digest
   217  	sm3.digest[0] = 0x7380166f
   218  	sm3.digest[1] = 0x4914b2b9
   219  	sm3.digest[2] = 0x172442d7
   220  	sm3.digest[3] = 0xda8a0600
   221  	sm3.digest[4] = 0xa96f30bc
   222  	sm3.digest[5] = 0x163138aa
   223  	sm3.digest[6] = 0xe38dee4d
   224  	sm3.digest[7] = 0xb0fb0e4e
   225  
   226  	sm3.length = 0 // Reset numberic states
   227  	sm3.unhandleMsg = []byte{}
   228  }
   229  
   230  // Write (via the embedded io.Writer interface) adds more data to the running hash.
   231  // It never returns an error.
   232  func (sm3 *SM3) Write(p []byte) (int, error) {
   233  	toWrite := len(p)
   234  	sm3.length += uint64(len(p) * 8)
   235  	msg := append(sm3.unhandleMsg, p...)
   236  	nblocks := len(msg) / sm3.BlockSize()
   237  	sm3.update(msg)
   238  	// Update unhandleMsg
   239  	sm3.unhandleMsg = msg[nblocks*sm3.BlockSize():]
   240  
   241  	return toWrite, nil
   242  }
   243  
   244  // Sum 返回SM3哈希算法摘要值
   245  // Sum appends the current hash to b and returns the resulting slice.
   246  // It does not change the underlying hash state.
   247  func (sm3 *SM3) Sum(in []byte) []byte {
   248  	_, _ = sm3.Write(in)
   249  	msg := sm3.pad()
   250  	//Finalize
   251  	digest := sm3.update2(msg)
   252  
   253  	// save hash to in
   254  	needed := sm3.Size()
   255  	if cap(in)-len(in) < needed {
   256  		newIn := make([]byte, len(in), len(in)+needed)
   257  		copy(newIn, in)
   258  		in = newIn
   259  	}
   260  	out := in[len(in) : len(in)+needed]
   261  	for i := 0; i < 8; i++ {
   262  		binary.BigEndian.PutUint32(out[i*4:], digest[i])
   263  	}
   264  	return out
   265  
   266  }
   267  
   268  func Sm3Sum(data []byte) []byte {
   269  	var sm3 SM3
   270  
   271  	sm3.Reset()
   272  	_, _ = sm3.Write(data)
   273  	return sm3.Sum(nil)
   274  }