github.com/tunabay/go-bitarray@v1.3.1/bitarray_sha256.go (about)

     1  // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved.
     2  // Use of this source code is governed by the MIT license that can be found in
     3  // the LICENSE file.
     4  
     5  package bitarray
     6  
     7  import (
     8  	_ "crypto/sha256" // block()
     9  	"encoding/binary"
    10  	_ "unsafe" // linkname
    11  )
    12  
    13  // SHA256 returns the SHA-256 checksum of the bit array. It treats the bit array
    14  // as a bit-oriented message to compute the checksum as defined in FIPS 180-4.
    15  func (ba *BitArray) SHA256() (d256 [32]byte) {
    16  	return ba.sha256CheckSum(false)
    17  }
    18  
    19  // SHA224 returns the SHA-224 checksum of the bit array. It treats the bit array
    20  // as a bit-oriented message to compute the checksum as defined in FIPS 180-4.
    21  func (ba *BitArray) SHA224() (d224 [28]byte) {
    22  	d256 := ba.sha256CheckSum(true)
    23  	copy(d224[:], d256[:])
    24  	return
    25  }
    26  
    27  func (ba *BitArray) sha256CheckSum(is224 bool) [32]byte {
    28  	nBits := ba.Len()
    29  	buf := NewBuffer((nBits + 1 + 64 + 511) &^ 511)
    30  	buf.PutBitArrayAt(0, ba)
    31  	buf.PutBitAt(nBits, 1)
    32  	binary.BigEndian.PutUint64(buf.b[len(buf.b)-8:], uint64(nBits))
    33  
    34  	d := &sha256Digest{is224: is224}
    35  	sha256Reset(d)
    36  	sha256Block(d, buf.b)
    37  
    38  	n := 8
    39  	if is224 {
    40  		n = 7
    41  	}
    42  	var d256 [32]byte
    43  	for i := 0; i < n; i++ {
    44  		binary.BigEndian.PutUint32(d256[i<<2:], d.h[i])
    45  	}
    46  
    47  	return d256
    48  }
    49  
    50  // crypto/sha256.digest
    51  // TODO: if possible, use crypto/sha256.digest directly
    52  type sha256Digest struct {
    53  	h     [8]uint32
    54  	x     [64]byte //nolint:structcheck,unused // for Reset()
    55  	nx    int      //nolint:structcheck,unused // for Reset()
    56  	len   uint64   //nolint:structcheck,unused // for Reset()
    57  	is224 bool
    58  }
    59  
    60  //go:linkname sha256Block crypto/sha256.block
    61  func sha256Block(*sha256Digest, []byte)
    62  
    63  //go:linkname sha256Reset crypto/sha256.(*digest).Reset
    64  func sha256Reset(*sha256Digest)