如何确定OpenSSL HMAC摘要的默认长度?
获取OpenSSL HMAC摘要比特数的优化方案
需求说明
需要获取OpenSSL支持的HMAC摘要生成的比特数(或十六进制位数),原通过自定义bash函数实现,执行echo $(sslmacbits sha1)可得到结果10,但希望找到更高效的实现方式。
原实现思路
原脚本通过生成实际摘要、提取十六进制结果、计算长度转换为目标数值,同时处理了SHAKE系列可变长度摘要的特殊情况,还包含OpenSSL安装检查、摘要有效性验证逻辑。
优化实现方案
方案1:利用摘要固有长度映射表(高效无依赖)
大部分摘要算法的输出长度是固定的,直接构建映射表返回结果,SHAKE系列单独处理,避免生成实际摘要的开销:
#!/bin/bash if [[ -z "${__hmacsslmacbits_opt}" ]]; then export __hmacsslmacbits_opt=1 function sslmacbits() { local dgstname=$1 # 固定摘要算法的比特数映射表(若需原脚本输出的"字符数/4"结果,可将数值改为对应值,如sha1改为10) declare -A digest_bits=( ["md5"]=128 ["sha1"]=160 ["sha224"]=224 ["sha256"]=256 ["sha384"]=384 ["sha512"]=512 ["sha512-224"]=224 ["sha512-256"]=256 ["sha3-224"]=224 ["sha3-256"]=256 ["sha3-384"]=384 ["sha3-512"]=512 ["blake2b512"]=512 ["blake2s256"]=256 ["ripemd160"]=160 ) # 参数检查 if [[ $# -ne 1 ]]; then echo "用法: sslmacbits <摘要算法名>" >&2 return 1 fi # 检查OpenSSL是否安装 if ! command -v openssl &> /dev/null; then echo "未找到openssl,尝试自动安装..." >&2 sudo apt-get install -y openssl || return 3 fi # 检查摘要算法是否存在 if ! openssl list -digest-commands | grep -q "^${dgstname}$"; then echo "指定的摘要算法${dgstname}未在当前OpenSSL中支持" >&2 return 2 fi # 处理可变长度的SHAKE系列 case $dgstname in shake128) # 按原脚本逻辑使用32字节(256比特)作为默认长度,若需原输出则改为8 echo 256 ;; shake256) # 按原脚本逻辑使用64字节(512比特)作为默认长度,若需原输出则改为16 echo 512 ;; *) # 从映射表获取固定长度 if [[ -n "${digest_bits[$dgstname]}" ]]; then echo "${digest_bits[$dgstname]}" else # 兼容未知固定长度算法, fallback到原方法 local digest=$((openssl ${dgstname} -hex <<<"Hello World") | awk -F'= ' '{print $2}') # 若需保持原脚本的"字符数/4"输出,改为echo $(( ${#digest} / 4 )) echo $(( ${#digest} * 4 )) fi ;; esac } export -f sslmacbits fi
方案2:简化原脚本的执行流程
如果不想用映射表,可简化原脚本的摘要提取逻辑,用awk直接分割结果,减少字符串处理复杂度:
#!/bin/bash if [[ -z "${__hmacsslmacbits_simple}" ]]; then export __hmacsslmacbits_simple=1 function sslmacbits() { local CHEXBITS=4 local dgstname=$1 if [[ $# -ne 1 ]]; then echo "用法: sslmacbits <摘要算法名>" >&2 return 1 fi if ! command -v openssl &> /dev/null; then echo "未找到openssl,尝试自动安装..." >&2 sudo apt-get install -y openssl || return 3 fi if ! openssl list -digest-commands | grep -q "^${dgstname}$"; then echo "指定的摘要算法${dgstname}未在当前OpenSSL中支持" >&2 return 2 fi local chkopenssl="openssl ${dgstname} -hex" case $dgstname in shake128) chkopenssl="${chkopenssl} -xoflen 32" ;; shake256) chkopenssl="${chkopenssl} -xoflen 64" ;; esac # 用awk直接提取十六进制结果,避免复杂的字符串切割 local digesthex=$($chkopenssl <<<"Hello World" | awk -F'= ' '{print $2}') # 若需实际比特数,改为echo $(( ${#digesthex} * CHEXBITS )) echo $(( ${#digesthex} / CHEXBITS )) } export -f sslmacbits fi
优化点说明
- 性能提升:方案1通过映射表直接返回固定长度,无需生成实际摘要,执行速度更快;
- 代码简化:方案2用
awk替代原脚本的字符串切割逻辑,代码更简洁易读; - 鲁棒性优化:统一使用
command -v检查命令存在性,比which更可靠;用grep -q "^${dgstname}$"精确匹配摘要命令,避免部分匹配误判;用返回错误码替代exit,避免source引入后退出整个shell; - 逻辑修正提示:原脚本中比特数计算逻辑存在错误,正确的比特数应为十六进制字符数乘以4(每个十六进制字符对应4比特)。若需保持原输出(十六进制字符数/4),可保留原计算式;若需获取实际比特数,调整计算式即可。
内容的提问来源于stack exchange,提问作者sailnfool
相关产品推荐
相关产品推荐

