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

使用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;

额外注意事项

  1. AES-256要求密钥长度必须为32字节,解密前可添加校验:if Length(fKey) <> 32 then raise Exception.Create('Invalid AES-256 key length');
  2. GCM模式通常需要附带认证标签(Tag),如果密文包含标签,需确保fDataBin包含完整的密文+标签,或通过Crypto.GCMTag属性设置标签(取决于加密时的实现)。

内容的提问来源于stack exchange,提问作者David Kovář

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:50:13