PHP Conference Japan 2024

mdecrypt_generic

(PHP 4 >= 4.0.2, PHP 5, PHP 7 < 7.2.0, PECL mcrypt >= 1.0.0)

mdecrypt_generic解密資料

警告

此函式在 PHP 7.1.0 起已過時,並在 PHP 7.2.0 起已移除。強烈建議不要依賴此函式。

說明

mdecrypt_generic(資源 $td, 字串 $data): 字串

此函式會解密資料。請注意,由於資料的填充,返回字串的長度實際上可能比未加密的字串更長。

參數

td

mcrypt_module_open() 返回的加密描述符。

data

已加密的資料。

返回值

返回已解密的字串。

範例

範例 #1 mdecrypt_generic() 範例

<?php
/* 資料 */
$key = 'this is a very long key, even too long for the cipher';
$plain_text = 'very important data';

/* 開啟模組並建立 IV */
$td = mcrypt_module_open('des', '', 'ecb', '');
$key = substr($key, 0, mcrypt_enc_get_key_size($td));
$iv_size = mcrypt_enc_get_iv_size($td);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

/* 初始化加密控制代碼 */
if (mcrypt_generic_init($td, $key, $iv) != -1) {

/* 加密資料 */
$c_t = mcrypt_generic($td, $plain_text);
mcrypt_generic_deinit($td);

/* 重新初始化用於解密的緩衝區 */
mcrypt_generic_init($td, $key, $iv);
$p_t = mdecrypt_generic($td, $c_t);

/* 清理 */
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}

if (
strncmp($p_t, $plain_text, strlen($plain_text)) == 0) {
echo
"ok\n";
} else {
echo
"error\n";
}
?>

上面的範例顯示如何檢查加密前的資料是否與解密後的資料相同。在嘗試解密資料之前,使用 mcrypt_generic_init() 重新初始化加密緩衝區非常重要。

解密控制代碼應始終在使用此函式之前,使用金鑰和 IV 來透過 mcrypt_generic_init() 初始化。在完成加密後,您應該透過呼叫 mcrypt_generic_deinit() 來釋放加密緩衝區。有關範例,請參閱 mcrypt_module_open()

參見

新增註解

使用者貢獻的註解 11 則註解

6
nytro_rst at yahoo dot com
15 年前
<?php
// 參數:
// $text = 您要加密的文字。
// $key = 您用來加密的金鑰。
// $alg = 加密演算法。
// $crypt = 如果要加密則設為 1,如果要解密則設為 0。

function cryptare($text, $key, $alg, $crypt)
{
$encrypted_data="";
switch(
$alg)
{
case
"3des":
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
break;
case
"cast-128":
$td = mcrypt_module_open('cast-128', '', 'ecb', '');
break;
case
"gost":
$td = mcrypt_module_open('gost', '', 'ecb', '');
break;
case
"rijndael-128":
$td = mcrypt_module_open('rijndael-128', '', 'ecb', '');
break;
case
"twofish":
$td = mcrypt_module_open('twofish', '', 'ecb', '');
break;
case
"arcfour":
$td = mcrypt_module_open('arcfour', '', 'ecb', '');
break;
case
"cast-256":
$td = mcrypt_module_open('cast-256', '', 'ecb', '');
break;
case
"loki97":
$td = mcrypt_module_open('loki97', '', 'ecb', '');
break;
case
"rijndael-192":
$td = mcrypt_module_open('rijndael-192', '', 'ecb', '');
break;
case
"saferplus":
$td = mcrypt_module_open('saferplus', '', 'ecb', '');
break;
case
"wake":
$td = mcrypt_module_open('wake', '', 'ecb', '');
break;
case
"blowfish-compat":
$td = mcrypt_module_open('blowfish-compat', '', 'ecb', '');
break;
case
"des":
$td = mcrypt_module_open('des', '', 'ecb', '');
break;
case
"rijndael-256":
$td = mcrypt_module_open('rijndael-256', '', 'ecb', '');
break;
case
"xtea":
$td = mcrypt_module_open('xtea', '', 'ecb', '');
break;
case
"enigma":
$td = mcrypt_module_open('enigma', '', 'ecb', '');
break;
case
"rc2":
$td = mcrypt_module_open('rc2', '', 'ecb', '');
break;
default:
$td = mcrypt_module_open('blowfish', '', 'ecb', '');
break;
}

$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr($key, 0, mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);

if(
$crypt)
{
$encrypted_data = mcrypt_generic($td, $text);
}
else
{
$encrypted_data = mdecrypt_generic($td, $text);
}

mcrypt_generic_deinit($td);
mcrypt_module_close($td);

return
$encrypted_data;
}
?>
4
jakub dot lopuszanski at nasza-klasa dot pl
11 年前
對於所有因填充(即使在方法描述中已提及)而「感到驚訝」的人,請不要只是「移除所有我不理解的東西」。
使用 rtrim、rtrim "\0"、移除所有 charcodes < 16 等等的方法都是錯誤的。
PKCS #7 填充的運作方式與 RFC 5652 中描述的完全相同。
要移除它,只需查看訊息的最後一個位元組,它會告訴您要移除多少個位元組。
例如,如果最後一個位元組等於 \0A,則移除 10 個位元組。
2
Ulysse
11 年前
根據 "jakub dot lopuszanski at nasza-klasa dot pl" 提供的資訊,在 PKCS#7 中,最後一個位元組包含要移除的位元組數(請參閱 RFC 5652,第 6.3 部分),並且對於像我一樣喜歡複製貼上現成程式碼片段的人

