PHP Conference Japan 2024

mcrypt_create_iv

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

mcrypt_create_iv從隨機來源建立初始化向量 (IV)

警告

此函式在 PHP 7.1.0 中已不建議使用,並在 PHP 7.2.0 中移除

此函式的替代方案包括

說明

mcrypt_create_iv(int $size, int $source = MCRYPT_DEV_URANDOM): string

從隨機來源建立初始化向量 (IV)。

IV 僅用於為加密常式提供替代種子。此 IV 完全不需要是秘密的,儘管可能是期望如此。您甚至可以將它與您的密文一起傳送,而不會失去安全性。

參數

size

IV 的大小。

source

IV 的來源。來源可以是 MCRYPT_RAND(系統隨機數字產生器)、MCRYPT_DEV_RANDOM(從 /dev/random 讀取資料)和 MCRYPT_DEV_URANDOM(從 /dev/urandom 讀取資料)。在 5.3.0 之前,MCRYPT_RAND 是 Windows 上唯一支援的選項。

請注意,此參數的預設值在 PHP 5.6.0 之前為 MCRYPT_DEV_RANDOM

注意請注意,MCRYPT_DEV_RANDOM 可能會阻塞,直到有更多熵可用。

回傳值

回傳初始化向量,錯誤時回傳 false

範例

範例 1 mcrypt_create_iv() 範例

<?php
$size
= mcrypt_get_iv_size(MCRYPT_CAST_256, MCRYPT_MODE_CFB);
$iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
?>

參閱

新增附註

使用者提供的附註 12 個附註

44
Graham
10 年前
關於這裡看到的所有加密「建議」,我的建議是您忽略大部分的建議。其中一些是好的,一些是壞的,但大多數都跳過了關鍵問題。

我本希望寫一篇長篇解釋,但 PHP 的註解系統告訴我我的文章太長了。相反,我會這樣說

您應該使用 CBC,使用每個金鑰唯一隨機選擇的 IV,並且您應該將該 IV 與您的密文一起以明文傳輸。您還應該使用類似 HMAC-SHA256 的東西,使用另一個獨立的金鑰,對整個資料 blob 執行真實性檢查。

這是我打算寫的完整文字:http://pastebin.com/sN6buivY

如果您對這方面感興趣,或只是想了解更多資訊,請查看維基百科中關於區塊加密模式、區塊加密、HMAC 等的文章。

我也建議閱讀 Bruce Schneier 的《Practical Cryptography》,以及 Niels Ferguson 的《Cryptography Engineering》,這兩本都是非常容易理解的實用密碼學書籍。
16
Chris
18 年前
>首先,IV 應該是隨機且可變的。它的重點在於確保相同的純文字不會 >每次都加密為相同的密文。如果 IV 是恆定或公開的,您肯定會失去安全性。

錯誤,錯誤,大錯特錯!初始化向量允許公開!它通常與密文一起傳送,未加密。

>密文應該是 E(IV | 純文字, 金鑰)

又錯了!初始化向量在加密之前不會附加到純文字。IV 用於為回饋系統設定種子! (這就是為什麼您在 ECB 模式下不需要一個的原因 - 沒有回饋)

>第二,IV 不應該是解密 >參數的一部分。您應該能夠解密密文,扔掉前面的初始化向量,甚至不用 >讀取它,並取得您的純文字

不。您需要在解密期間將回饋機制設定為與加密期間設定的狀態相同。這表示使用相同的 IV!
5
nils at nm dot cx
12 年前
如果您使用 /dev/random,您需要一個填滿的熵池,否則應用程式會阻塞,直到有足夠的良好熵可用
6
hans at llis dot nl
12 年前
這並非在所有系統上產生隨機分佈的 IV,因此構成了很大的安全風險。使用腳本(基於 Alex Khimch's 在 rand() 頁面上發布的腳本),可以輕鬆檢查這一點

<?php

$td
= mcrypt_module_open (MCRYPT_RIJNDAEL_256, "", MCRYPT_MODE_CBC, "");
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($td), MCRYPT_DEV_RANDOM);

// header("Content-type: image/png");
$img = imagecreatetruecolor(255,255);

$ink = imagecolorallocate($img,255,255,255);
for(
$i=0;$i<255;$i++) {
for(
$j=0;$j<255;$j++) {
$twobytes = substr ($iv, 0, 2);
$iv = substr ($iv, 2);
if (!
strlen ($iv)) $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($td), MCRYPT_RAND);

imagesetpixel($img, ord($twobytes[0]), ord($twobytes[1]), $ink);
}
}

imagepng($img);
imagedestroy($img);

?>

產生的影像應該顯示隨機雜訊,但我在測試的 Windows 系統 (執行 PHP 5.3.x) 上顯示出非常明顯的模式。
5
robert at peakepro dot com
20 年前
重要的是,除了 ecb 以外的所有加密模式都要求解密時使用的 IV 與加密時使用的 IV 相同。

您需要將金鑰 *和* IV 傳遞給解密函式。在解密程序中初始化新的 IV 將無法運作。

由於「您甚至可以將 [IV] 與密文一起傳送,而不會損失安全性」,一個很好的處理方式是將 IV 前置於密文。由於 IV 的寬度是固定的,因此您可以使用 mcrypt_get_iv_size() 和 substr() 輕鬆恢復 IV 和原始密文。

以下是一個範例

