// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sha256 implements the SHA224 and SHA256 hash algorithms as defined // in FIPS 180-4.
package sha256 import ( ) func init() { crypto.RegisterHash(crypto.SHA224, New224) crypto.RegisterHash(crypto.SHA256, New) } // The size of a SHA256 checksum in bytes. const Size = 32 // The size of a SHA224 checksum in bytes. const Size224 = 28 // The blocksize of SHA256 and SHA224 in bytes. const BlockSize = 64 const ( chunk = 64 init0 = 0x6A09E667 init1 = 0xBB67AE85 init2 = 0x3C6EF372 init3 = 0xA54FF53A init4 = 0x510E527F init5 = 0x9B05688C init6 = 0x1F83D9AB init7 = 0x5BE0CD19 init0_224 = 0xC1059ED8 init1_224 = 0x367CD507 init2_224 = 0x3070DD17 init3_224 = 0xF70E5939 init4_224 = 0xFFC00B31 init5_224 = 0x68581511 init6_224 = 0x64F98FA7 init7_224 = 0xBEFA4FA4 ) // digest represents the partial evaluation of a checksum. type digest struct { h [8]uint32 x [chunk]byte nx int len uint64 is224 bool // mark if this digest is SHA-224 } const ( magic224 = "sha\x02" magic256 = "sha\x03" marshaledSize = len(magic256) + 8*4 + chunk + 8 ) func ( *digest) () ([]byte, error) { := make([]byte, 0, marshaledSize) if .is224 { = append(, magic224...) } else { = append(, magic256...) } = appendUint32(, .h[0]) = appendUint32(, .h[1]) = appendUint32(, .h[2]) = appendUint32(, .h[3]) = appendUint32(, .h[4]) = appendUint32(, .h[5]) = appendUint32(, .h[6]) = appendUint32(, .h[7]) = append(, .x[:.nx]...) = [:len()+len(.x)-int(.nx)] // already zero = appendUint64(, .len) return , nil } func ( *digest) ( []byte) error { if len() < len(magic224) || (.is224 && string([:len(magic224)]) != magic224) || (!.is224 && string([:len(magic256)]) != magic256) { return errors.New("crypto/sha256: invalid hash state identifier") } if len() != marshaledSize { return errors.New("crypto/sha256: invalid hash state size") } = [len(magic224):] , .h[0] = consumeUint32() , .h[1] = consumeUint32() , .h[2] = consumeUint32() , .h[3] = consumeUint32() , .h[4] = consumeUint32() , .h[5] = consumeUint32() , .h[6] = consumeUint32() , .h[7] = consumeUint32() = [copy(.x[:], ):] , .len = consumeUint64() .nx = int(.len % chunk) return nil } func appendUint64( []byte, uint64) []byte { var [8]byte binary.BigEndian.PutUint64([:], ) return append(, [:]...) } func appendUint32( []byte, uint32) []byte { var [4]byte binary.BigEndian.PutUint32([:], ) return append(, [:]...) } func consumeUint64( []byte) ([]byte, uint64) { _ = [7] := uint64([7]) | uint64([6])<<8 | uint64([5])<<16 | uint64([4])<<24 | uint64([3])<<32 | uint64([2])<<40 | uint64([1])<<48 | uint64([0])<<56 return [8:], } func consumeUint32( []byte) ([]byte, uint32) { _ = [3] := uint32([3]) | uint32([2])<<8 | uint32([1])<<16 | uint32([0])<<24 return [4:], } func ( *digest) () { if !.is224 { .h[0] = init0 .h[1] = init1 .h[2] = init2 .h[3] = init3 .h[4] = init4 .h[5] = init5 .h[6] = init6 .h[7] = init7 } else { .h[0] = init0_224 .h[1] = init1_224 .h[2] = init2_224 .h[3] = init3_224 .h[4] = init4_224 .h[5] = init5_224 .h[6] = init6_224 .h[7] = init7_224 } .nx = 0 .len = 0 } // New returns a new hash.Hash computing the SHA256 checksum. The Hash // also implements encoding.BinaryMarshaler and // encoding.BinaryUnmarshaler to marshal and unmarshal the internal // state of the hash. func () hash.Hash { := new(digest) .Reset() return } // New224 returns a new hash.Hash computing the SHA224 checksum. func () hash.Hash { := new(digest) .is224 = true .Reset() return } func ( *digest) () int { if !.is224 { return Size } return Size224 } func ( *digest) () int { return BlockSize } func ( *digest) ( []byte) ( int, error) { = len() .len += uint64() if .nx > 0 { := copy(.x[.nx:], ) .nx += if .nx == chunk { block(, .x[:]) .nx = 0 } = [:] } if len() >= chunk { := len() &^ (chunk - 1) block(, [:]) = [:] } if len() > 0 { .nx = copy(.x[:], ) } return } func ( *digest) ( []byte) []byte { // Make a copy of d so that caller can keep writing and summing. := * := .checkSum() if .is224 { return append(, [:Size224]...) } return append(, [:]...) } func ( *digest) () [Size]byte { := .len // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. var [64]byte [0] = 0x80 if %64 < 56 { .Write([0 : 56-%64]) } else { .Write([0 : 64+56-%64]) } // Length in bits. <<= 3 binary.BigEndian.PutUint64([:], ) .Write([0:8]) if .nx != 0 { panic("d.nx != 0") } var [Size]byte binary.BigEndian.PutUint32([0:], .h[0]) binary.BigEndian.PutUint32([4:], .h[1]) binary.BigEndian.PutUint32([8:], .h[2]) binary.BigEndian.PutUint32([12:], .h[3]) binary.BigEndian.PutUint32([16:], .h[4]) binary.BigEndian.PutUint32([20:], .h[5]) binary.BigEndian.PutUint32([24:], .h[6]) if !.is224 { binary.BigEndian.PutUint32([28:], .h[7]) } return } // Sum256 returns the SHA256 checksum of the data. func ( []byte) [Size]byte { var digest .Reset() .Write() return .checkSum() } // Sum224 returns the SHA224 checksum of the data. func ( []byte) ( [Size224]byte) { var digest .is224 = true .Reset() .Write() := .checkSum() copy([:], [:Size224]) return }