...

Source file src/crypto/sha512/sha512.go

Documentation: crypto/sha512

		 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 SHA-384, SHA-512, SHA-512/224, and SHA-512/256
		 6  // hash algorithms as defined in FIPS 180-4.
		 7  //
		 8  // All the hash.Hash implementations returned by this package also
		 9  // implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
		10  // marshal and unmarshal the internal state of the hash.
		11  package sha512
		12  
		13  import (
		14  	"crypto"
		15  	"encoding/binary"
		16  	"errors"
		17  	"hash"
		18  )
		19  
		20  func init() {
		21  	crypto.RegisterHash(crypto.SHA384, New384)
		22  	crypto.RegisterHash(crypto.SHA512, New)
		23  	crypto.RegisterHash(crypto.SHA512_224, New512_224)
		24  	crypto.RegisterHash(crypto.SHA512_256, New512_256)
		25  }
		26  
		27  const (
		28  	// Size is the size, in bytes, of a SHA-512 checksum.
		29  	Size = 64
		30  
		31  	// Size224 is the size, in bytes, of a SHA-512/224 checksum.
		32  	Size224 = 28
		33  
		34  	// Size256 is the size, in bytes, of a SHA-512/256 checksum.
		35  	Size256 = 32
		36  
		37  	// Size384 is the size, in bytes, of a SHA-384 checksum.
		38  	Size384 = 48
		39  
		40  	// BlockSize is the block size, in bytes, of the SHA-512/224,
		41  	// SHA-512/256, SHA-384 and SHA-512 hash functions.
		42  	BlockSize = 128
		43  )
		44  
		45  const (
		46  	chunk		 = 128
		47  	init0		 = 0x6a09e667f3bcc908
		48  	init1		 = 0xbb67ae8584caa73b
		49  	init2		 = 0x3c6ef372fe94f82b
		50  	init3		 = 0xa54ff53a5f1d36f1
		51  	init4		 = 0x510e527fade682d1
		52  	init5		 = 0x9b05688c2b3e6c1f
		53  	init6		 = 0x1f83d9abfb41bd6b
		54  	init7		 = 0x5be0cd19137e2179
		55  	init0_224 = 0x8c3d37c819544da2
		56  	init1_224 = 0x73e1996689dcd4d6
		57  	init2_224 = 0x1dfab7ae32ff9c82
		58  	init3_224 = 0x679dd514582f9fcf
		59  	init4_224 = 0x0f6d2b697bd44da8
		60  	init5_224 = 0x77e36f7304c48942
		61  	init6_224 = 0x3f9d85a86a1d36c8
		62  	init7_224 = 0x1112e6ad91d692a1
		63  	init0_256 = 0x22312194fc2bf72c
		64  	init1_256 = 0x9f555fa3c84c64c2
		65  	init2_256 = 0x2393b86b6f53b151
		66  	init3_256 = 0x963877195940eabd
		67  	init4_256 = 0x96283ee2a88effe3
		68  	init5_256 = 0xbe5e1e2553863992
		69  	init6_256 = 0x2b0199fc2c85b8aa
		70  	init7_256 = 0x0eb72ddc81c52ca2
		71  	init0_384 = 0xcbbb9d5dc1059ed8
		72  	init1_384 = 0x629a292a367cd507
		73  	init2_384 = 0x9159015a3070dd17
		74  	init3_384 = 0x152fecd8f70e5939
		75  	init4_384 = 0x67332667ffc00b31
		76  	init5_384 = 0x8eb44a8768581511
		77  	init6_384 = 0xdb0c2e0d64f98fa7
		78  	init7_384 = 0x47b5481dbefa4fa4
		79  )
		80  
		81  // digest represents the partial evaluation of a checksum.
		82  type digest struct {
		83  	h				[8]uint64
		84  	x				[chunk]byte
		85  	nx			 int
		86  	len			uint64
		87  	function crypto.Hash
		88  }
		89  
		90  func (d *digest) Reset() {
		91  	switch d.function {
		92  	case crypto.SHA384:
		93  		d.h[0] = init0_384
		94  		d.h[1] = init1_384
		95  		d.h[2] = init2_384
		96  		d.h[3] = init3_384
		97  		d.h[4] = init4_384
		98  		d.h[5] = init5_384
		99  		d.h[6] = init6_384
	 100  		d.h[7] = init7_384
	 101  	case crypto.SHA512_224:
	 102  		d.h[0] = init0_224
	 103  		d.h[1] = init1_224
	 104  		d.h[2] = init2_224
	 105  		d.h[3] = init3_224
	 106  		d.h[4] = init4_224
	 107  		d.h[5] = init5_224
	 108  		d.h[6] = init6_224
	 109  		d.h[7] = init7_224
	 110  	case crypto.SHA512_256:
	 111  		d.h[0] = init0_256
	 112  		d.h[1] = init1_256
	 113  		d.h[2] = init2_256
	 114  		d.h[3] = init3_256
	 115  		d.h[4] = init4_256
	 116  		d.h[5] = init5_256
	 117  		d.h[6] = init6_256
	 118  		d.h[7] = init7_256
	 119  	default:
	 120  		d.h[0] = init0
	 121  		d.h[1] = init1
	 122  		d.h[2] = init2
	 123  		d.h[3] = init3
	 124  		d.h[4] = init4
	 125  		d.h[5] = init5
	 126  		d.h[6] = init6
	 127  		d.h[7] = init7
	 128  	}
	 129  	d.nx = 0
	 130  	d.len = 0
	 131  }
	 132  
	 133  const (
	 134  	magic384			= "sha\x04"
	 135  	magic512_224	= "sha\x05"
	 136  	magic512_256	= "sha\x06"
	 137  	magic512			= "sha\x07"
	 138  	marshaledSize = len(magic512) + 8*8 + chunk + 8
	 139  )
	 140  
	 141  func (d *digest) MarshalBinary() ([]byte, error) {
	 142  	b := make([]byte, 0, marshaledSize)
	 143  	switch d.function {
	 144  	case crypto.SHA384:
	 145  		b = append(b, magic384...)
	 146  	case crypto.SHA512_224:
	 147  		b = append(b, magic512_224...)
	 148  	case crypto.SHA512_256:
	 149  		b = append(b, magic512_256...)
	 150  	case crypto.SHA512:
	 151  		b = append(b, magic512...)
	 152  	default:
	 153  		return nil, errors.New("crypto/sha512: invalid hash function")
	 154  	}
	 155  	b = appendUint64(b, d.h[0])
	 156  	b = appendUint64(b, d.h[1])
	 157  	b = appendUint64(b, d.h[2])
	 158  	b = appendUint64(b, d.h[3])
	 159  	b = appendUint64(b, d.h[4])
	 160  	b = appendUint64(b, d.h[5])
	 161  	b = appendUint64(b, d.h[6])
	 162  	b = appendUint64(b, d.h[7])
	 163  	b = append(b, d.x[:d.nx]...)
	 164  	b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
	 165  	b = appendUint64(b, d.len)
	 166  	return b, nil
	 167  }
	 168  
	 169  func (d *digest) UnmarshalBinary(b []byte) error {
	 170  	if len(b) < len(magic512) {
	 171  		return errors.New("crypto/sha512: invalid hash state identifier")
	 172  	}
	 173  	switch {
	 174  	case d.function == crypto.SHA384 && string(b[:len(magic384)]) == magic384:
	 175  	case d.function == crypto.SHA512_224 && string(b[:len(magic512_224)]) == magic512_224:
	 176  	case d.function == crypto.SHA512_256 && string(b[:len(magic512_256)]) == magic512_256:
	 177  	case d.function == crypto.SHA512 && string(b[:len(magic512)]) == magic512:
	 178  	default:
	 179  		return errors.New("crypto/sha512: invalid hash state identifier")
	 180  	}
	 181  	if len(b) != marshaledSize {
	 182  		return errors.New("crypto/sha512: invalid hash state size")
	 183  	}
	 184  	b = b[len(magic512):]
	 185  	b, d.h[0] = consumeUint64(b)
	 186  	b, d.h[1] = consumeUint64(b)
	 187  	b, d.h[2] = consumeUint64(b)
	 188  	b, d.h[3] = consumeUint64(b)
	 189  	b, d.h[4] = consumeUint64(b)
	 190  	b, d.h[5] = consumeUint64(b)
	 191  	b, d.h[6] = consumeUint64(b)
	 192  	b, d.h[7] = consumeUint64(b)
	 193  	b = b[copy(d.x[:], b):]
	 194  	b, d.len = consumeUint64(b)
	 195  	d.nx = int(d.len % chunk)
	 196  	return nil
	 197  }
	 198  
	 199  func appendUint64(b []byte, x uint64) []byte {
	 200  	var a [8]byte
	 201  	binary.BigEndian.PutUint64(a[:], x)
	 202  	return append(b, a[:]...)
	 203  }
	 204  
	 205  func consumeUint64(b []byte) ([]byte, uint64) {
	 206  	_ = b[7]
	 207  	x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
	 208  		uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
	 209  	return b[8:], x
	 210  }
	 211  
	 212  // New returns a new hash.Hash computing the SHA-512 checksum.
	 213  func New() hash.Hash {
	 214  	d := &digest{function: crypto.SHA512}
	 215  	d.Reset()
	 216  	return d
	 217  }
	 218  
	 219  // New512_224 returns a new hash.Hash computing the SHA-512/224 checksum.
	 220  func New512_224() hash.Hash {
	 221  	d := &digest{function: crypto.SHA512_224}
	 222  	d.Reset()
	 223  	return d
	 224  }
	 225  
	 226  // New512_256 returns a new hash.Hash computing the SHA-512/256 checksum.
	 227  func New512_256() hash.Hash {
	 228  	d := &digest{function: crypto.SHA512_256}
	 229  	d.Reset()
	 230  	return d
	 231  }
	 232  
	 233  // New384 returns a new hash.Hash computing the SHA-384 checksum.
	 234  func New384() hash.Hash {
	 235  	d := &digest{function: crypto.SHA384}
	 236  	d.Reset()
	 237  	return d
	 238  }
	 239  
	 240  func (d *digest) Size() int {
	 241  	switch d.function {
	 242  	case crypto.SHA512_224:
	 243  		return Size224
	 244  	case crypto.SHA512_256:
	 245  		return Size256
	 246  	case crypto.SHA384:
	 247  		return Size384
	 248  	default:
	 249  		return Size
	 250  	}
	 251  }
	 252  
	 253  func (d *digest) BlockSize() int { return BlockSize }
	 254  
	 255  func (d *digest) Write(p []byte) (nn int, err error) {
	 256  	nn = len(p)
	 257  	d.len += uint64(nn)
	 258  	if d.nx > 0 {
	 259  		n := copy(d.x[d.nx:], p)
	 260  		d.nx += n
	 261  		if d.nx == chunk {
	 262  			block(d, d.x[:])
	 263  			d.nx = 0
	 264  		}
	 265  		p = p[n:]
	 266  	}
	 267  	if len(p) >= chunk {
	 268  		n := len(p) &^ (chunk - 1)
	 269  		block(d, p[:n])
	 270  		p = p[n:]
	 271  	}
	 272  	if len(p) > 0 {
	 273  		d.nx = copy(d.x[:], p)
	 274  	}
	 275  	return
	 276  }
	 277  
	 278  func (d *digest) Sum(in []byte) []byte {
	 279  	// Make a copy of d so that caller can keep writing and summing.
	 280  	d0 := new(digest)
	 281  	*d0 = *d
	 282  	hash := d0.checkSum()
	 283  	switch d0.function {
	 284  	case crypto.SHA384:
	 285  		return append(in, hash[:Size384]...)
	 286  	case crypto.SHA512_224:
	 287  		return append(in, hash[:Size224]...)
	 288  	case crypto.SHA512_256:
	 289  		return append(in, hash[:Size256]...)
	 290  	default:
	 291  		return append(in, hash[:]...)
	 292  	}
	 293  }
	 294  
	 295  func (d *digest) checkSum() [Size]byte {
	 296  	// Padding. Add a 1 bit and 0 bits until 112 bytes mod 128.
	 297  	len := d.len
	 298  	var tmp [128]byte
	 299  	tmp[0] = 0x80
	 300  	if len%128 < 112 {
	 301  		d.Write(tmp[0 : 112-len%128])
	 302  	} else {
	 303  		d.Write(tmp[0 : 128+112-len%128])
	 304  	}
	 305  
	 306  	// Length in bits.
	 307  	len <<= 3
	 308  	binary.BigEndian.PutUint64(tmp[0:], 0) // upper 64 bits are always zero, because len variable has type uint64
	 309  	binary.BigEndian.PutUint64(tmp[8:], len)
	 310  	d.Write(tmp[0:16])
	 311  
	 312  	if d.nx != 0 {
	 313  		panic("d.nx != 0")
	 314  	}
	 315  
	 316  	var digest [Size]byte
	 317  	binary.BigEndian.PutUint64(digest[0:], d.h[0])
	 318  	binary.BigEndian.PutUint64(digest[8:], d.h[1])
	 319  	binary.BigEndian.PutUint64(digest[16:], d.h[2])
	 320  	binary.BigEndian.PutUint64(digest[24:], d.h[3])
	 321  	binary.BigEndian.PutUint64(digest[32:], d.h[4])
	 322  	binary.BigEndian.PutUint64(digest[40:], d.h[5])
	 323  	if d.function != crypto.SHA384 {
	 324  		binary.BigEndian.PutUint64(digest[48:], d.h[6])
	 325  		binary.BigEndian.PutUint64(digest[56:], d.h[7])
	 326  	}
	 327  
	 328  	return digest
	 329  }
	 330  
	 331  // Sum512 returns the SHA512 checksum of the data.
	 332  func Sum512(data []byte) [Size]byte {
	 333  	d := digest{function: crypto.SHA512}
	 334  	d.Reset()
	 335  	d.Write(data)
	 336  	return d.checkSum()
	 337  }
	 338  
	 339  // Sum384 returns the SHA384 checksum of the data.
	 340  func Sum384(data []byte) (sum384 [Size384]byte) {
	 341  	d := digest{function: crypto.SHA384}
	 342  	d.Reset()
	 343  	d.Write(data)
	 344  	sum := d.checkSum()
	 345  	copy(sum384[:], sum[:Size384])
	 346  	return
	 347  }
	 348  
	 349  // Sum512_224 returns the Sum512/224 checksum of the data.
	 350  func Sum512_224(data []byte) (sum224 [Size224]byte) {
	 351  	d := digest{function: crypto.SHA512_224}
	 352  	d.Reset()
	 353  	d.Write(data)
	 354  	sum := d.checkSum()
	 355  	copy(sum224[:], sum[:Size224])
	 356  	return
	 357  }
	 358  
	 359  // Sum512_256 returns the Sum512/256 checksum of the data.
	 360  func Sum512_256(data []byte) (sum256 [Size256]byte) {
	 361  	d := digest{function: crypto.SHA512_256}
	 362  	d.Reset()
	 363  	d.Write(data)
	 364  	sum := d.checkSum()
	 365  	copy(sum256[:], sum[:Size256])
	 366  	return
	 367  }
	 368  

View as plain text