I need to find the number of bits (and/or hex digits) generated by an openssl HMAC digest. I generated the following function which can be included with source command, but I could not tease out a simpler method from the openssl man pages.
#!/bin/bash
# The following wrapper assumes that this is included in a "source"
# statement and needs guarding against possible multiple includes due
# to nesting
if [[ -z "${__hmacsslmacbits}" ]] ; then
export __hmacsslmacbits=1
function sslmacbits()
# sslmacbits dgst
{
########################################################
# A constant to convert number of digest hex characters
# to the number of bits generated by a digest.
########################################################
local CHEXBITS=4
########################################################
# The name of the digest as arg #1.
########################################################
local dgstname
########################################################
# The digest generated from openssl and the hex string
# extracted from that.
########################################################
local digest
local digesthex
########################################################
# Use the installed copy of openssl to verify the
# information start by verifying openssl is installed
########################################################
which openssl > /dev/null
if [[ ! $? ]]; then
echo "Privileged retrival of openssl" >&2
sudo apt-get install openssl
fi
if [[ ! $# == 1 ]]; then
echo "${FUNCTION} missing digest name" >&2
exit 1
fi
dgstname=$1
########################################################
# Verify that the requested digest exists in the
# installed copy of openssl.
########################################################
openssl list -digest-commands\
|grep ${dgstname} > /dev/null
if [[ ! $? ]]; then
echo "${FUNCTION} ${dgstname} not installed " \
"in openssl" >&2
exit 2
fi
########################################################
# Make sure that openssl generates the strongest
# digest for the shake digests (see -xoflen):
# https://www.openssl.org/docs/man3.0/man1/openssl-dgst.html
########################################################
chkopenssl="openssl ${dgstname} -hex"
case ${dgstname} in
shake128)
chkopenssl="${chkopenssl} -xoflen 32"
;;
shake256)
chkopenssl="${chkopenssl} -xoflen 64"
;;
esac
########################################################
# Now we have the correct invocation of openssl for
# each digest invoke the digest on "Hello World"
# string and get the result
########################################################
digest=$(${chkopenssl} <<<"Hello World")
########################################################
# The resulting string in digest contains a string with
# the uppercase name of the digest, the file name
# (in this case stdin) in parentheses, followed by
# an "= " string and then the hex digits that compose
# the digest. E.G.
# SHA256(/etc/hosts)= 878ab7da...cb0f648b
# So we use a nice pattern match to strip off the
# unwanted characters at the front.
digesthex=${digest##*= }
########################################################
# Now we count the number of hex generated digits and
# convert that to the number of bits generated
########################################################
echo "$((${#digesthex} / ${CHEXBITS}))"
}
export -f sslmacbits
fi # if [[ -z "${__hmacsslmacbits}" ]]
I had hoped that something related to the property of openssl commands would yield the result, but the man page was sufficiently opaque that I could not find a path to the solution.
With my above script, I generate:
echo $(sslmacbits sha1)
and get
10 Hopefully there is a better method?
-binaryoption and pipe it throughwc -cto count the number of bytes, then multply by the appropriate factor for your needs, e.g. 8 for bytes or 2 for hex digits.list -digest-commandsdoes not list all hashes supported by (a particular build of) OpenSSL;list -digest-algorithmsdoes but it includes a bunch of synonyms that aren't really different hashes and some dummy values. OTOH some hashes (in particular SHAKE128/256, the ones you handle specially) can't be used for HMAC; you must instead use the underlying hash Keccak with KMAC -- NOT HMAC. And algorithm names in OpenSSL are case-insensitive (but commands are not).