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)