delphi JDAESExtend中AES-base64解密报错的解决办法

在我的资源【Delphi XE2+标准AES加解密算法(AES/EBC,CBC/PKCS5Padding-base64)】中,有朋友反应说aes加密以base64模式输出时,解密的时候报错。因为我的项目中使用的是十六进制,所以当时没有留意到这个情况。现将修复后的代码贴出,供有需要的朋友使用。

问题主要出现在JDAESExtend.pas解密函数(DecryptString)的base64解密段(以下代码在XE2,加密模式ECB+PKCS5Padding-base64模式下验证成功。)

在研究它加密的逻辑时可以看到,base64加密使用了EncdDecd.EncodeStream(DS,outDS):

      outDS := TStringStream.Create('',TEncoding.UTF8);
      try
        DS.Position := 0;
        EncdDecd.EncodeStream(DS,outDS);
        Result := outDS.DataString;
      finally
        freeandnil(outDS);
      end;

但base64解密时直接用了EncdDecd.DecodeString(Value)

  if CipherType= ctHex then
    str := HexToStr(Value)
  else
    str := EncdDecd.DecodeString(Value);

故我们可以尝试把解密的方式调整下,用base64的逆向解密。调整后的解密函数为:

function DecryptString(Value: AnsiString; Key: AnsiString; KeyBit: TKeyBit = kb128; algoMode: TalgoMode = amECB; padding: TPaddingType = PKCS5Padding; sInitVector: AnsiString = '0000000000000000';
  CipherType: TCipherType = ctHex): AnsiString;
var
  SS,DS: TMemoryStream;
  DSBase64: TStringStream;
  str: AnsiString;
  byteContent: TBytes;
  BytesValue: TBytes;
begin
  Result := '';
  DS := TMemoryStream.Create;
  SS := TMemoryStream.Create;
  if CipherType= ctHex then
  begin
    str := HexToStr(Value);
    SetLength(byteContent, Length(str));
    Move(str[1], byteContent[0], Length(str));
    SS.WriteBuffer(byteContent[0], Length(byteContent));
  end
  else
  begin
    try
      DSBase64 := TStringStream.Create(Value,TEncoding.UTF8);
      DSBase64.Position := 0;
      EncdDecd.DecodeStream(DSBase64,SS);
      SS.Position := 0;
    finally
      freeandnil(DSBase64);
    end;
  end;

  try
    case KeyBit of
      kb128:
        begin
          ZeroPadding(kb128);
          Move(PAnsiChar(Key)^, AESKey128, Length(Key));
          case algoMode of
            amECB:
              begin
                DecryptAESStreamECB(SS, 0, AESKey128, DS);
              end;
            amCBC:
              begin
                // 不足16位用0补齐
                FillChar(InitVector, SizeOf(InitVector), 0);
                Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
                DecryptAESStreamCBC(SS, 0, AESKey128, InitVector, DS);
              end;
          end;
        end;
      kb192:
        begin
          ZeroPadding(kb192);
          Move(PAnsiChar(Key)^, AESKey192, Length(Key));
          case algoMode of
            amECB:
              begin
                DecryptAESStreamECB(SS, 0, AESKey192, DS);
              end;
            amCBC:
              begin
                FillChar(InitVector, SizeOf(InitVector), 0);
                Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
                DecryptAESStreamCBC(SS, 0, AESKey192, InitVector, DS);
              end;
          end;
        end;
      kb256:
        begin
          ZeroPadding(kb256);
          Move(PAnsiChar(Key)^, AESKey256, Length(Key));
          case algoMode of
            amECB:
              begin
                DecryptAESStreamECB(SS, 0, AESKey256, DS);
              end;
            amCBC:
              begin
                FillChar(InitVector, SizeOf(InitVector), 0);
                Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
                DecryptAESStreamCBC(SS, 0, AESKey256, InitVector, DS);
              end;
          end;
        end;
    end;
    DS.Position := 0;
    SetLength(BytesValue, DS.size);
    DS.ReadBuffer(BytesValue[0], DS.size);
    Result := PKCS5_DePadding(BytesValue);
  finally
    SS.Free;
    DS.Free;
  end;
end;

你可能感兴趣的:(Delphi,算法,JDAESExtend,AES)