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 }