package sha256
import (
"crypto/internal/fips140"
"crypto/internal/fips140deps/byteorder"
"errors"
)
const size = 32
const size224 = 28
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
)
type Digest struct {
h [8 ]uint32
x [chunk ]byte
nx int
len uint64
is224 bool
}
const (
magic224 = "sha\x02"
magic256 = "sha\x03"
marshaledSize = len (magic256 ) + 8 *4 + chunk + 8
)
func (d *Digest ) MarshalBinary () ([]byte , error ) {
return d .AppendBinary (make ([]byte , 0 , marshaledSize ))
}
func (d *Digest ) AppendBinary (b []byte ) ([]byte , error ) {
if d .is224 {
b = append (b , magic224 ...)
} else {
b = append (b , magic256 ...)
}
b = byteorder .BEAppendUint32 (b , d .h [0 ])
b = byteorder .BEAppendUint32 (b , d .h [1 ])
b = byteorder .BEAppendUint32 (b , d .h [2 ])
b = byteorder .BEAppendUint32 (b , d .h [3 ])
b = byteorder .BEAppendUint32 (b , d .h [4 ])
b = byteorder .BEAppendUint32 (b , d .h [5 ])
b = byteorder .BEAppendUint32 (b , d .h [6 ])
b = byteorder .BEAppendUint32 (b , d .h [7 ])
b = append (b , d .x [:d .nx ]...)
b = append (b , make ([]byte , len (d .x )-d .nx )...)
b = byteorder .BEAppendUint64 (b , d .len )
return b , nil
}
func (d *Digest ) UnmarshalBinary (b []byte ) error {
if len (b ) < len (magic224 ) || (d .is224 && string (b [:len (magic224 )]) != magic224 ) || (!d .is224 && string (b [:len (magic256 )]) != magic256 ) {
return errors .New ("crypto/sha256: invalid hash state identifier" )
}
if len (b ) != marshaledSize {
return errors .New ("crypto/sha256: invalid hash state size" )
}
b = b [len (magic224 ):]
b , d .h [0 ] = consumeUint32 (b )
b , d .h [1 ] = consumeUint32 (b )
b , d .h [2 ] = consumeUint32 (b )
b , d .h [3 ] = consumeUint32 (b )
b , d .h [4 ] = consumeUint32 (b )
b , d .h [5 ] = consumeUint32 (b )
b , d .h [6 ] = consumeUint32 (b )
b , d .h [7 ] = consumeUint32 (b )
b = b [copy (d .x [:], b ):]
b , d .len = consumeUint64 (b )
d .nx = int (d .len % chunk )
return nil
}
func consumeUint64(b []byte ) ([]byte , uint64 ) {
return b [8 :], byteorder .BEUint64 (b )
}
func consumeUint32(b []byte ) ([]byte , uint32 ) {
return b [4 :], byteorder .BEUint32 (b )
}
func (d *Digest ) Reset () {
if !d .is224 {
d .h [0 ] = init0
d .h [1 ] = init1
d .h [2 ] = init2
d .h [3 ] = init3
d .h [4 ] = init4
d .h [5 ] = init5
d .h [6 ] = init6
d .h [7 ] = init7
} else {
d .h [0 ] = init0_224
d .h [1 ] = init1_224
d .h [2 ] = init2_224
d .h [3 ] = init3_224
d .h [4 ] = init4_224
d .h [5 ] = init5_224
d .h [6 ] = init6_224
d .h [7 ] = init7_224
}
d .nx = 0
d .len = 0
}
func New () *Digest {
d := new (Digest )
d .Reset ()
return d
}
func New224 () *Digest {
d := new (Digest )
d .is224 = true
d .Reset ()
return d
}
func (d *Digest ) Size () int {
if !d .is224 {
return size
}
return size224
}
func (d *Digest ) BlockSize () int { return blockSize }
func (d *Digest ) Write (p []byte ) (nn int , err error ) {
nn = len (p )
d .len += uint64 (nn )
if d .nx > 0 {
n := copy (d .x [d .nx :], p )
d .nx += n
if d .nx == chunk {
block (d , d .x [:])
d .nx = 0
}
p = p [n :]
}
if len (p ) >= chunk {
n := len (p ) &^ (chunk - 1 )
block (d , p [:n ])
p = p [n :]
}
if len (p ) > 0 {
d .nx = copy (d .x [:], p )
}
return
}
func (d *Digest ) Sum (in []byte ) []byte {
fips140 .RecordApproved ()
d0 := *d
hash := d0 .checkSum ()
if d0 .is224 {
return append (in , hash [:size224 ]...)
}
return append (in , hash [:]...)
}
func (d *Digest ) checkSum () [size ]byte {
len := d .len
var tmp [64 + 8 ]byte
tmp [0 ] = 0x80
var t uint64
if len %64 < 56 {
t = 56 - len %64
} else {
t = 64 + 56 - len %64
}
len <<= 3
padlen := tmp [:t +8 ]
byteorder .BEPutUint64 (padlen [t +0 :], len )
d .Write (padlen )
if d .nx != 0 {
panic ("d.nx != 0" )
}
var digest [size ]byte
byteorder .BEPutUint32 (digest [0 :], d .h [0 ])
byteorder .BEPutUint32 (digest [4 :], d .h [1 ])
byteorder .BEPutUint32 (digest [8 :], d .h [2 ])
byteorder .BEPutUint32 (digest [12 :], d .h [3 ])
byteorder .BEPutUint32 (digest [16 :], d .h [4 ])
byteorder .BEPutUint32 (digest [20 :], d .h [5 ])
byteorder .BEPutUint32 (digest [24 :], d .h [6 ])
if !d .is224 {
byteorder .BEPutUint32 (digest [28 :], d .h [7 ])
}
return digest
}
The pages are generated with Golds v0.7.3-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .