github.com/insolar/x-crypto@v0.0.0-20191031140942-75fab8a325f6/sha256/sha256.go (about) 1 // Copyright 2009 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 sha256 implements the SHA224 and SHA256 hash algorithms as defined 6 // in FIPS 180-4. 7 package sha256 8 9 import ( 10 "errors" 11 "github.com/insolar/x-crypto" 12 "hash" 13 ) 14 15 func init() { 16 crypto.RegisterHash(crypto.SHA224, New224) 17 crypto.RegisterHash(crypto.SHA256, New) 18 } 19 20 // The size of a SHA256 checksum in bytes. 21 const Size = 32 22 23 // The size of a SHA224 checksum in bytes. 24 const Size224 = 28 25 26 // The blocksize of SHA256 and SHA224 in bytes. 27 const BlockSize = 64 28 29 const ( 30 chunk = 64 31 init0 = 0x6A09E667 32 init1 = 0xBB67AE85 33 init2 = 0x3C6EF372 34 init3 = 0xA54FF53A 35 init4 = 0x510E527F 36 init5 = 0x9B05688C 37 init6 = 0x1F83D9AB 38 init7 = 0x5BE0CD19 39 init0_224 = 0xC1059ED8 40 init1_224 = 0x367CD507 41 init2_224 = 0x3070DD17 42 init3_224 = 0xF70E5939 43 init4_224 = 0xFFC00B31 44 init5_224 = 0x68581511 45 init6_224 = 0x64F98FA7 46 init7_224 = 0xBEFA4FA4 47 ) 48 49 // digest represents the partial evaluation of a checksum. 50 type digest struct { 51 h [8]uint32 52 x [chunk]byte 53 nx int 54 len uint64 55 is224 bool // mark if this digest is SHA-224 56 } 57 58 const ( 59 magic224 = "sha\x02" 60 magic256 = "sha\x03" 61 marshaledSize = len(magic256) + 8*4 + chunk + 8 62 ) 63 64 func (d *digest) MarshalBinary() ([]byte, error) { 65 b := make([]byte, 0, marshaledSize) 66 if d.is224 { 67 b = append(b, magic224...) 68 } else { 69 b = append(b, magic256...) 70 } 71 b = appendUint32(b, d.h[0]) 72 b = appendUint32(b, d.h[1]) 73 b = appendUint32(b, d.h[2]) 74 b = appendUint32(b, d.h[3]) 75 b = appendUint32(b, d.h[4]) 76 b = appendUint32(b, d.h[5]) 77 b = appendUint32(b, d.h[6]) 78 b = appendUint32(b, d.h[7]) 79 b = append(b, d.x[:d.nx]...) 80 b = b[:len(b)+len(d.x)-int(d.nx)] // already zero 81 b = appendUint64(b, d.len) 82 return b, nil 83 } 84 85 func (d *digest) UnmarshalBinary(b []byte) error { 86 if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) { 87 return errors.New("crypto/sha256: invalid hash state identifier") 88 } 89 if len(b) != marshaledSize { 90 return errors.New("crypto/sha256: invalid hash state size") 91 } 92 b = b[len(magic224):] 93 b, d.h[0] = consumeUint32(b) 94 b, d.h[1] = consumeUint32(b) 95 b, d.h[2] = consumeUint32(b) 96 b, d.h[3] = consumeUint32(b) 97 b, d.h[4] = consumeUint32(b) 98 b, d.h[5] = consumeUint32(b) 99 b, d.h[6] = consumeUint32(b) 100 b, d.h[7] = consumeUint32(b) 101 b = b[copy(d.x[:], b):] 102 b, d.len = consumeUint64(b) 103 d.nx = int(d.len) % chunk 104 return nil 105 } 106 107 func putUint32(x []byte, s uint32) { 108 _ = x[3] 109 x[0] = byte(s >> 24) 110 x[1] = byte(s >> 16) 111 x[2] = byte(s >> 8) 112 x[3] = byte(s) 113 } 114 115 func putUint64(x []byte, s uint64) { 116 _ = x[7] 117 x[0] = byte(s >> 56) 118 x[1] = byte(s >> 48) 119 x[2] = byte(s >> 40) 120 x[3] = byte(s >> 32) 121 x[4] = byte(s >> 24) 122 x[5] = byte(s >> 16) 123 x[6] = byte(s >> 8) 124 x[7] = byte(s) 125 } 126 127 func appendUint64(b []byte, x uint64) []byte { 128 var a [8]byte 129 putUint64(a[:], x) 130 return append(b, a[:]...) 131 } 132 133 func appendUint32(b []byte, x uint32) []byte { 134 var a [4]byte 135 putUint32(a[:], x) 136 return append(b, a[:]...) 137 } 138 139 func consumeUint64(b []byte) ([]byte, uint64) { 140 _ = b[7] 141 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | 142 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 143 return b[8:], x 144 } 145 146 func consumeUint32(b []byte) ([]byte, uint32) { 147 _ = b[3] 148 x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 149 return b[4:], x 150 } 151 152 func (d *digest) Reset() { 153 if !d.is224 { 154 d.h[0] = init0 155 d.h[1] = init1 156 d.h[2] = init2 157 d.h[3] = init3 158 d.h[4] = init4 159 d.h[5] = init5 160 d.h[6] = init6 161 d.h[7] = init7 162 } else { 163 d.h[0] = init0_224 164 d.h[1] = init1_224 165 d.h[2] = init2_224 166 d.h[3] = init3_224 167 d.h[4] = init4_224 168 d.h[5] = init5_224 169 d.h[6] = init6_224 170 d.h[7] = init7_224 171 } 172 d.nx = 0 173 d.len = 0 174 } 175 176 // New returns a new hash.Hash computing the SHA256 checksum. The Hash 177 // also implements encoding.BinaryMarshaler and 178 // encoding.BinaryUnmarshaler to marshal and unmarshal the internal 179 // state of the hash. 180 func New() hash.Hash { 181 d := new(digest) 182 d.Reset() 183 return d 184 } 185 186 // New224 returns a new hash.Hash computing the SHA224 checksum. 187 func New224() hash.Hash { 188 d := new(digest) 189 d.is224 = true 190 d.Reset() 191 return d 192 } 193 194 func (d *digest) Size() int { 195 if !d.is224 { 196 return Size 197 } 198 return Size224 199 } 200 201 func (d *digest) BlockSize() int { return BlockSize } 202 203 func (d *digest) Write(p []byte) (nn int, err error) { 204 nn = len(p) 205 d.len += uint64(nn) 206 if d.nx > 0 { 207 n := copy(d.x[d.nx:], p) 208 d.nx += n 209 if d.nx == chunk { 210 block(d, d.x[:]) 211 d.nx = 0 212 } 213 p = p[n:] 214 } 215 if len(p) >= chunk { 216 n := len(p) &^ (chunk - 1) 217 block(d, p[:n]) 218 p = p[n:] 219 } 220 if len(p) > 0 { 221 d.nx = copy(d.x[:], p) 222 } 223 return 224 } 225 226 func (d *digest) Sum(in []byte) []byte { 227 // Make a copy of d so that caller can keep writing and summing. 228 d0 := *d 229 hash := d0.checkSum() 230 if d0.is224 { 231 return append(in, hash[:Size224]...) 232 } 233 return append(in, hash[:]...) 234 } 235 236 func (d *digest) checkSum() [Size]byte { 237 len := d.len 238 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. 239 var tmp [64]byte 240 tmp[0] = 0x80 241 if len%64 < 56 { 242 d.Write(tmp[0 : 56-len%64]) 243 } else { 244 d.Write(tmp[0 : 64+56-len%64]) 245 } 246 247 // Length in bits. 248 len <<= 3 249 putUint64(tmp[:], len) 250 d.Write(tmp[0:8]) 251 252 if d.nx != 0 { 253 panic("d.nx != 0") 254 } 255 256 var digest [Size]byte 257 258 putUint32(digest[0:], d.h[0]) 259 putUint32(digest[4:], d.h[1]) 260 putUint32(digest[8:], d.h[2]) 261 putUint32(digest[12:], d.h[3]) 262 putUint32(digest[16:], d.h[4]) 263 putUint32(digest[20:], d.h[5]) 264 putUint32(digest[24:], d.h[6]) 265 if !d.is224 { 266 putUint32(digest[28:], d.h[7]) 267 } 268 269 return digest 270 } 271 272 // Sum256 returns the SHA256 checksum of the data. 273 func Sum256(data []byte) [Size]byte { 274 var d digest 275 d.Reset() 276 d.Write(data) 277 return d.checkSum() 278 } 279 280 // Sum224 returns the SHA224 checksum of the data. 281 func Sum224(data []byte) (sum224 [Size224]byte) { 282 var d digest 283 d.is224 = true 284 d.Reset() 285 d.Write(data) 286 sum := d.checkSum() 287 copy(sum224[:], sum[:Size224]) 288 return 289 }