github.com/Hyperledger-TWGC/tjfoc-gm@v1.4.0/sm3/sm3.go (about)

     1  /*
     2  Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7                   http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  package sm3
    17  
    18  import (
    19  	"encoding/binary"
    20  	"hash"
    21  )
    22  
    23  type SM3 struct {
    24  	digest      [8]uint32 // digest represents the partial evaluation of V
    25  	length      uint64    // length of the message
    26  	unhandleMsg []byte    // uint8  //
    27  }
    28  
    29  func (sm3 *SM3) ff0(x, y, z uint32) uint32 { return x ^ y ^ z }
    30  
    31  func (sm3 *SM3) ff1(x, y, z uint32) uint32 { return (x & y) | (x & z) | (y & z) }
    32  
    33  func (sm3 *SM3) gg0(x, y, z uint32) uint32 { return x ^ y ^ z }
    34  
    35  func (sm3 *SM3) gg1(x, y, z uint32) uint32 { return (x & y) | (^x & z) }
    36  
    37  func (sm3 *SM3) p0(x uint32) uint32 { return x ^ sm3.leftRotate(x, 9) ^ sm3.leftRotate(x, 17) }
    38  
    39  func (sm3 *SM3) p1(x uint32) uint32 { return x ^ sm3.leftRotate(x, 15) ^ sm3.leftRotate(x, 23) }
    40  
    41  func (sm3 *SM3) leftRotate(x uint32, i uint32) uint32 { return x<<(i%32) | x>>(32-i%32) }
    42  
    43  func (sm3 *SM3) pad() []byte {
    44  	msg := sm3.unhandleMsg
    45  	msg = append(msg, 0x80) // Append '1'
    46  	blockSize := 64         // Append until the resulting message length (in bits) is congruent to 448 (mod 512)
    47  	for len(msg)%blockSize != 56 {
    48  		msg = append(msg, 0x00)
    49  	}
    50  	// append message length
    51  	msg = append(msg, uint8(sm3.length>>56&0xff))
    52  	msg = append(msg, uint8(sm3.length>>48&0xff))
    53  	msg = append(msg, uint8(sm3.length>>40&0xff))
    54  	msg = append(msg, uint8(sm3.length>>32&0xff))
    55  	msg = append(msg, uint8(sm3.length>>24&0xff))
    56  	msg = append(msg, uint8(sm3.length>>16&0xff))
    57  	msg = append(msg, uint8(sm3.length>>8&0xff))
    58  	msg = append(msg, uint8(sm3.length>>0&0xff))
    59  
    60  	if len(msg)%64 != 0 {
    61  		panic("------SM3 Pad: error msgLen =")
    62  	}
    63  	return msg
    64  }
    65  
    66  func (sm3 *SM3) update(msg []byte) {
    67  	var w [68]uint32
    68  	var w1 [64]uint32
    69  
    70  	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]
    71  	for len(msg) >= 64 {
    72  		for i := 0; i < 16; i++ {
    73  			w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
    74  		}
    75  		for i := 16; i < 68; i++ {
    76  			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]
    77  		}
    78  		for i := 0; i < 64; i++ {
    79  			w1[i] = w[i] ^ w[i+4]
    80  		}
    81  		A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
    82  		for i := 0; i < 16; i++ {
    83  			SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
    84  			SS2 := SS1 ^ sm3.leftRotate(A, 12)
    85  			TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
    86  			TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
    87  			D = C
    88  			C = sm3.leftRotate(B, 9)
    89  			B = A
    90  			A = TT1
    91  			H = G
    92  			G = sm3.leftRotate(F, 19)
    93  			F = E
    94  			E = sm3.p0(TT2)
    95  		}
    96  		for i := 16; i < 64; i++ {
    97  			SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
    98  			SS2 := SS1 ^ sm3.leftRotate(A, 12)
    99  			TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
   100  			TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
   101  			D = C
   102  			C = sm3.leftRotate(B, 9)
   103  			B = A
   104  			A = TT1
   105  			H = G
   106  			G = sm3.leftRotate(F, 19)
   107  			F = E
   108  			E = sm3.p0(TT2)
   109  		}
   110  		a ^= A
   111  		b ^= B
   112  		c ^= C
   113  		d ^= D
   114  		e ^= E
   115  		f ^= F
   116  		g ^= G
   117  		h ^= H
   118  		msg = msg[64:]
   119  	}
   120  	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
   121  }
   122  func (sm3 *SM3) update2(msg []byte,) [8]uint32 {
   123  	var w [68]uint32
   124  	var w1 [64]uint32
   125  
   126  	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]
   127  	for len(msg) >= 64 {
   128  		for i := 0; i < 16; i++ {
   129  			w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
   130  		}
   131  		for i := 16; i < 68; i++ {
   132  			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]
   133  		}
   134  		for i := 0; i < 64; i++ {
   135  			w1[i] = w[i] ^ w[i+4]
   136  		}
   137  		A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
   138  		for i := 0; i < 16; i++ {
   139  			SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
   140  			SS2 := SS1 ^ sm3.leftRotate(A, 12)
   141  			TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
   142  			TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
   143  			D = C
   144  			C = sm3.leftRotate(B, 9)
   145  			B = A
   146  			A = TT1
   147  			H = G
   148  			G = sm3.leftRotate(F, 19)
   149  			F = E
   150  			E = sm3.p0(TT2)
   151  		}
   152  		for i := 16; i < 64; i++ {
   153  			SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
   154  			SS2 := SS1 ^ sm3.leftRotate(A, 12)
   155  			TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
   156  			TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
   157  			D = C
   158  			C = sm3.leftRotate(B, 9)
   159  			B = A
   160  			A = TT1
   161  			H = G
   162  			G = sm3.leftRotate(F, 19)
   163  			F = E
   164  			E = sm3.p0(TT2)
   165  		}
   166  		a ^= A
   167  		b ^= B
   168  		c ^= C
   169  		d ^= D
   170  		e ^= E
   171  		f ^= F
   172  		g ^= G
   173  		h ^= H
   174  		msg = msg[64:]
   175  	}
   176  	var digest [8]uint32
   177  	digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7] = a, b, c, d, e, f, g, h
   178  	return digest
   179  }
   180  
   181  // 创建哈希计算实例
   182  func New() hash.Hash {
   183  	var sm3 SM3
   184  
   185  	sm3.Reset()
   186  	return &sm3
   187  }
   188  
   189  // BlockSize returns the hash's underlying block size.
   190  // The Write method must be able to accept any amount
   191  // of data, but it may operate more efficiently if all writes
   192  // are a multiple of the block size.
   193  func (sm3 *SM3) BlockSize() int { return 64 }
   194  
   195  // Size returns the number of bytes Sum will return.
   196  func (sm3 *SM3) Size() int { return 32 }
   197  
   198  // Reset clears the internal state by zeroing bytes in the state buffer.
   199  // This can be skipped for a newly-created hash state; the default zero-allocated state is correct.
   200  func (sm3 *SM3) Reset() {
   201  	// Reset digest
   202  	sm3.digest[0] = 0x7380166f
   203  	sm3.digest[1] = 0x4914b2b9
   204  	sm3.digest[2] = 0x172442d7
   205  	sm3.digest[3] = 0xda8a0600
   206  	sm3.digest[4] = 0xa96f30bc
   207  	sm3.digest[5] = 0x163138aa
   208  	sm3.digest[6] = 0xe38dee4d
   209  	sm3.digest[7] = 0xb0fb0e4e
   210  
   211  	sm3.length = 0 // Reset numberic states
   212  	sm3.unhandleMsg = []byte{}
   213  }
   214  
   215  // Write (via the embedded io.Writer interface) adds more data to the running hash.
   216  // It never returns an error.
   217  func (sm3 *SM3) Write(p []byte) (int, error) {
   218  	toWrite := len(p)
   219  	sm3.length += uint64(len(p) * 8)
   220  	msg := append(sm3.unhandleMsg, p...)
   221  	nblocks := len(msg) / sm3.BlockSize()
   222  	sm3.update(msg)
   223  	// Update unhandleMsg
   224  	sm3.unhandleMsg = msg[nblocks*sm3.BlockSize():]
   225  
   226  	return toWrite, nil
   227  }
   228  
   229  // 返回SM3哈希算法摘要值
   230  // Sum appends the current hash to b and returns the resulting slice.
   231  // It does not change the underlying hash state.
   232  func (sm3 *SM3) Sum(in []byte) []byte {
   233  	_, _ = sm3.Write(in)
   234  	msg := sm3.pad()
   235  	//Finalize
   236  	digest := sm3.update2(msg)
   237  
   238  	// save hash to in
   239  	needed := sm3.Size()
   240  	if cap(in)-len(in) < needed {
   241  		newIn := make([]byte, len(in), len(in)+needed)
   242  		copy(newIn, in)
   243  		in = newIn
   244  	}
   245  	out := in[len(in) : len(in)+needed]
   246  	for i := 0; i < 8; i++ {
   247  		binary.BigEndian.PutUint32(out[i*4:], digest[i])
   248  	}
   249  	return out
   250  
   251  }
   252  
   253  func Sm3Sum(data []byte) []byte {
   254  	var sm3 SM3
   255  
   256  	sm3.Reset()
   257  	_, _ = sm3.Write(data)
   258  	return sm3.Sum(nil)
   259  }