github.com/hellobchain/newcryptosm@v0.0.0-20221019060107-edb949a317e9/sm3/sm3.go (about)

     1  package sm3
     2  
     3  import (
     4  	"hash"
     5  )
     6  
     7  // The size of a SM3 checksum in bytes.
     8  const Size = 32
     9  
    10  // The blocksize of SM3 in bytes.
    11  const BlockSize = 64
    12  
    13  const (
    14  	chunk = 64
    15  	init0 = 0x7380166F
    16  	init1 = 0x4914B2B9
    17  	init2 = 0x172442D7
    18  	init3 = 0xDA8A0600
    19  	init4 = 0xA96F30BC
    20  	init5 = 0x163138AA
    21  	init6 = 0xE38DEE4D
    22  	init7 = 0xB0FB0E4E
    23  )
    24  
    25  type digest struct {
    26  	h   [8]uint32
    27  	x   [chunk]byte
    28  	nx  int
    29  	len uint64
    30  }
    31  
    32  func (d *digest) Reset() {
    33  	d.h[0] = init0
    34  	d.h[1] = init1
    35  	d.h[2] = init2
    36  	d.h[3] = init3
    37  	d.h[4] = init4
    38  	d.h[5] = init5
    39  	d.h[6] = init6
    40  	d.h[7] = init7
    41  	d.nx = 0
    42  	d.len = 0
    43  }
    44  
    45  // New returns a new hash.Hash computing the SM3 checksum.
    46  func New() hash.Hash {
    47  	d := new(digest)
    48  	d.Reset()
    49  	return d
    50  }
    51  
    52  func (d *digest) Size() int { return Size }
    53  
    54  func (d *digest) BlockSize() int { return BlockSize }
    55  
    56  func (d *digest) Write(p []byte) (nn int, err error) {
    57  	nn = len(p)
    58  	d.len += uint64(nn)
    59  	if d.nx > 0 {
    60  		n := copy(d.x[d.nx:], p)
    61  		d.nx += n
    62  		if d.nx == chunk {
    63  			block(d, d.x[:])
    64  			d.nx = 0
    65  		}
    66  		p = p[n:]
    67  	}
    68  	if len(p) >= chunk {
    69  		n := len(p) &^ (chunk - 1)
    70  		block(d, p[:n])
    71  		p = p[n:]
    72  	}
    73  	if len(p) > 0 {
    74  		d.nx = copy(d.x[:], p)
    75  	}
    76  	return
    77  }
    78  
    79  func (d *digest) Sum(in []byte) []byte {
    80  	// Make a copy of d0 so that caller can keep writing and summing.
    81  	dLocal := *d
    82  	hash := dLocal.checkSum()
    83  	return append(in, hash[:]...)
    84  }
    85  
    86  func (d *digest) checkSum() [Size]byte {
    87  	len := d.len
    88  	// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
    89  	var tmp [64]byte
    90  	tmp[0] = 0x80
    91  	if len%64 < 56 {
    92  		d.Write(tmp[0 : 56-len%64])
    93  	} else {
    94  		d.Write(tmp[0 : 64+56-len%64])
    95  	}
    96  
    97  	// Length in bits.
    98  	len <<= 3
    99  	for i := uint(0); i < 8; i++ {
   100  		tmp[i] = byte(len >> (56 - 8*i))
   101  	}
   102  	d.Write(tmp[0:8])
   103  
   104  	if d.nx != 0 {
   105  		panic("d.nx != 0")
   106  	}
   107  
   108  	h := d.h[:]
   109  
   110  	var digest [Size]byte
   111  	for i, s := range h {
   112  		digest[i*4] = byte(s >> 24)
   113  		digest[i*4+1] = byte(s >> 16)
   114  		digest[i*4+2] = byte(s >> 8)
   115  		digest[i*4+3] = byte(s)
   116  	}
   117  	return digest
   118  }
   119  
   120  // Sum returns the SM3 checksum of the data.
   121  func Sum(data []byte) [Size]byte {
   122  	var d digest
   123  	d.Reset()
   124  	d.Write(data)
   125  	return d.checkSum()
   126  }