Perl/PHP/ColdFusion 中的 TripleDES

2021-12-20 00:00:00 encryption perl php tripledes coldfusion

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

Recently a problem arose regarding hooking up an API with a payment processor who were requesting a string to be encrypted to be used as a token, using the TripleDES standard. Our Applications run using ColdFusion, which has an Encrypt tag - that supports TripleDES - however the result we were getting back was not what the payment processor expected.

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

First of all, here is the resulting token the payment processor were expecting.

AYOF+kRtg239Mnyc8QIarw==

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

And below is the snippet of ColdFusion we were using, and the resulting string.

<!--- 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
--->

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

As you can see, this was not returning the string we were hoping for. Seeking a solution, we ditched ColdFusion for this process and attempted to reproduce the token in PHP.

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

Now I'm aware that various languages implement encryption in different ways - for example in the past managing encryption between a C# application and PHP back-end, I've had to play about with padding in order to get the two to talk, but my experience has been that PHP generally behaves when it comes to encryption standards.

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

Anyway, on to the PHP source we tried, and the resulting string.

/* 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==
*/

您可以清楚地看到,我们得到了另一个字符串,它与支付处理器预期的字符串和 ColdFusion 生成的字符串都不同.提示对抗集成技术.

As you can plainly see, we've got another string that differs from both the string expected by the payment processor AND the one produced by ColdFusion. Cue head-against-wall integration techniques.

在与支付处理商进行多次来回沟通后(很多代表说我们无法帮助解决编码问题,你一定是做错了,阅读手册")我们终于被升级到某人有多个脑细胞相互摩擦,谁能够退后一步,实际查看和诊断问题.

After many to-and-fro communications with the payment processor (lots and lots of reps stating 'we can't help with coding issues, you must be doing it incorrectly, read the manual') we were finally escalated to someone with more than a couple of brain-cells to rub together, who was able to step back and actually look at and diagnose the issue.

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

He agreed, our CF and PHP attempts were not resulting in the correct string. After a quick search, he also agreed that it was not neccesarily our source, but rather how the two languages implemented their vision of the TripleDES standard.

今天早上走进办公室,我们收到一封电子邮件,其中包含一段 Perl 源代码.这是他们直接用于生成预期令牌的代码.

Coming into the office this morning, we were met by an email with a snippet of source code, in Perl. This is was the code they were directly using on their end to produce the expected token.

#!/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/
//gs;

# resulting string (enc): AYOF+kRtg239Mnyc8QIarw==

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

So, there we have it. Three languages, three implementations of what they quote in the documentation as TripleDES Standard Encryption, and three totally different resulting strings.

我的问题是,根据您对这三种语言及其 TripleDES 算法实现的经验,您是否能够让其中任何两种语言给出相同的响应,如果是,您必须对代码进行哪些调整?为了得出结果?

My question is, from your experience of these three languages and their implementations of the TripleDES algorithm, have you been able to get any two of them to give the same response, and if so what tweaks to the code did you have to make in order to come to the result?

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

I understand this is a very drawn out question, but I wanted to give clear and precise setting for each stage of testing that we had to perform.

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

I'll also be performing some more investigatory work on this subject later, and will post any findings that I come up with to this question, so that others may avoid this headache.

推荐答案

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

The Perl's TripleDES should never be used. It does so many weird things and you are going to have fun.

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

Your first problem is that the keys in Perl are hex and you need to convert them into binary. Try this in 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, "
";

结果是,

AYOF+kRtg239Mnyc8QIarw==

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

Then you have to pad it in a weird way. I forgot the details. You are lucky with this sample (it's 16 chars).

相关文章