You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本中OpenSSL加解密报错:wrong final block length问题求助

问题:Bash脚本加密环境变量后解密失败(wrong final block length)

我写了两个Bash脚本用来加密/解密环境变量:

  • setit.sh:接收两个参数,将第二个字符串用OpenSSL v3.4.2加密后设置为第一个参数命名的环境变量
  • getit.sh:接收环境变量名参数,解密并输出其值

setit.sh 代码及用法

#!/bin/bash

if [ $# -ne 2 ]; then
    echo "Usage: $0 <variable_name> <string_to_encrypt>"
    exit 1
fi

VAR_NAME=$1
STRING_TO_ENCRYPT=$2

# Generate a random salt and passphrase
SALT=$(openssl rand -hex 8)
PASSPHRASE=$(openssl rand -hex 12)

# Encrypt the string
ENCRYPTED=$(echo -n "$STRING_TO_ENCRYPT" | openssl enc -aes-256-cbc -a -salt -pbkdf2 -pass pass:"$PASSPHRASE" -S "$SALT")

# Combine salt, passphrase, and encrypted string
RESULT="${SALT}:${PASSPHRASE}:${ENCRYPTED}"

# Set the environment variable
export "$VAR_NAME=$RESULT"

echo "Environment variable $VAR_NAME has been set with the encrypted value."

示例用法:source ./setit.sh MY_VAR secret_value

getit.sh 代码及用法

#!/bin/bash

if [ $# -ne 1 ]; then
    echo "Usage: $0 <variable_name>"
    exit 1
fi

VAR_NAME=$1

# Check if the environment variable exists
if [ -z "${!VAR_NAME}" ]; then
    echo "Error: Environment variable $VAR_NAME does not exist."
    exit 1
fi

# Get the value of the environment variable
ENCRYPTED_VALUE="${!VAR_NAME}\n"
echo "$VAR_NAME = $ENCRYPTED_VALUE"

# Extract salt, passphrase, and encrypted string
IFS=':' read -r SALT PASSPHRASE ENCRYPTED <<< "$ENCRYPTED_VALUE"

# Decrypt the string
DECRYPTED=$(echo -n "$ENCRYPTED" | openssl enc -aes-256-cbc -d -a -pbkdf2 -pass pass:"$PASSPHRASE" -S "$SALT")

# Check if decryption was successful
if [ $? -eq 0 ]; then
    echo "Decrypted value of $VAR_NAME:"
    echo "$DECRYPTED"
else
    echo "Error: Decryption failed. The encrypted value may be corrupted or tampered with."
    exit 1
fi

示例用法:./getit.sh MY_VAR

错误现象

setit.sh运行正常,但执行getit.sh时出现解密错误:

bad decrypt 0031185FF87F0000:error:1C80006B:Provider routines:ossl_cipher_generic_block_final:wrong final block length:providers/implementations/ciphers/ciphercommon.c:444: Error: Decryption failed. The encrypted value may be corrupted or tampered with.

怀疑和填充问题有关,但不确定具体原因,求解决。


原因分析

问题出在getit.sh的这一行:

ENCRYPTED_VALUE="${!VAR_NAME}\n"

你给环境变量的值额外添加了\n(换行符转义序列),但echo默认不会解析转义序列,所以实际变量值里会包含字面量\n字符,而不是换行符。这会导致后续用IFS=':'分割时,ENCRYPTED部分被混入了\n,传给OpenSSL解密时,数据长度不符合AES块大小要求,触发"wrong final block length"错误。

另外,echo "$VAR_NAME = $ENCRYPTED_VALUE"这一步也会让输出看起来有换行,但实际变量值被篡改了。

修复方案

修改getit.sh中获取环境变量值的代码,去掉多余的\n:

修复后的getit.sh

#!/bin/bash

if [ $# -ne 1 ]; then
    echo "Usage: $0 <variable_name>"
    exit 1
fi

VAR_NAME=$1

# Check if the environment variable exists
if [ -z "${!VAR_NAME}" ]; then
    echo "Error: Environment variable $VAR_NAME does not exist."
    exit 1
fi

# Get the value of the environment variable (去掉多余的\n)
ENCRYPTED_VALUE="${!VAR_NAME}"
echo "$VAR_NAME = $ENCRYPTED_VALUE"

# Extract salt, passphrase, and encrypted string
IFS=':' read -r SALT PASSPHRASE ENCRYPTED <<< "$ENCRYPTED_VALUE"

# Decrypt the string
DECRYPTED=$(echo -n "$ENCRYPTED" | openssl enc -aes-256-cbc -d -a -pbkdf2 -pass pass:"$PASSPHRASE" -S "$SALT")

# Check if decryption was successful
if [ $? -eq 0 ]; then
    echo "Decrypted value of $VAR_NAME:"
    echo "$DECRYPTED"
else
    echo "Error: Decryption failed. The encrypted value may be corrupted or tampered with."
    exit 1
fi

验证步骤

  1. 重新执行source ./setit.sh MY_VAR secret_value设置环境变量
  2. 运行修复后的./getit.sh MY_VAR,应该能正常输出解密后的secret_value

内容的提问来源于stack exchange,提问作者Daveh0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:52:43