github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/crypto/sha512/sha512.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 sha512 implements the SHA384 and SHA512 hash algorithms as defined 6 // in FIPS 180-2. 7 package sha512 8 9 import ( 10 "crypto" 11 "hash" 12 ) 13 14 func init() { 15 crypto.RegisterHash(crypto.SHA384, New384) 16 crypto.RegisterHash(crypto.SHA512, New) 17 } 18 19 // The size of a SHA512 checksum in bytes. 20 const Size = 64 21 22 // The size of a SHA384 checksum in bytes. 23 const Size384 = 48 24 25 // The blocksize of SHA512 and SHA384 in bytes. 26 const BlockSize = 128 27 28 const ( 29 chunk = 128 30 init0 = 0x6a09e667f3bcc908 31 init1 = 0xbb67ae8584caa73b 32 init2 = 0x3c6ef372fe94f82b 33 init3 = 0xa54ff53a5f1d36f1 34 init4 = 0x510e527fade682d1 35 init5 = 0x9b05688c2b3e6c1f 36 init6 = 0x1f83d9abfb41bd6b 37 init7 = 0x5be0cd19137e2179 38 init0_384 = 0xcbbb9d5dc1059ed8 39 init1_384 = 0x629a292a367cd507 40 init2_384 = 0x9159015a3070dd17 41 init3_384 = 0x152fecd8f70e5939 42 init4_384 = 0x67332667ffc00b31 43 init5_384 = 0x8eb44a8768581511 44 init6_384 = 0xdb0c2e0d64f98fa7 45 init7_384 = 0x47b5481dbefa4fa4 46 ) 47 48 // digest represents the partial evaluation of a checksum. 49 type digest struct { 50 h [8]uint64 51 x [chunk]byte 52 nx int 53 len uint64 54 is384 bool // mark if this digest is SHA-384 55 } 56 57 func (d *digest) Reset() { 58 if !d.is384 { 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_384 69 d.h[1] = init1_384 70 d.h[2] = init2_384 71 d.h[3] = init3_384 72 d.h[4] = init4_384 73 d.h[5] = init5_384 74 d.h[6] = init6_384 75 d.h[7] = init7_384 76 } 77 d.nx = 0 78 d.len = 0 79 } 80 81 // New returns a new hash.Hash computing the SHA512 checksum. 82 func New() hash.Hash { 83 d := new(digest) 84 d.Reset() 85 return d 86 } 87 88 // New384 returns a new hash.Hash computing the SHA384 checksum. 89 func New384() hash.Hash { 90 d := new(digest) 91 d.is384 = true 92 d.Reset() 93 return d 94 } 95 96 func (d *digest) Size() int { 97 if !d.is384 { 98 return Size 99 } 100 return Size384 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 := new(digest) 137 *d = *d0 138 hash := d.checkSum() 139 if d.is384 { 140 return append(in, hash[:Size384]...) 141 } 142 return append(in, hash[:]...) 143 } 144 145 func (d *digest) checkSum() [Size]byte { 146 // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. 147 len := d.len 148 var tmp [128]byte 149 tmp[0] = 0x80 150 if len%128 < 112 { 151 d.Write(tmp[0 : 112-len%128]) 152 } else { 153 d.Write(tmp[0 : 128+112-len%128]) 154 } 155 156 // Length in bits. 157 len <<= 3 158 for i := uint(0); i < 16; i++ { 159 tmp[i] = byte(len >> (120 - 8*i)) 160 } 161 d.Write(tmp[0:16]) 162 163 if d.nx != 0 { 164 panic("d.nx != 0") 165 } 166 167 h := d.h[:] 168 if d.is384 { 169 h = d.h[:6] 170 } 171 172 var digest [Size]byte 173 for i, s := range h { 174 digest[i*8] = byte(s >> 56) 175 digest[i*8+1] = byte(s >> 48) 176 digest[i*8+2] = byte(s >> 40) 177 digest[i*8+3] = byte(s >> 32) 178 digest[i*8+4] = byte(s >> 24) 179 digest[i*8+5] = byte(s >> 16) 180 digest[i*8+6] = byte(s >> 8) 181 digest[i*8+7] = byte(s) 182 } 183 184 return digest 185 } 186 187 // Sum512 returns the SHA512 checksum of the data. 188 func Sum512(data []byte) [Size]byte { 189 var d digest 190 d.Reset() 191 d.Write(data) 192 return d.checkSum() 193 } 194 195 // Sum384 returns the SHA384 checksum of the data. 196 func Sum384(data []byte) (sum384 [Size384]byte) { 197 var d digest 198 d.is384 = true 199 d.Reset() 200 d.Write(data) 201 sum := d.checkSum() 202 copy(sum384[:], sum[:Size384]) 203 return 204 }