github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/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 := copy(d.x[d.nx:], p) 110 d.nx += n 111 if d.nx == chunk { 112 block(d, d.x[:]) 113 d.nx = 0 114 } 115 p = p[n:] 116 } 117 if len(p) >= chunk { 118 n := len(p) &^ (chunk - 1) 119 block(d, p[:n]) 120 p = p[n:] 121 } 122 if len(p) > 0 { 123 d.nx = copy(d.x[:], p) 124 } 125 return 126 } 127 128 func (d0 *digest) Sum(in []byte) []byte { 129 // Make a copy of d0 so that caller can keep writing and summing. 130 d := new(digest) 131 *d = *d0 132 hash := d.checkSum() 133 if d.is384 { 134 return append(in, hash[:Size384]...) 135 } 136 return append(in, hash[:]...) 137 } 138 139 func (d *digest) checkSum() [Size]byte { 140 // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. 141 len := d.len 142 var tmp [128]byte 143 tmp[0] = 0x80 144 if len%128 < 112 { 145 d.Write(tmp[0 : 112-len%128]) 146 } else { 147 d.Write(tmp[0 : 128+112-len%128]) 148 } 149 150 // Length in bits. 151 len <<= 3 152 for i := uint(0); i < 16; i++ { 153 tmp[i] = byte(len >> (120 - 8*i)) 154 } 155 d.Write(tmp[0:16]) 156 157 if d.nx != 0 { 158 panic("d.nx != 0") 159 } 160 161 h := d.h[:] 162 if d.is384 { 163 h = d.h[:6] 164 } 165 166 var digest [Size]byte 167 for i, s := range h { 168 digest[i*8] = byte(s >> 56) 169 digest[i*8+1] = byte(s >> 48) 170 digest[i*8+2] = byte(s >> 40) 171 digest[i*8+3] = byte(s >> 32) 172 digest[i*8+4] = byte(s >> 24) 173 digest[i*8+5] = byte(s >> 16) 174 digest[i*8+6] = byte(s >> 8) 175 digest[i*8+7] = byte(s) 176 } 177 178 return digest 179 } 180 181 // Sum512 returns the SHA512 checksum of the data. 182 func Sum512(data []byte) [Size]byte { 183 var d digest 184 d.Reset() 185 d.Write(data) 186 return d.checkSum() 187 } 188 189 // Sum384 returns the SHA384 checksum of the data. 190 func Sum384(data []byte) (sum384 [Size384]byte) { 191 var d digest 192 d.is384 = true 193 d.Reset() 194 d.Write(data) 195 sum := d.checkSum() 196 copy(sum384[:], sum[:Size384]) 197 return 198 }