Perl/PHP/ColdFusion中的TripleDES

Sei*_*idr 12 php encryption coldfusion perl tripledes

最近出现了一个问题,即使用TripleDES标准将请求字符串加密的支付处理器连接到API以用作令牌.我们的应用程序使用ColdFusion运行,它有一个加密标签 - 支持TripleDES - 但是我们得到的结果并不是支付处理器所期望的.

首先,这是支付处理器所期望的结果令牌.

AYOF+kRtg239Mnyc8QIarw==
Run Code Online (Sandbox Code Playgroud)

下面是我们正在使用的ColdFusion的片段,以及结果字符串.

<!--- Coldfusion Crypt (here be monsters) --->
<cfset theKey="123412341234123412341234">
<cfset theString = "username=test123">
<cfset strEncodedEnc = Encrypt(theString, theKey, "DESEDE", "Base64")>
<!---
 resulting string(strEncodedEnc): tc/Jb7E9w+HpU2Yvn5dA7ILGmyNTQM0h
--->
Run Code Online (Sandbox Code Playgroud)

如您所见,这并没有返回我们希望的字符串.寻求解决方案,我们为此过程抛弃了ColdFusion,并尝试在PHP中重现令牌.

现在我知道各种语言以不同的方式实现加密 - 例如在过去管理C#应用程序和PHP后端之间的加密,我不得不玩填充以使两者交谈,但是我的经验是,PHP在加密标准方面通常表现得很好.

无论如何,我们尝试的PHP源代码和结果字符串.

/* PHP Circus (here be Elephants) */
$theKey="123412341234123412341234";
$theString="username=test123";
$strEncodedEnc=base64_encode(mcrypt_ecb (MCRYPT_3DES, $theKey, $theString, MCRYPT_ENCRYPT));
/*
 resulting string(strEncodedEnc): sfiSu4mVggia8Ysw98x0uw==
*/
Run Code Online (Sandbox Code Playgroud)

正如您可以清楚地看到的那样,我们有另一个字符串,它与支付处理器预期的字符串和ColdFusion生成的字符串不同.提示头对墙集成技术.

经过与支付处理器的多次往复通信(很多代表说"我们无法解决编码问题,你必须做错了,阅读手册")我们最终被升级为超过一对脑细胞在一起摩擦,能够退后一步,实际观察和诊断问题.

他同意,我们的CF和PHP尝试没有产生正确的字符串.经过快速搜索,他还同意这不是我们的来源,而是两种语言如何实现他们对TripleDES标准的看法.

今天早上进入办公室时,我们遇到了一封包含Perl源代码片段的电子邮件.这是他们在最终直接使用的代码,用于生成预期的令牌.

#!/usr/bin/perl
# Perl Crypt Calamity (here be...something)
use strict;
use CGI;
use MIME::Base64;
use Crypt::TripleDES;

my $cgi = CGI->new();
my $param = $cgi->Vars();

$param->{key} = "123412341234123412341234";
$param->{string} = "username=test123";
my $des = Crypt::TripleDES->new();

my $enc = $des->encrypt3($param->{string}, $param->{key});
$enc = encode_base64($enc);
$enc =~ s/\n//gs;

# resulting string (enc): AYOF+kRtg239Mnyc8QIarw==
Run Code Online (Sandbox Code Playgroud)

因此,我们有它.三种语言,三种在文档中引用的实现,如TripleDES标准加密,以及三种完全不同的结果字符串.

我的问题是,根据你对这三种语言的体验以及它们对TripleDES算法的实现,你能否得到它们中的任何两个来给出相同的响应,如果有的话,你需要对代码进行哪些调整结果呢?

我知道这是一个非常引人注目的问题,但我想为我们必须执行的每个测试阶段提供清晰准确的设置.

我稍后还会就此问题进行更多的调查工作,并将我提出的任何调查结果发布到这个问题上,以便其他人可以避免这种头痛.

ZZ *_*der 8

永远不应该使用Perl的TripleDES.它做了很多奇怪的事情,你会玩得很开心.

你的第一个问题是Perl中的键是十六进制的,你需要将它们转换为二进制.在PHP中试试这个,

$theKey="123412341234123412341234";
$key = pack('H*', str_pad($theKey, 16*3, '0'));
$strEncodedEnc=base64_encode(mcrypt_ecb (MCRYPT_3DES, $key, $theString, MCRYPT_ENCRYPT));
echo $strEncodedEnc, "\n";
Run Code Online (Sandbox Code Playgroud)

结果是,

AYOF+kRtg239Mnyc8QIarw==
Run Code Online (Sandbox Code Playgroud)

然后你必须以一种奇怪的方式填充它.我忘记了细节.你很幸运这个样本(它是16个字符).


Edw*_*ith 5

Coldfusion答案:

第一个问题是您的密钥长度对于Triple DES不正确.ZZ Coder正确地推断出它需要用0填充到正确的长度.

下一步是密钥需要转换为十六进制.要在CF中执行此操作,我们有:

<cfset theKey="123412341234123412341234000000000000000000000000">
<cfset encodedKey = ToBase64(BinaryDecode(theKey, "HEX"))>
Run Code Online (Sandbox Code Playgroud)

最后一步是结果也没有填充,所以我们需要在CF中的加密算法中指定:

<cfset strEncodedEnc = Encrypt(theString, encodedKey, "DESEDE/ECB/NoPadding", "Base64")>
Run Code Online (Sandbox Code Playgroud)

由此产生的完整代码:

<cfset theKey="123412341234123412341234000000000000000000000000">
<cfset encodedKey = ToBase64(BinaryDecode(theKey, "HEX"))>
<cfset theString = "username=test123">
<cfset strEncodedEnc = Encrypt(theString, encodedKey, "DESEDE/ECB/NoPadding", "Base64")>
<cfdump var="#strEncodedEnc#"><br>
Run Code Online (Sandbox Code Playgroud)

结果是:

AYOF+kRtg239Mnyc8QIarw==
Run Code Online (Sandbox Code Playgroud)