0

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?

3
  • It might be easier to output with the -binary option and pipe it through wc -c to count the number of bytes, then multply by the appropriate factor for your needs, e.g. 8 for bytes or 2 for hex digits. Commented Oct 1, 2023 at 23:20
  • list -digest-commands does not list all hashes supported by (a particular build of) OpenSSL; list -digest-algorithms does 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). Commented Oct 2, 2023 at 1:44
  • Thanks for the feedback. I obviously have an uphill learning curve to master. It is a shame that the output of list -digest-algorithms is not easier to parse and deduplicate, but that is just a SMOP (Small Matter of Programming). Commented Oct 2, 2023 at 6:48

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.