使用Delphi 10.1 Berlin进行3DES加密字符串

3

我需要使用3DES在Delphi中加密一个10字节的字符串。

它必须得到与此PHP代码相同的结果:

function encrypt_3DES($message, $key){
$bytes = array(0,0,0,0,0,0,0,0);
$iv = implode(array_map("chr", $bytes)); 

$ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv); 
return $ciphertext;

我一直在尝试使用DCPCrypt和LockBox 3进行编码。最终,我放弃了DCPCrypt,因为它已经很久没有更新了,而且我不确定它是否与Delphi 10.1 Berlin兼容,所以我将重点放在了LockBox 3上,但我无法正确加密。

加密密钥是一个24字节的密钥(我有它的base64表示)。我找不到如何使用LockBox的TSymetricKey类创建这样的密钥,并将其传递给Codec.Init方法。因此,我将其放在AnsiString中,并将其设置为密码属性(虽然文档中说有utf8Password,但我找不到它)。

然后有一个名为EncryptAnsiString的方法,但它仍然期望字符串(Delphi 10.1 Berlin上的utf16)而不是AnsiStrings(尽管文档说相反),因此我不惊讶结果与我要找的(在PHP代码片段中加密的相同值)不匹配。

以下是我的Delphi代码:

  function Encrypt(Data: AnsiString; LocalKey: AnsiString): AnsiString;
  var 
    BinaryLocalKey: TBytes;
    strLocalKey, strTripleDes: AnsiString;
  begin
    BinaryLocalKey := DecodeBase64(LocalKey);
    setString(strLocalKey, PAnsiChar(@BinaryLocalKey[0]), Length(BinaryLocalKey));

    Codec1.Rest;
    Codec1.Password := strLocalKey;
    Codec1.EncryptAnsiString(Data, strTripleDES);
    Codec1.Reset;

    Result := strTripleDes;
  end;

但是这段代码不仅不能得到与PHP代码相同的结果,而且每次调用相同的输入都会返回不同的结果。

注意:Codec1是一个与TCryptographicLibrary组件相关联的组件,其链模式属性设置为CBC*,加密器设置为3DES(键入选项1)。

有人知道如何正确地获得这个3DES加密吗?

谢谢。


2
你为什么要使用文本而不是字节? - David Heffernan
我非常有信心问题应该是设置密码/密钥,但我不知道如何将它们设置为二进制。一旦密钥设置完成,我应该能够在内存中解密,但这相当复杂(您需要启动和完成解密并通过流获取结果),看起来使用24字节的密钥加密10字节的字符串有些过度,因为我只需要这样做。 - Marc Guillot
3DES不应该用于新的工作。 - zaph
@MarcGuillot 你解决了这个问题吗?我也遇到了类似的问题,接受UnicodeString的EncryptAnsiString函数非常奇怪。在最新版本3.7中,如果定义了UNICODE,他们只是有条件地将其留了下来。真是个好修复。我敢打赌你最终使用了EncryptMemory()函数吧? - drakorg
不好意思,Eduardo。我们最终通过Javascript在客户端解决了这个问题。 - Marc Guillot
显示剩余4条评论
1个回答

1
每个消息都会生成一个随机的IV。 IV的低8字节是nonce,高字节为零。这些低8字节将被添加到输出中。
如果您想通过侧信道发送IV,则从名义上的密文中删除前8个字节。
如果您想控制IV,请使用3.7.0版本( https://github.com/SeanBDurkin/tplockbox)。您需要设置高级选项并实现OnGetIV方法。
在密码选择和链模式选择的属性编辑器中呈现的星号(*)表示这是推荐的选择。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接