// 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 SHA-224 and SHA-256 hash algorithms as defined // in FIPS 180-4.
package sha256 import ( ) // The size of a SHA-256 checksum in bytes. const size = 32 // The size of a SHA-224 checksum in bytes. const size224 = 28 // The block size of SHA-256 and SHA-224 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 is a SHA-224 or SHA-256 [hash.Hash] implementation. 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) { return .AppendBinary(make([]byte, 0, marshaledSize)) } func ( *Digest) ( []byte) ([]byte, error) { if .is224 { = append(, magic224...) } else { = append(, magic256...) } = byteorder.BEAppendUint32(, .h[0]) = byteorder.BEAppendUint32(, .h[1]) = byteorder.BEAppendUint32(, .h[2]) = byteorder.BEAppendUint32(, .h[3]) = byteorder.BEAppendUint32(, .h[4]) = byteorder.BEAppendUint32(, .h[5]) = byteorder.BEAppendUint32(, .h[6]) = byteorder.BEAppendUint32(, .h[7]) = append(, .x[:.nx]...) = append(, make([]byte, len(.x)-.nx)...) = byteorder.BEAppendUint64(, .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 consumeUint64( []byte) ([]byte, uint64) { return [8:], byteorder.BEUint64() } func consumeUint32( []byte) ([]byte, uint32) { return [4:], byteorder.BEUint32() } 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 Digest computing the SHA-256 hash. func () *Digest { := new(Digest) .Reset() return } // New224 returns a new Digest computing the SHA-224 hash. func () *Digest { := 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 { fips140.RecordApproved() // 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 + 8]byte // padding + length buffer [0] = 0x80 var uint64 if %64 < 56 { = 56 - %64 } else { = 64 + 56 - %64 } // Length in bits. <<= 3 := [:+8] byteorder.BEPutUint64([+0:], ) .Write() if .nx != 0 { panic("d.nx != 0") } var [size]byte byteorder.BEPutUint32([0:], .h[0]) byteorder.BEPutUint32([4:], .h[1]) byteorder.BEPutUint32([8:], .h[2]) byteorder.BEPutUint32([12:], .h[3]) byteorder.BEPutUint32([16:], .h[4]) byteorder.BEPutUint32([20:], .h[5]) byteorder.BEPutUint32([24:], .h[6]) if !.is224 { byteorder.BEPutUint32([28:], .h[7]) } return }