我试图使用DEC3.0库 (Delphi加密竞争第一部分)加密Delphi7中的数据,并通过POST将其发送到PHP脚本,在那里使用mcrypt (RIJNDAEL_256,ECB模式)对其进行解密。
Delphi部分:
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部件:
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有什么不同。可能键大小不同,或者块大小不同,但无法从代码中分辨出这一点。这里有一段摘录自第一章:
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脚本?或者知道关键就足够了,就像欧洲央行一样?
发布于 2012-02-10 11:36:30
您正在调用TCipher.Create( constructor : String;AProtection: TProtection);构造函数,它将在将密码传递给Init方法之前计算密码的散列,后者执行已实现算法的标准密钥调度。若要重写此键派生,请使用:
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;结束;
发布于 2012-02-10 14:35:16
好的,总之,我的代码有三个问题:
提供以下工作代码:
德尔菲:
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:
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)));
}发布于 2014-10-19 00:43:28
我找到的256位键是32个字符,或32个字节。不是24岁。这可能就是问题所在。
编辑
我把每个人的想法(如字符串等)合并成一个固定的想法。
而且,您使用的是代码字符串( --应该是Encodestring(
我粘贴工作加密和解密源如下:
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中也不要忘记它!
https://stackoverflow.com/questions/9226487
复制相似问题