github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/crypto/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-2. 7 package sha256 8 9 import ( 10 "crypto" 11 "hash" 12 ) 13 14 func init() { 15 crypto.RegisterHash(crypto.SHA224, New224) 16 crypto.RegisterHash(crypto.SHA256, New) 17 } 18 19 // The size of a SHA256 checksum in bytes. 20 const Size = 32 21 22 // The size of a SHA224 checksum in bytes. 23 const Size224 = 28 24 25 // The blocksize of SHA256 and SHA224 in bytes. 26 const BlockSize = 64 27 28 const ( 29 chunk = 64 30 init0 = 0x6A09E667 31 init1 = 0xBB67AE85 32 init2 = 0x3C6EF372 33 init3 = 0xA54FF53A 34 init4 = 0x510E527F 35 init5 = 0x9B05688C 36 init6 = 0x1F83D9AB 37 init7 = 0x5BE0CD19 38 init0_224 = 0xC1059ED8 39 init1_224 = 0x367CD507 40 init2_224 = 0x3070DD17 41 init3_224 = 0xF70E5939 42 init4_224 = 0xFFC00B31 43 init5_224 = 0x68581511 44 init6_224 = 0x64F98FA7 45 init7_224 = 0xBEFA4FA4 46 ) 47 48 // digest represents the partial evaluation of a checksum. 49 type digest struct { 50 h [8]uint32 51 x [chunk]byte 52 nx int 53 len uint64 54 is224 bool // mark if this digest is SHA-224 55 } 56 57 func (d *digest) Reset() { 58 if !d.is224 { 59 d.h[0] = init0 60 d.h[1] = init1 61 d.h[2] = init2 62 d.h[3] = init3 63 d.h[4] = init4 64 d.h[5] = init5 65 d.h[6] = init6 66 d.h[7] = init7 67 } else { 68 d.h[0] = init0_224 69 d.h[1] = init1_224 70 d.h[2] = init2_224 71 d.h[3] = init3_224 72 d.h[4] = init4_224 73 d.h[5] = init5_224 74 d.h[6] = init6_224 75 d.h[7] = init7_224 76 } 77 d.nx = 0 78 d.len = 0 79 } 80 81 // New returns a new hash.Hash computing the SHA256 checksum. 82 func New() hash.Hash { 83 d := new(digest) 84 d.Reset() 85 return d 86 } 87 88 // New224 returns a new hash.Hash computing the SHA224 checksum. 89 func New224() hash.Hash { 90 d := new(digest) 91 d.is224 = true 92 d.Reset() 93 return d 94 } 95 96 func (d *digest) Size() int { 97 if !d.is224 { 98 return Size 99 } 100 return Size224 101 } 102 103 func (d *digest) BlockSize() int { return BlockSize } 104 105 func (d *digest) Write(p []byte) (nn int, err error) { 106 nn = len(p) 107 d.len += uint64(nn) 108 if d.nx > 0 { 109 n := len(p) 110 if n > chunk-d.nx { 111 n = chunk - d.nx 112 } 113 for i := 0; i < n; i++ { 114 d.x[d.nx+i] = p[i] 115 } 116 d.nx += n 117 if d.nx == chunk { 118 block(d, d.x[0:]) 119 d.nx = 0 120 } 121 p = p[n:] 122 } 123 if len(p) >= chunk { 124 n := len(p) &^ (chunk - 1) 125 block(d, p[:n]) 126 p = p[n:] 127 } 128 if len(p) > 0 { 129 d.nx = copy(d.x[:], p) 130 } 131 return 132 } 133 134 func (d0 *digest) Sum(in []byte) []byte { 135 // Make a copy of d0 so that caller can keep writing and summing. 136 d := *d0 137 hash := d.checkSum() 138 if d.is224 { 139 return append(in, hash[:Size224]...) 140 } 141 return append(in, hash[:]...) 142 } 143 144 func (d *digest) checkSum() [Size]byte { 145 len := d.len 146 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. 147 var tmp [64]byte 148 tmp[0] = 0x80 149 if len%64 < 56 { 150 d.Write(tmp[0 : 56-len%64]) 151 } else { 152 d.Write(tmp[0 : 64+56-len%64]) 153 } 154 155 // Length in bits. 156 len <<= 3 157 for i := uint(0); i < 8; i++ { 158 tmp[i] = byte(len >> (56 - 8*i)) 159 } 160 d.Write(tmp[0:8]) 161 162 if d.nx != 0 { 163 panic("d.nx != 0") 164 } 165 166 h := d.h[:] 167 if d.is224 { 168 h = d.h[:7] 169 } 170 171 var digest [Size]byte 172 for i, s := range h { 173 digest[i*4] = byte(s >> 24) 174 digest[i*4+1] = byte(s >> 16) 175 digest[i*4+2] = byte(s >> 8) 176 digest[i*4+3] = byte(s) 177 } 178 179 return digest 180 } 181 182 // Sum256 returns the SHA256 checksum of the data. 183 func Sum256(data []byte) [Size]byte { 184 var d digest 185 d.Reset() 186 d.Write(data) 187 return d.checkSum() 188 } 189 190 // Sum224 returns the SHA224 checksum of the data. 191 func Sum224(data []byte) (sum224 [Size224]byte) { 192 var d digest 193 d.is224 = true 194 d.Reset() 195 d.Write(data) 196 sum := d.checkSum() 197 copy(sum224[:], sum[:Size224]) 198 return 199 }