• 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):

    1. outDS := TStringStream.Create('',TEncoding.UTF8);
    2. try
    3. DS.Position := 0;
    4. EncdDecd.EncodeStream(DS,outDS);
    5. Result := outDS.DataString;
    6. finally
    7. freeandnil(outDS);
    8. end;

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

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

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

    1. function DecryptString(Value: AnsiString; Key: AnsiString; KeyBit: TKeyBit = kb128; algoMode: TalgoMode = amECB; padding: TPaddingType = PKCS5Padding; sInitVector: AnsiString = '0000000000000000';
    2. CipherType: TCipherType = ctHex): AnsiString;
    3. var
    4. SS,DS: TMemoryStream;
    5. DSBase64: TStringStream;
    6. str: AnsiString;
    7. byteContent: TBytes;
    8. BytesValue: TBytes;
    9. begin
    10. Result := '';
    11. DS := TMemoryStream.Create;
    12. SS := TMemoryStream.Create;
    13. if CipherType= ctHex then
    14. begin
    15. str := HexToStr(Value);
    16. SetLength(byteContent, Length(str));
    17. Move(str[1], byteContent[0], Length(str));
    18. SS.WriteBuffer(byteContent[0], Length(byteContent));
    19. end
    20. else
    21. begin
    22. try
    23. DSBase64 := TStringStream.Create(Value,TEncoding.UTF8);
    24. DSBase64.Position := 0;
    25. EncdDecd.DecodeStream(DSBase64,SS);
    26. SS.Position := 0;
    27. finally
    28. freeandnil(DSBase64);
    29. end;
    30. end;
    31. try
    32. case KeyBit of
    33. kb128:
    34. begin
    35. ZeroPadding(kb128);
    36. Move(PAnsiChar(Key)^, AESKey128, Length(Key));
    37. case algoMode of
    38. amECB:
    39. begin
    40. DecryptAESStreamECB(SS, 0, AESKey128, DS);
    41. end;
    42. amCBC:
    43. begin
    44. // 不足16位用0补齐
    45. FillChar(InitVector, SizeOf(InitVector), 0);
    46. Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
    47. DecryptAESStreamCBC(SS, 0, AESKey128, InitVector, DS);
    48. end;
    49. end;
    50. end;
    51. kb192:
    52. begin
    53. ZeroPadding(kb192);
    54. Move(PAnsiChar(Key)^, AESKey192, Length(Key));
    55. case algoMode of
    56. amECB:
    57. begin
    58. DecryptAESStreamECB(SS, 0, AESKey192, DS);
    59. end;
    60. amCBC:
    61. begin
    62. FillChar(InitVector, SizeOf(InitVector), 0);
    63. Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
    64. DecryptAESStreamCBC(SS, 0, AESKey192, InitVector, DS);
    65. end;
    66. end;
    67. end;
    68. kb256:
    69. begin
    70. ZeroPadding(kb256);
    71. Move(PAnsiChar(Key)^, AESKey256, Length(Key));
    72. case algoMode of
    73. amECB:
    74. begin
    75. DecryptAESStreamECB(SS, 0, AESKey256, DS);
    76. end;
    77. amCBC:
    78. begin
    79. FillChar(InitVector, SizeOf(InitVector), 0);
    80. Move(PAnsiChar(sInitVector)^, InitVector, Length(sInitVector));
    81. DecryptAESStreamCBC(SS, 0, AESKey256, InitVector, DS);
    82. end;
    83. end;
    84. end;
    85. end;
    86. DS.Position := 0;
    87. SetLength(BytesValue, DS.size);
    88. DS.ReadBuffer(BytesValue[0], DS.size);
    89. Result := PKCS5_DePadding(BytesValue);
    90. finally
    91. SS.Free;
    92. DS.Free;
    93. end;
    94. end;

  • 相关阅读:
    pyqt5移动鼠标时显示鼠标坐标
    LeetCode 第155题:最小栈(Java解法)- 剑指 Offer 30. 包含min函数的栈
    java集合list map set
    MongoDB 中的索引分析
    bash for循环
    Nacos2.X源码阅读总结
    新人一看就懂:Dubbo3 + Nacos的RPC远程调用框架demo
    在Windows安装Flutter
    nginx反向代理动静分离和负载均衡
    46LVS+Keepalived群集
  • 原文地址:https://blog.csdn.net/yueyun889/article/details/127650287