github.com/tunabay/go-bitarray@v1.3.1/bitarray_sha512.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"
     9  	_ "crypto/sha512" // block()
    10  	"encoding/binary"
    11  	_ "unsafe" // linkname
    12  )
    13  
    14  // SHA512 returns the SHA-512 checksum of the bit array. It treats the bit array
    15  // as a bit-oriented message to compute the checksum as defined in FIPS 180-4.
    16  func (ba *BitArray) SHA512() (d512 [64]byte) {
    17  	return ba.sha512CheckSum(crypto.SHA512)
    18  }
    19  
    20  // SHA384 returns the SHA-384 checksum of the bit array. It treats the bit array
    21  // as a bit-oriented message to compute the checksum as defined in FIPS 180-4.
    22  func (ba *BitArray) SHA384() (d384 [48]byte) {
    23  	d512 := ba.sha512CheckSum(crypto.SHA384)
    24  	copy(d384[:], d512[:])
    25  	return
    26  }
    27  
    28  // SHA512_256 returns the SHA-512/256 checksum of the bit array. It treats the
    29  // bit array as a bit-oriented message to compute the checksum as defined in
    30  // FIPS 180-4.
    31  //nolint:revive,stylecheck // not an ALL_CAPS
    32  func (ba *BitArray) SHA512_256() (d256 [32]byte) {
    33  	d512 := ba.sha512CheckSum(crypto.SHA512_256)
    34  	copy(d256[:], d512[:])
    35  	return
    36  }
    37  
    38  // SHA512_224 returns the SHA-512/224 checksum of the bit array. It treats the
    39  // bit array as a bit-oriented message to compute the digest as defined in FIPS
    40  // 180-4.
    41  //nolint:revive,stylecheck // not an ALL_CAPS
    42  func (ba *BitArray) SHA512_224() (d224 [28]byte) {
    43  	d512 := ba.sha512CheckSum(crypto.SHA512_224)
    44  	copy(d224[:], d512[:])
    45  	return
    46  }
    47  
    48  func (ba *BitArray) sha512CheckSum(hash crypto.Hash) [64]byte {
    49  	nBits := ba.Len()
    50  	buf := NewBuffer((nBits + 1 + 128 + 1023) &^ 1023)
    51  	buf.PutBitArrayAt(0, ba)
    52  	buf.PutBitAt(nBits, 1)
    53  	// binary.BigEndian.PutUint64(buf.b[len(buf.b)-16:], uint64(hi)) // for nBits > max-uint64
    54  	binary.BigEndian.PutUint64(buf.b[len(buf.b)-8:], uint64(nBits))
    55  
    56  	d := &sha512Digest{function: hash}
    57  	sha512Reset(d)
    58  	sha512Block(d, buf.b)
    59  
    60  	n := 8
    61  	if hash == crypto.SHA384 {
    62  		n = 6
    63  	}
    64  	var d512 [64]byte
    65  	for i := 0; i < n; i++ {
    66  		binary.BigEndian.PutUint64(d512[i<<3:], d.h[i])
    67  	}
    68  
    69  	return d512
    70  }
    71  
    72  // crypto/sha512.digest
    73  // TODO: if possible, use crypto/sha512.digest directly
    74  type sha512Digest struct {
    75  	h        [8]uint64
    76  	x        [128]byte //nolint:structcheck,unused // for Reset()
    77  	nx       int       //nolint:structcheck,unused // for Reset()
    78  	len      uint64    //nolint:structcheck,unused // for Reset()
    79  	function crypto.Hash
    80  }
    81  
    82  //go:linkname sha512Block crypto/sha512.block
    83  func sha512Block(*sha512Digest, []byte)
    84  
    85  //go:linkname sha512Reset crypto/sha512.(*digest).Reset
    86  func sha512Reset(*sha512Digest)