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 }