<?php
function unpadPKCS7($data, $blocksize)
{
$last = substr($data, -1);
return
substr($data, 0, strlen($data) - ord($last));
}
?>

現在您沒有理由再使用 rtrim() 來移除結果末尾的填充。
2
Anonymous
15 年前
這是一個快速移除 PKCS7 填充的程式碼片段

<?php
function unpadPKCS7($data, $blockSize) {
$length = strlen ( $data );
if (
$length > 0) {
$first = substr ( $data, - 1 );

if (
ord ( $first ) <= $blockSize) {
for(
$i = $length - 2; $i > 0; $i --)
if (
ord ( $data [$i] != $first ))
break;

return
substr ( $data, 0, $i );
}
}
return
$data;
}
?>
2
Peter Bailey
12 年前
我們發現有時候產生的填充並非空字元「\0」,而是一些控制字元。

如果您知道您的資料不應該有任何尾隨的控制字元(就像我們的情況),您可以像這樣去除它們。

<?php

$data
= mdecrypt_generic( $cipher, $data );

// 去除尾隨的控制字元填充
$data = preg_replace( "/\p{Cc}*$/u", "", $data );

?>
2
trashmail dot hashishin at gmail dot com
14 年前
當您需要解密使用 dot.net (以及其他?) 加密的文件時,您可以使用以下設定

加密方式:'rijndael-256'
模式:'cbc'
填充模式:Zeros
iv: "yes"

使用 base64 編碼資料後,將其傳送到您的 php 腳本
1
robbie [at] averill [dot] co [dot] nz
19 年前
我注意到有時候當二進位密文比明文長時,解密後的明文旁邊可能會有一些小方塊/正方形作為「填充」。我也注意到您無法複製貼上它們來編輯,但我找到了一個解決方案。

只要在字串周圍呼叫 rtrim() 就可以移除它們。
0
Silvan
17 年前
通常不建議僅使用 rtrim 來移除填充。

對於不以「\0」結尾的字串,請使用 rtrim($str, "\0"),或在加密時儲存資料長度。
(雖然包含「\0」的資料有時會在加密期間損壞,因此這些類型的資料實際上應該打包。)

例如

<?php

function encrypt($original_data)
{
$length = strlen($original_data);
$data_to_encrypt = $length.'|'.$original_data;
// 加密包含長度的資料。
// 不要將長度未加密地儲存,因為這可能是一個(小的)安全風險
}

function
decrypt($cypher)
{
// 首先解密密文資料
// 接下來檢索原始資料
list($length, $padded_data) = explode('|', $decrypted_data, 2);
$original_data = substr($padded_data, 0, $length);
}

?>
0
php at pcwize dot com
18 年前
只是確認 .DLL 的問題。使用 4.3.4 版本您需要較舊的 .DLL。我猜測任何 PHP4 版本都需要較舊的 .DLL。使用 PHP5 版本您需要較新的 .DLL。
0
drew at expressdynamics dot com
19 年前
在 Windows 32 位元系統上使用 PHP 5 時,您必須使用較新的 libmcrypt.dll 檔案,否則 mdecrypt_generic 將無法運作。
0
jon@jonroig dot com
20 年前
這是一些加密/解密程式碼。

如果您在 Windows 32 位元平台上使用此程式碼,請注意!最新的 DLL (2004 年 1 月 19 日) 包含一個會導致 mdecrypt_generic 無法運作的錯誤。差點把我逼瘋... 2002 年 12 月 30 日的版本似乎運作正常。
<?

$key = "這是一個秘密金鑰";
$input = "讓我們在秘密地點 9 點鐘見面。";

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

echo "加密: ".$encrypted_data;

echo "<br><br>";

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr($key, 0, mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$decrypted_data = mdecrypt_generic($td, $encrypted_data);
echo "解密: ".$decrypted_data;
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

?>
To Top