簡體   English   中英

使用 3DES 和 PHP 的 openssl_encrypt() 加密

[英]Encrypt using 3DES and PHP's openssl_encrypt()

我正在嘗試使用openssl_encrypt()在 PHP (v7.4.6) 中實施 3DES,但在生成正確的密文 output 時遇到問題。(我知道 3DES 是不安全的,但我必須使用它,因為我正在連接的遺留系統需要它。)

示例鍵:

fa21b161b659afec7633e08ea5ef54aaddd8728f5d3f7b97

樣本明文輸入:

9/3/2013 9:26:21 PM|100|john.smith@clubsoftpayments.com|John|Smith|1234.56

和預期的密文 output:

18E4719B4DC9C4E0581964C16B0077609B58717B465106A235AEC353467EC2A370AF97F3CFBB68B6E4005AF1178FE926418E49E55ECEFE794E28E8FC2DED4AFC077883B6D2517BD542F116408588B0B6

tripledes.online-domain-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()的 arguments 有什么問題?

  • 算法:

由於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-ecb”。

  • options

我已經嘗試了OPENSSL_RAW_DATAOPENSSL_ZERO_PADDINGOPENSSL_NO_PADDING的每個按位組合,但都無濟於事。

  • 零填充數據:

我還嘗試通過附加str_repeat("\x00", 2)向明文添加兩個 null 字節,使長度成為 8 字節塊大小的倍數。 (參考: https://www.php.net/manual/en/function.openssl-encrypt.php#121545 )這沒有幫助。

  • iv (初始化向量):

我不確定我是否需要初始化向量,因為我不需要向http://tripledes.online-domain-tools.com提供一個,並且在加密樣本時它沒有返回給我。 也許我錯了?

  • tagaadtag_length

據我所知,這些都不適用於 3DES,所以我不設置它們。

如何讓openssl_encrypt()使用樣本密鑰對樣本明文進行編碼,以生成所需的密文?

我知道Cannot find the right 3DES cipher in PHPphpcrypt project on GitHub。雖然 GitHub 庫有效,但我試圖弄清楚如何在可能的情況下僅使用openssl_encrypt()執行此操作。

使用以下 PHP 代碼生成所需的密文(包括結尾):

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

解釋:

  • 由於應用了 24 字節的密鑰,因此在3TDEA或三倍長度密鑰變體中使用了三重 DES (又名 3DES 或 TDES)。 OpenSSL 將此變體稱為des-ede3 (或des-ede3-ecb )。 使用的模式是 ECB。 但是,您應用的des-ecb指定DES (在 ECB 模式下)。 盡管 Triple DES 是基於 DES,但它們最終是不同的算法。
  • openssl_encrypt()中的第 4 個參數默認值為0 ,表示加密時密文編碼為 Base64。 在解密過程中,需要 Base64 解碼密文。 由於您示例中的密文在加密過程中不應編碼為 Base64,因此必須設置標志OPENSSL_RAW_DATA
  • OpenSSL 默認使用PKCS#7 填充 這提供了密文的預期結尾。 相比之下,引用的 web 站點應用了零填充,這導致了密文的不同結尾。

安全:
您已經指出 Triple DES 已被棄用。 今天的標准是 AES。 但是ECB 也是不安全的,因為這種模式不使用 IV。 更安全的是帶有 IV 的模式(如CBC ),甚至更好的身份驗證加密(例如GCM )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM