使用SecureBlackBox解密AES-256数据时遇「无效密钥材料」错误求助
解决SecureBlackBox AES-GCM解密时的"Invalid key material"错误
问题根源
代码中对密钥(Key)和IV的二进制转换逻辑错误,导致传递给TElSymmetricKeyMaterial的密钥长度不符合AES-256的要求:
TBytes是单字节数组,但转换为ByteArray时错误使用了Length(fKey) * SizeOf(Char),Delphi中Char为双字节类型,这会让密钥实际长度翻倍(AES-256需要32字节密钥,错误处理后变为64字节),触发"Invalid key material"错误。- 同样的错误也出现在IV的转换上,GCM模式的IV通常为12字节,错误处理后变为24字节,不符合要求。
修正方案
移除错误的SizeOf(Char)计算,将TBytes直接转换为ByteArray(两者本质都是字节数组,无需额外扩容):
修正后的完整函数
function DecryptAES256GCM(aData, aSal, aKey: String): string; function Base64UrlDecode(Input: string): TBytes; begin Result := TNetEncoding.Base64.DecodeStringToBytes( StringReplace( StringReplace(Input, '-', '+', [rfReplaceAll]), '_', '/', [rfReplaceAll] ) ); end; var Crypto : TElSymmetricCrypto; KeyMaterial : TElSymmetricKeyMaterial; Factory : TElSymmetricCryptoFactory; fIV, fKey, fDataBin, fDecryptedData : TBytes; OutSize : integer; KeyBinary, IVBinary : ByteArray; begin result := ''; // 转换输入数据 fDataBin := Base64UrlDecode(aData); fIV := Base64UrlDecode(aSal); fKey := Base64UrlDecode(aKey); // 修正:直接使用TBytes的长度作为ByteArray的长度,无需乘以SizeOf(Char) SetLength(IVBinary, Length(fIV)); if Length(fIV) > 0 then Move(fIV[0], IVBinary[0], Length(fIV)); SetLength(KeyBinary, Length(fKey)); if Length(fKey) > 0 then Move(fKey[0], KeyBinary[0], Length(fKey)); // 初始化SecureBlackBox对象 Factory := TElSymmetricCryptoFactory.Create; Crypto := Factory.CreateInstance(SB_ALGORITHM_CNT_AES256, cmGCM); try KeyMaterial := TElSymmetricKeyMaterial.Create; KeyMaterial.Key := KeyBinary; KeyMaterial.IV := IVBinary; Crypto.Padding := cpNone; Crypto.KeyMaterial := KeyMaterial; try // 获取解密后长度 OutSize := 0; Crypto.Decrypt(@fDataBin[0], Length(fDataBin), nil, OutSize); if OutSize < 0 then raise Exception.Create('Failed to decrypt data'); // 执行解密 SetLength(fDecryptedData, OutSize); Crypto.Decrypt(@fDataBin[0], Length(fDataBin), @fDecryptedData[0], OutSize); if OutSize < 0 then raise Exception.Create('Failed to decrypt data'); SetLength(fDecryptedData, OutSize); // 转换为UTF-8字符串输出 result := TEncoding.UTF8.GetString(fDecryptedData); except on E: Exception do ShowMessage(E.Message); end; finally Factory.Free; Crypto.Free; KeyMaterial.Free; end; end;
额外注意事项
- AES-256要求密钥长度必须为32字节,解密前可添加校验:
if Length(fKey) <> 32 then raise Exception.Create('Invalid AES-256 key length'); - GCM模式通常需要附带认证标签(Tag),如果密文包含标签,需确保
fDataBin包含完整的密文+标签,或通过Crypto.GCMTag属性设置标签(取决于加密时的实现)。
内容的提问来源于stack exchange,提问作者David Kovář
相关产品推荐
相关产品推荐

