github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/crypto/sm/sm3/sm3.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package sm3 implements china crypto standards.
     6  package sm3
     7  
     8  import (
     9  	"crypto"
    10  	"hash"
    11  )
    12  
    13  func init() {
    14  	crypto.RegisterHash(crypto.SM3, New)
    15  }
    16  
    17  // The size of a SHA256 checksum in bytes.
    18  const Size = 32
    19  
    20  // The blocksize of SHA256 and SHA224 in bytes.
    21  const BlockSize = 64
    22  
    23  const (
    24  	chunk = 64
    25  	init0 = 0x7380166f
    26  	init1 = 0x4914b2b9
    27  	init2 = 0x172442d7
    28  	init3 = 0xda8a0600
    29  	init4 = 0xa96f30bc
    30  	init5 = 0x163138aa
    31  	init6 = 0xe38dee4d
    32  	init7 = 0xb0fb0e4e
    33  )
    34  
    35  // digest represents the partial evaluation of a checksum.
    36  type digest struct {
    37  	h   [8]uint32
    38  	x   [chunk]byte
    39  	nx  int
    40  	len uint64
    41  }
    42  
    43  func (d *digest) Reset() {
    44  	d.h[0] = init0
    45  	d.h[1] = init1
    46  	d.h[2] = init2
    47  	d.h[3] = init3
    48  	d.h[4] = init4
    49  	d.h[5] = init5
    50  	d.h[6] = init6
    51  	d.h[7] = init7
    52  	d.nx = 0
    53  	d.len = 0
    54  }
    55  
    56  func New() hash.Hash {
    57  	d := new(digest)
    58  	d.Reset()
    59  	return d
    60  }
    61  
    62  func (d *digest) Size() int {
    63  	return Size
    64  }
    65  
    66  func (d *digest) BlockSize() int { return BlockSize }
    67  
    68  func (d *digest) Write(p []byte) (nn int, err error) {
    69  	nn = len(p)
    70  	d.len += uint64(nn)
    71  	var n int
    72  	if d.nx > 0 {
    73  		n := copy(d.x[d.nx:], p)
    74  		d.nx += n
    75  		if d.nx == chunk {
    76  			Block(d, d.x[:])
    77  			d.nx = 0
    78  		}
    79  		p = p[n:]
    80  	}
    81  
    82  	if len(p) >= chunk {
    83  		Block(d, p)
    84  		p = p[n:]
    85  	}
    86  	if len(p) > 0 {
    87  		d.nx = copy(d.x[:], p)
    88  	}
    89  	return
    90  }
    91  
    92  func (d0 *digest) Sum(in []byte) []byte {
    93  	// Make a copy of d0 so that caller can keep writing and summing.
    94  	d := *d0
    95  	hash := d.checkSum()
    96  	return append(in, hash[:]...)
    97  }
    98  
    99  func (d *digest) checkSum() [Size]byte {
   100  	len := d.len
   101  	// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
   102  	var tmp [64]byte
   103  	tmp[0] = 0x80
   104  	if len%64 < 56 {
   105  		d.Write(tmp[0 : 56-len%64])
   106  	} else {
   107  		d.Write(tmp[0 : 64+56-len%64])
   108  	}
   109  
   110  	// Length in bits.
   111  	len <<= 3
   112  	for i := uint(0); i < 8; i++ {
   113  		tmp[i] = byte(len >> (56 - 8*i))
   114  	}
   115  	d.Write(tmp[0:8])
   116  
   117  	if d.nx != 0 {
   118  		panic("d.nx != 0")
   119  	}
   120  
   121  	h := d.h[:]
   122  
   123  	var digest [Size]byte
   124  	for i, s := range h {
   125  		digest[i*4] = byte(s >> 24)
   126  		digest[i*4+1] = byte(s >> 16)
   127  		digest[i*4+2] = byte(s >> 8)
   128  		digest[i*4+3] = byte(s)
   129  	}
   130  	return digest
   131  
   132  }
   133  
   134  func SumSM3(data []byte) [Size]byte {
   135  	var d digest
   136  	d.Reset()
   137  	d.Write(data)
   138  	return d.checkSum()
   139  }