<?PHP
function my_encrypt($string,$key) {
srand((double) microtime() * 1000000); //為了 MCRYPT_RAND
$key = md5($key); //為了提高變異性
/* 開啟模組,並建立 IV */
$td = mcrypt_module_open('des', '','cfb', '');
$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, $string);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$c_t = $iv.$c_t;
return
$c_t;
}
//end if
}

function
my_decrypt($string,$key) {
$key = md5($key); //為了提高變異性
/* 開啟模組,並建立 IV */
$td = mcrypt_module_open('des', '','cfb', '');
$key = substr($key, 0, mcrypt_enc_get_key_size($td));
$iv_size = mcrypt_enc_get_iv_size($td);
$iv = substr($string,0,$iv_size);
$string = substr($string,$iv_size);
/* 初始化加密控制代碼 */
if (mcrypt_generic_init($td, $key, $iv) != -1) {

/* 加密資料 */
$c_t = mdecrypt_generic($td, $string);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return
$c_t;
}
//end if
}
// 測試:
//print my_decrypt(my_encrypt("Hello, world.","foo"),"foo");
?>
2
kkaiser at dataresolutions dot com
18 年前
在分析我維護的一個相當龐大的動態網站,以確定執行過程中斷性凍結的原因後,我發現使用 MCRYPT_DEV_RANDOM 作為來源呼叫 mcrypt_create_iv() 會持續停止執行,每次呼叫的時間從 0.2 秒到約 12 秒不等,諷刺的是,這是隨機發生的。我假設停止是由於 /dev/random 中目前可用的隨機輸入不足所導致的,因為它的預期功能是阻塞,直到足夠的隨機輸入提供回裝置。我發現使用以下修改後的 alt_mcrypt_create_iv() 函式足以滿足我的需求。

雖然未經測試,但我假設使用 MCRYPT_DEV_URANDOM 或 MCRYPT_DEV_RAND 與 srand() 的組合也可以解決問題;事後我發現 /dev/urandom 的預期功能是在 /dev/urandom 緩衝區為空時,無縫地從隨機數產生器提供加密安全的輸出,而 MCRYPT_DEV_RAND 只會使用與 alt_mcrypt_create_iv() 相同的 rand() 函式。

-凱文·凱撒
2
tim at indigopixel dot com
20 年前
來自 http://www.ciphersbyritter.com/GLOSSARY.HTM#IV (如上連結)

「雖然人們常說 IV 值只需要像隨機或不可預測,並且不需要保密,但在 CBC 模式下,該建議可能會導致對第一個明文區塊的中間人攻擊。如果 MITM 對手知道第一個區塊的通常內容,他們可以更改 IV 來操縱該區塊(且僅該區塊)以傳送不同的地址、不同的金額、不同的命令或任何其他內容。雖然傳統的建議是在較高的層級使用 MAC 來偵測已變更的明文,但這並非總是理想或適當的執行方式。但是,CBC 第一個區塊問題很容易在 CBC 層級解決,只需加密 IV 並保持其機密性,即使稍後將使用 MAC,這也是合理的。」
1
joseph dot t dot fallon at gmail dot com
9 年前
區塊加密的核心是一對轉換演算法,稱為轉換。一個加密,一個解密 - 在某些情況下,演算法是相同的,但這並不重要。區塊轉換採用固定長度的明文區塊,使用某個選定大小的密鑰對其進行轉換,並產生長度相同的密文區塊。當然,反之亦然(解密)。

區塊加密的安全模型,至少簡單來說,被定義為「如果您使用隨機選擇的金鑰加密一個明文區塊,則僅知道密文的攻擊者(即,他不知道金鑰)在計算上是不可行的,無法發現有關明文內容的資訊」。事實略有不同 - 還有一些條款是關於知道部分明文而無法發現更多明文 - 但那是另一個故事。

一旦您開始使用相同的區塊轉換和相同的金鑰來加密多個明文區塊,一切就都沒保障了。在電子密碼本 (ECB) 加密模式下,每個明文區塊都使用相同的金鑰獨立轉換。這會導致一個問題:當使用相同的金鑰時,相同的明文區塊會產生相同的密文區塊。這表示可以看到資料中的「模式」,尤其是在具有重複模式或長序列相同資料的資料格式中。這最好以視覺方式描述,使用 ECB 加密的點陣圖。請參閱 Wikipedia 上關於 ECB 的文章,以了解此示範。
1
Matthew
16 年前
我正在處理的一個專案中,我加密了頁面上的一些項目,並且我發現 IV 建立函式也會導致頁面呈現出現巨大的延遲(我注意到這裡的其他人也有這個問題)。

對於一個應該是快速的網站來說,4 秒的呈現時間是很常見的。我建議,如果速度至關重要,則應使用替代方法來建立 IV(例如,如果您覺得以下方法足夠安全)。

在使用替代 IV 建立方法後,我的頁面呈現時間從 4 秒降至 0.01 秒。
0
wschalle at gmail dot com
9 年前
hans at illis dot nl 的示範程式碼不正確。在迴圈中,他使用

$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($td), MCRYPT_RAND);

但實際上應該是

$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($td), MCRYPT_DEV_URANDOM);

這會在 Windows 上產生一致的結果。
-1
Anonymous
19 年前

edwardzyang at thewritingpot dot com
2005 年 7 月 19 日 10:06

這是因為事實上(如上述手冊所述),此函式並不會重新設定亂數產生器,這與 rand() 相反。請如上述建議使用 srand() 來取得正確的 IV。
-4
Mahn
10 年前
如果此函式在您的請求中隨機掛起,請在第二個參數中指定 MCRYPT_RAND。
To Top