我试图使用openssl_encrypt()
在PHP (v7.4.6)中实现3 3DES,但在生成正确的密文输出时遇到了问题。(我知道3 3DES是不安全的,但我必须使用它,因为我连接到的遗留系统需要它。)
示例密钥:
fa21b161b659afec7633e08ea5ef54aaddd8728f5d3f7b97
纯文本输入示例:
9/3/2013 9:26:21 PM|100|john.smith@clubsoftpayments.com|John|Smith|1234.56
以及预期密文输出:
18E4719B4DC9C4E0581964C16B0077609B58717B465106A235AEC353467EC2A370AF97F3CFBB68B6E4005AF1178FE926418E49E55ECEFE794E28E8FC2DED4AFC077883B6D2517BD542F116408588B0B6
在线域-tools.com网站使用"ECB (电子码本)“模式正确地编码示例明文,从而产生以下密文(显示为十六进制):
18E4719B4DC9C4E0581964C16B0077609B58717B465106A235AEC353467EC2A370AF97F3CFBB68B6E4005AF1178FE926418E49E55ECEFE794E28E8FC2DED4AFC077883B6D2517BD5D00067BFA921ABC0
尽管前8个字节(42F116408588B0B6
)与预期的密文不同,但同一网站可以成功地将两个密文解码为原始明文:
编码:http://tripledes.online-domain-tools.com/link/2b65dfdgf4MoJSND32/
解码:http://tripledes.online-domain-tools.com/link/2b68348glGkJ0h3ejQ/
试图使用PHP的openssl_encrypt()
加密明文,我按如下方式调用它:
$ciphertext_raw = openssl_encrypt(
'9/3/2013 9:26:21 PM|100|john.smith@clubsoftpayments.com|John|Smith|1234.56', // plaintext data
'des-ecb', // algorithm
hex2bin('fa21b161b659afec7633e08ea5ef54aaddd8728f5d3f7b97'), // Key must be provided as plaintext, hence the call to hex2bin()
);
$ciphertext_hex = bin2hex($ciphertext_raw);
由此产生的(十六进制编码)密文是:
6e7267444579666f6b7338795334614347626949455a544347316d3768732f7730784b6552375945344e466f67463677737a6b786e463863506b79466c3941593956734579705939356c754d6b794a76347345424b302f47735a623972575543395a4f4f7857456e34744d3d
我传递给openssl_encrypt()
**?** 的参数有什么问题?
由于http://tripledes.online-domain-tools.com使用"ECB (电子码本)“模式工作,我想我应该使用一种同时表示"des”和"ecb“的密码方法。openssl_get_cipher_methods()
列出了在其名称中包含"des“的下列算法:
des-cbc
des-cfb
des-cfb1
des-cfb8
des-ecb
des-ede
des-ede-cbc
des-ede-cfb
des-ede-ofb
des-ede3
des-ede3-cbc
des-ede3-cfb
des-ede3-cfb1
des-ede3-cfb8
des-ede3-ofb
des-ofb
desx-cbc
id-smime-alg-CMS3DESwrap
包含"des“和"ecb”的唯一算法是“des”。
options
我尝试过OPENSSL_RAW_DATA
、OPENSSL_ZERO_PADDING
和OPENSSL_NO_PADDING
的每一个按位组合,但都没有效果。
我还尝试将两个空字节添加到明文中,方法是追加str_repeat("\x00", 2)
,使长度成为8字节块大小的倍数。(参考:https://www.php.net/manual/en/function.openssl-encrypt.php#121545)这没有帮助。
iv
(初始化向量):我不确定是否需要初始化向量,因为我不需要向http://tripledes.online-domain-tools.com提供初始化向量,而且在加密示例时它也没有返回给我。也许我错了?
tag
、aad
和tag_length
据我所知,这些都不适用于3 3DES,所以我不设置它们。
如何让openssl_encrypt()
使用示例密钥对示例明文进行编码,以生成所需的密文?
我知道无法在PHP中找到正确的3 3DES密码和[医]隐窝在GitHub上的项目。虽然GitHub库可以工作,但如果可能的话,我想知道如何使用openssl_encrypt()
来完成这个任务。
发布于 2022-04-23 06:14:05
使用以下PHP代码生成所需的密文(包括end):
<?php
// Encryption
$ciphertext_raw = openssl_encrypt(
'9/3/2013 9:26:21 PM|100|john.smith@clubsoftpayments.com|John|Smith|1234.56',
'des-ede3', // des-ede3-ecb
hex2bin('fa21b161b659afec7633e08ea5ef54aaddd8728f5d3f7b97'),
OPENSSL_RAW_DATA
);
$ciphertext_hex = bin2hex($ciphertext_raw);
print($ciphertext_hex . PHP_EOL); // 18e4719b4dc9c4e0581964c16b0077609b58717b465106a235aec353467ec2a370af97f3cfbb68b6e4005af1178fe926418e49e55ecefe794e28e8fc2ded4afc077883b6d2517bd542f116408588b0b6
// Decryption
$decrypted = openssl_decrypt(
$ciphertext_raw,
'des-ede3', // des-ede3-ecb
hex2bin('fa21b161b659afec7633e08ea5ef54aaddd8728f5d3f7b97'),
OPENSSL_RAW_DATA
);
print($decrypted . PHP_EOL); // 9/3/2013 9:26:21 PM|100|john.smith@clubsoftpayments.com|John|Smith|1234.56
?>
解释:
des-ede3
(或des-ede3-ecb
)。采用的模式是欧洲央行。然而,您应用的des-ecb
指定了DES (在欧洲央行模式下)。虽然三重DES是基于DES的,但它们最终是不同的算法。openssl_encrypt()
中的第四个参数具有默认值0
,这意味着加密期间加密文本是Base64编码的。在解密过程中,需要Base64解码的密文。由于示例中的密文不应在加密期间进行Base64编码,所以必须设置标志OPENSSL_RAW_DATA
。安保:
您已经指出,Triple DES是不受欢迎的。今天的标准是AES。但是欧洲央行也不安全,因为这种模式不使用IV。更安全的是带有IV的模式(比如CBC,更好的认证加密(例如GCM) )。
https://stackoverflow.com/questions/71976593
复制相似问题