github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/sm3soft/sm3_soft.go (about)

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