src/pkg/crypto/sha512/sha512.go - The Go Programming Language

Golang

Source file src/pkg/crypto/sha512/sha512.go

     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		n := _Block(d, p)
   124		p = p[n:]
   125		if len(p) > 0 {
   126			d.nx = copy(d.x[:], p)
   127		}
   128		return
   129	}
   130	
   131	func (d0 *digest) Sum(in []byte) []byte {
   132		// Make a copy of d0 so that caller can keep writing and summing.
   133		d := new(digest)
   134		*d = *d0
   135	
   136		// Padding.  Add a 1 bit and 0 bits until 112 bytes mod 128.
   137		len := d.len
   138		var tmp [128]byte
   139		tmp[0] = 0x80
   140		if len%128 < 112 {
   141			d.Write(tmp[0 : 112-len%128])
   142		} else {
   143			d.Write(tmp[0 : 128+112-len%128])
   144		}
   145	
   146		// Length in bits.
   147		len <<= 3
   148		for i := uint(0); i < 16; i++ {
   149			tmp[i] = byte(len >> (120 - 8*i))
   150		}
   151		d.Write(tmp[0:16])
   152	
   153		if d.nx != 0 {
   154			panic("d.nx != 0")
   155		}
   156	
   157		h := d.h[:]
   158		size := Size
   159		if d.is384 {
   160			h = d.h[:6]
   161			size = Size384
   162		}
   163	
   164		var digest [Size]byte
   165		for i, s := range h {
   166			digest[i*8] = byte(s >> 56)
   167			digest[i*8+1] = byte(s >> 48)
   168			digest[i*8+2] = byte(s >> 40)
   169			digest[i*8+3] = byte(s >> 32)
   170			digest[i*8+4] = byte(s >> 24)
   171			digest[i*8+5] = byte(s >> 16)
   172			digest[i*8+6] = byte(s >> 8)
   173			digest[i*8+7] = byte(s)
   174		}
   175	
   176		return append(in, digest[:size]...)
   177	}