首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Delphi DEC库(Rijndael)加密

Delphi DEC库(Rijndael)加密
EN

Stack Overflow用户
提问于 2012-02-10 10:43:53
回答 3查看 5.9K关注 0票数 8

我试图使用DEC3.0库 (Delphi加密竞争第一部分)加密Delphi7中的数据,并通过POST将其发送到PHP脚本,在那里使用mcrypt (RIJNDAEL_256,ECB模式)对其进行解密。

Delphi部分:

代码语言:javascript
复制
uses Windows, DECUtil, Cipher, Cipher1;

function EncryptMsgData(MsgData, Key: string): string;
var RCipher: TCipher_Rijndael;
begin
  RCipher:= TCipher_Rijndael.Create(KeyStr, nil);
  RCipher.Mode:= cmECB;
  Result:= RCipher.CodeString(MsgData, paEncode, fmtMIME64);
  RCipher.Free;
end;

PHP部件:

代码语言:javascript
复制
function decryptMsgContent($msgContent, $sKey) {
    return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $sKey, base64_decode($msgContent), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND));
}

问题是来自PHP的解密不起作用,输出是胡说八道,与实际数据不同。

当然,Delphi Key$Key是相同的24个字符字符串。

现在我知道DEC3.0已经过时了,我不是加密方面的专家,也不知道它是否是Rijndael 256。也许有人可以告诉我,这个实现与PHP的mcrypt / RIJNDAEL_256有什么不同。可能键大小不同,或者块大小不同,但无法从代码中分辨出这一点。这里有一段摘录自第一章:

代码语言:javascript
复制
const
{ don’t change this }
  Rijndael_Blocks =  4;
  Rijndael_Rounds = 14;

class procedure TCipher_Rijndael.GetContext(var ABufSize, AKeySize, AUserSize: Integer);
begin
  ABufSize := Rijndael_Blocks * 4;
  AKeySize := 32;
  AUserSize := (Rijndael_Rounds + 1) * Rijndael_Blocks * SizeOf(Integer) * 2;
end;

附带问题:

我知道欧洲央行模式是不推荐的,我将使用CBC,一旦我得到欧洲央行的工作。问题是,我是否也必须将Delphi中生成的IV传输到PHP脚本?或者知道关键就足够了,就像欧洲央行一样?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-02-10 11:36:30

您正在调用TCipher.Create( constructor : String;AProtection: TProtection);构造函数,它将在将密码传递给Init方法之前计算密码的散列,后者执行已实现算法的标准密钥调度。若要重写此键派生,请使用:

代码语言:javascript
复制
function EncryptMsgData(MsgData, Key: string): string;
var RCipher: TCipher_Rijndael;
begin
  RCipher:= TCipher_Rijndael.Create('', nil);
  RCipher.Init(Pointer(Key)^,Length(Key),nil);
  RCipher.Mode:= cmECB;
  Result:= RCipher.CodeString(MsgData, paEncode, fmtMIME64);
  RCipher.Free;

结束;

票数 6
EN

Stack Overflow用户

发布于 2012-02-10 14:35:16

好的,总之,我的代码有三个问题:

  1. 由于我对mcrypt和密码的理解很差,所以MCRYPT_RIJNDAEL_256引用128位,而不引用密钥大小。我正确的选择应该是MCRYPT_RIJNDAEL_128,这是AES标准,也是DEC3.0所支持的。
  2. DEC有自己的默认密钥派生,所以我需要绕过它,这样就不必在PHP中实现它了。实际上,我使用的是我自己的密钥派生算法,该算法易于在PHP中复制(sha1( key )的前32个字符)。
  3. DEC并不像mcrypt所期望的那样,将明文转换为密码块大小的倍数,所以我不得不手动执行。

提供以下工作代码:

德尔菲:

代码语言:javascript
复制
uses Windows, DECUtil, Cipher, Cipher1, CryptoAPI;

function EncryptMsgData(MsgData, Key: string): string;
var RCipher: TCipher_Rijndael;
    KeyStr: string;
begin
  Result:= '';
  try
    // key derivation; just making sure to feed the cipher a 24 chars key
    HashStr(HASH_SHA1, Key, KeyStr);
    KeyStr:= Copy(KeyStr, 1, 24);
    RCipher:= TCipher_Rijndael.Create('', nil);
    RCipher.Init(Pointer(KeyStr)^, Length(KeyStr), nil);
    RCipher.Mode:= cmECB;
    Result:= RCipher.CodeString(MsgData + StringOfChar(#0,16-(Length(MsgData) mod 16)), paEncode, fmtMIME64);
    RCipher.Free;
  except
  end;
end;

PHP:

代码语言:javascript
复制
function decryptMsgContent($msgContent, $sKey) {
    $sKey = substr(sha1(sKey), 0, 24);
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $sKey, base64_decode($msgContent), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_RAND)));
}
票数 2
EN

Stack Overflow用户

发布于 2014-10-19 00:43:28

我找到的256位键是32个字符,或32个字节。不是24岁。这可能就是问题所在。

编辑

我把每个人的想法(如字符串等)合并成一个固定的想法。

而且,您使用的是代码字符串( --应该是Encodestring(

我粘贴工作加密和解密源如下:

代码语言:javascript
复制
function EncryptMsgData(MsgData, Key: AnsiString): AnsiString;
var RCipher: TCipher_Rijndael;
begin
  RCipher:= TCipher_Rijndael.Create('', nil);
  RCipher.Init(Pointer(Key)^,Length(Key),nil);
  RCipher.Mode:= cmCBC;
  Result:= RCipher.EncodeString(MsgData);
  RCipher.Free;
end;

function DecryptMsgData(MsgData, Key: AnsiString): AnsiString;
var RCipher: TCipher_Rijndael;
begin
  RCipher:= TCipher_Rijndael.Create('',nil);
  RCipher.Init(Pointer(Key)^,Length(Key),nil);
  RCipher.Mode:= cmCBC;
  Result:= RCipher.DecodeString(MsgData);
  RCipher.Free;
end;

使用32字符的密钥,你就可以得到正确的加密和解密。

为了将加密的数据作为字符串存储和使用,您可能需要使用Base64Encode(

但是,在解密之前,不要忘记Base64Decode。

这是同样的技术所需的龙虾。有时字符实际上就像一个后台空间,并执行功能,而不是显示在屏幕上。Base64Encode基本上将字符转换为您可以在文本中显示的内容。

在以同一种或另一种语言在互联网或其他应用程序之间传输编码数据之前,必须先对数据进行base64encode和解码,以避免数据松散。在PHP中也不要忘记它!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9226487

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档