?
本文檔使用 php中文網(wǎng)手冊 發(fā)布
重要
不要將這個或任何其他加密庫用于用戶密碼存儲!密碼必須進(jìn)行散列處理,您應(yīng)該通過PHP自己的密碼散列擴展來實現(xiàn)。
加密庫提供雙向數(shù)據(jù)加密。為了以密碼安全的方式這樣做,它使用了PHP擴展,但不幸的是,這些擴展在所有系統(tǒng)上都不可用。您必須滿足以下某個依賴項才能使用此庫:
OpenSSL的
MCrypt(和MCRYPT_DEV_URANDOM
可用性)
如果上述依賴關(guān)系都不符合,我們根本無法為您提供足夠好的實現(xiàn)來滿足正確加密所需的高標(biāo)準(zhǔn)。
使用加密庫
便攜式密碼
驅(qū)動程序特定的密碼
加密模式
初始化類
默認(rèn)行為
設(shè)置您的encryption_key
支持的加密密碼和模式
- [Message Length](about:blank#message-length)- [Configuring the library](about:blank#configuring-the-library)- [Encrypting and decrypting data](about:blank#encrypting-and-decrypting-data) - [How it works](about:blank#how-it-works) - [Using custom parameters](about:blank#using-custom-parameters) - [Supported HMAC authentication algorithms](about:blank#supported-hmac-authentication-algorithms)
類參考
像CodeIgniter中的大多數(shù)其他類一樣,Encryption庫在您的控制器中使用以下$this->load->library()
方法進(jìn)行初始化:
$this->load->library('encryption');
加載后,加密庫對象將可用:
$this->encryption
默認(rèn)情況下,加密庫將使用CBC模式下的AES-128密碼,使用您配置的encryption_key和SHA512 HMAC驗證。
注意
選擇AES-128是因為它被證明是強大的,并且因為它在不同的加密軟件和編程語言的API中具有廣泛的可用性。
但是,encryption_key沒有按原樣使用。
如果您對密碼學(xué)有所了解,則應(yīng)該已經(jīng)知道HMAC也需要一個密鑰,并且使用相同的密鑰進(jìn)行加密和身份驗證是一種不好的做法。
因此,從已經(jīng)配置的encryption_key派生出兩個單獨的密鑰:一個用于加密,一個用于驗證。這是通過稱為基于HMAC的密鑰導(dǎo)出函數(shù)(HKDF)的技術(shù)完成的。
的加密密鑰是一條信息,其控制密碼處理并且允許以加密的純文本字符串,事后-解密。這是整個過程中的秘密“成分”,它使您成為唯一能夠解密您決定隱藏在公眾眼中的數(shù)據(jù)的人。在使用一個密鑰加密數(shù)據(jù)后,同一個密鑰提供唯一的解密方法,所以不僅必須仔細(xì)選擇一個密鑰,而且不能丟失數(shù)據(jù),否則您將無法訪問數(shù)據(jù)。
必須指出的是,以確保最大的安全性,比如關(guān)鍵應(yīng)該不僅是越強越好,而且還經(jīng)常變化。然而,這樣的行為很難實現(xiàn)或者不可能實現(xiàn),這就是為什么CodeIgniter允許您配置每次使用(幾乎)使用的單個密鑰的能力。
不用說,你應(yīng)該小心地保護(hù)你的鑰匙。如果有人能夠訪問您的密鑰,數(shù)據(jù)將很容易解密。如果你的服務(wù)器不完全在你的控制之下,那么確保關(guān)鍵的安全是不可能的,所以你可能需要仔細(xì)思考,然后將它用于需要高度安全性的任何事情,比如存儲信用卡號碼。
您的加密密鑰必須與正在使用的加密算法一致。對于AES-128,這是128位或16字節(jié)(charcters)長。您會在下面找到一張表格,顯示不同密碼支持的密鑰長度。
密鑰應(yīng)盡可能隨機,并且不能是常規(guī)文本字符串,也不能是哈希函數(shù)的輸出等。為了創(chuàng)建適當(dāng)?shù)拿荑€,您必須使用加密庫的create_key()
方法
// $key will be assigned a 16-byte (128-bit) random key$key = $this->encryption->create_key(16);
密鑰可以存儲在application / config / config.php中,也可以設(shè)計自己的存儲機制并在加密/解密時動態(tài)傳遞密鑰。
要將你的密鑰保存到你的application / config / config.php中,打開該文件并設(shè)置:
$config['encryption_key'] = 'YOUR KEY';
你會注意到create_key()
方法輸出二進(jìn)制數(shù)據(jù),這是很難對付(即復(fù)制粘貼可能會損壞),所以您可以使用bin2hex()
,hex2bin()
或Base64編碼以更友好的方式的關(guān)鍵工作。例如:
// Get a hex-encoded representation of the key:$key = bin2hex($this->encryption->create_key(16));// Put the same value in your config with hex2bin(),// so that it is still passed as binary to the library:$config['encryption_key'] = hex2bin(<your hex-encoded key>);
注意
術(shù)語'密碼'和'加密算法'是可以互換的。
由于MCrypt和OpenSSL(在本文檔中也稱為驅(qū)動程序)各自支持不同的加密算法集,并且通常以不同的方式實現(xiàn)它們,因此我們的加密庫旨在以便攜式方式使用它們,換句話說 - 它使您可以使用它們可以互換,至少對于兩個司機都支持的密碼。
它也以一種旨在與其他編程語言和庫中的標(biāo)準(zhǔn)實現(xiàn)相匹配的方式實現(xiàn)。
以下是所謂的“便攜式”密碼列表,其中“CodeIgniter名稱”是您必須傳遞給加密庫以使用該密碼的字符串值:
密碼名稱 | CodeIgniter名稱 | 密鑰長度(比特/字節(jié)) | 支持的模式 |
---|---|---|---|
AES-128 / Rijndael-128 | AES-128 | 128 / 16 | CBC,CTR,CFB,CFB8,OFB,ECB |
AES-192 | AES-192 | 192 / 24 | CBC,CTR,CFB,CFB8,OFB,ECB |
AES-256 | AES-256 | 256 / 32 | CBC,CTR,CFB,CFB8,OFB,ECB |
DES | des | 56 / 7 | CBC,CFB,CFB8,OFB,ECB |
TripleDes的 | TripleDes的 | 56 / 7, 112 / 14, 168 / 21 | CBC,CFB,CFB8,OFB |
Blowfish | blowfish | 128-448 / 16-56 | CBC,CFB,OFB,ECB |
CAST5 / CAST-128 | CAST5 | 88-128 / 11-16 | CBC,CFB,OFB,ECB |
RC4 / ARCFour | RC4 | 40-2048 / 5-256 | 流 |
重要
由于MCrypt的工作原理,如果您未能提供適當(dāng)長度的密鑰,最終可能會使用與配置的算法不同的算法,因此請小心!
注意
如果從上表不清楚,Blowfish,CAST5和RC4支持可變長度密鑰。也就是說,所示范圍內(nèi)的任何數(shù)字都是有效的,盡管只是以8位增量發(fā)生。
注意
盡管CAST5支持的密鑰長度低于128位(16字節(jié)),但實際上它們只會被填充到最大長度,正如RFC 2144中所規(guī)定的那樣。
注意
Blowfish支持小至32位(4字節(jié))的密鑰長度,但我們的測試表明,只有128位(16字節(jié))或更高的長度才能被MCrypt和OpenSSL正確支持。無論如何,使用這種低長度的密鑰也是不好的做法。
如上所述,MCrypt和OpenSSL支持不同的加密密碼組。出于可移植性的原因,并且由于我們沒有正確測試它們,我們不建議您使用特定于驅(qū)動程序的驅(qū)動程序,但不管如何,這里列出了大多數(shù)驅(qū)動程序:
Cipher 名稱 | Driver | 關(guān)鍵字長度(bits / bytes) | 支持的模型 |
---|---|---|---|
AES-128 | OpenSSL | 128 / 16 | CBC, CTR, CFB, CFB8, OFB, ECB, XTS |
AES-192 | OpenSSL | 192 / 24 | CBC, CTR, CFB, CFB8, OFB, ECB, XTS |
AES-256 | OpenSSL | 256 / 32 | CBC, CTR, CFB, CFB8, OFB, ECB, XTS |
Rijndael-128 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
Rijndael-192 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
Rijndael-256 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
GOST | MCrypt | 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
Twofish | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
CAST-128 | MCrypt | 40-128 / 5-16 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
CAST-256 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
Loki97 | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
SaferPlus | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
Serpent | MCrypt | 128 / 16, 192 / 24, 256 / 32 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
XTEA | MCrypt | 128 / 16 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
RC2 | MCrypt | 8-1024 / 1-128 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB |
RC2 | OpenSSL | 8-1024 / 1-128 | CBC, CFB, OFB, ECB |
Camellia-128 | OpenSSL | 128 / 16 | CBC, CFB, CFB8, OFB, ECB |
Camellia-192 | OpenSSL | 192 / 24 | CBC, CFB, CFB8, OFB, ECB |
Camellia-256 | OpenSSL | 256 / 32 | CBC, CFB, CFB8, OFB, ECB |
Seed | OpenSSL | 128 / 16 | CBC, CFB, OFB, ECB |
注意
如果您希望使用其中一種密碼,則必須將其名稱以小寫形式傳遞到加密庫。
注意
您可能已經(jīng)注意到,所有AES cipers(和Rijndael-128)也列在便攜式密碼列表中。這是因為驅(qū)動程序支持這些密碼的不同模式。此外,重要的是要注意AES-128和Rijndael-128實際上是相同的密碼,但只有在與128位密鑰一起使用時才是如此。
注意
CAST-128 / CAST-5也列在便攜式和驅(qū)動程序?qū)S妹艽a列表中。這是因為OpenSSL的實現(xiàn)似乎無法正確使用80位或更低的密鑰。
注意
RC2被列為支持MCrypt和OpenSSL。但是,這兩個驅(qū)動程序都以不同的方式實現(xiàn)它們,并且它們不具有便攜性 可能值得注意的是,我們只發(fā)現(xiàn)了一個不明確的來源,確認(rèn)它是MCrypt沒有正確實施它。
不同的加密模式具有不同的特征并用于不同的目的。有些比其他更強,有些更快,有些提供額外的功能。我們不會深入討論這個問題,我們會將其留給加密專家。下表是為我們更有經(jīng)驗的用戶提供簡要的信息參考。如果你是初學(xué)者,只需堅持CBC模式 - 它被廣泛接受為強大和安全的一般用途。
模式名稱 | CodeIgniter名稱 | 驅(qū)動程序支持 | 附加信息 |
---|---|---|---|
CBC | CBC | MCrypt,OpenSSL | 一個安全的默認(rèn)選擇 |
CTR | CTR | MCrypt,OpenSSL | 理論上認(rèn)為比CBC更好,但沒有那么廣泛 |
CFB | CFB | MCrypt,OpenSSL | N / A |
CFB8 | CFB8 | MCrypt,OpenSSL | 與CFB相同,但以8位模式運行(不推薦)。 |
OFB | OFB | MCrypt,OpenSSL | N / A |
OFB8 | ofb8 | mcrypt的 | 與OFB相同,但以8位模式運行(不推薦)。 |
ECB | ecb | MCrypt,OpenSSL | 忽略IV(不推薦)。 |
XTS | XTS | OpenSSL的 | 通常用于加密隨機存取數(shù)據(jù),如RAM或硬盤存儲。 |
Stream | stream | MCrypt,OpenSSL | 這實際上不是一種模式,它只是說正在使用流密碼。由于通用密碼+模式初始化過程而需要。 |
知道加密的字符串通常比原始的純文本字符串長(取決于密碼)可能很重要。
這受到密碼算法本身,密文前置的IV和預(yù)先配置的HMAC認(rèn)證消息的影響。此外,加密的消息也是Base64編碼的,因此無論使用哪種字符集,都可以安全地進(jìn)行存儲和傳輸。
選擇數(shù)據(jù)存儲機制時請記住這些信息。例如,Cookie只能保存4K條信息。
為了可用性,性能以及與我們以前的加密類相關(guān)的歷史原因,加密庫旨在重復(fù)使用相同的驅(qū)動程序,加密密碼,模式和密鑰。
如上面的“默認(rèn)行為”部分所述,這意味著使用自動檢測的驅(qū)動程序(OpenSSL具有更高的優(yōu)先級),CBC模式下的AES-128鉗位和您的$config['encryption_key']
值。
但是,如果您想更改該initialize()
方法,則需要使用該方法。它接受一個參數(shù)的關(guān)聯(lián)數(shù)組,所有這些參數(shù)都是可選的:
選項 | 可能的值 |
---|---|
司機 | 'mcrypt','openssl' |
暗號 | 密碼名稱(請參閱支持的加密密碼和模式) |
模式 | 加密模式(請參閱加密模式) |
鍵 | 加密密鑰 |
例如,如果要在CTR模式下將加密算法和模式更改為AES-256,則應(yīng)該這樣做:
$this->encryption->initialize( array( 'cipher' => 'aes-256', 'mode' => 'ctr', 'key' => '<a 32-character random string>' ));
請注意,我們只提到要更改鉗位和模式,但我們還在示例中包含了一個鍵。如前所述,為使用的算法選擇適當(dāng)大小的密鑰非常重要。
如果出于某種原因,您也可以更改驅(qū)動程序,但是希望使用MCrypt而不是OpenSSL:
// Switch to the MCrypt driver$this->encryption->initialize(array('driver' => 'mcrypt'));// Switch back to the OpenSSL driver$this->encryption->initialize(array('driver' => 'openssl'));
使用已配置的庫設(shè)置加密和解密數(shù)據(jù)很簡單。就像將字符串傳遞給encrypt()
和/或decrypt()
方法一樣簡單:
$plain_text = 'This is a plain-text message!';$ciphertext = $this->encryption->encrypt($plain_text);// Outputs: This is a plain-text message!echo $this->encryption->decrypt($ciphertext);
就是這樣!加密庫將完成整個過程所需的一切,以加密保護(hù)開箱即用。你不需要擔(dān)心它。
重要
如果發(fā)生錯誤,兩種方法都將返回FALSE。雖然encrypt()
這只能意味著配置不正確,但您應(yīng)該始終檢查decrypt()
生產(chǎn)代碼的返回值。
如果你必須知道這個過程是如何工作的,下面是發(fā)生的一切:
$this->encryption->encrypt($plain_text)
使用SHA-512摘要算法,通過HKDF 從您配置的encryption_key導(dǎo)出加密密鑰和HMAC密鑰。
生成隨機初始化向量(IV)。
使用上述導(dǎo)出的加密密鑰和IV,以CBC模式(或其他先前配置的密碼和模式)通過AES-128對數(shù)據(jù)進(jìn)行加密。
在結(jié)果密文上面加上IV。
對結(jié)果字符串進(jìn)行Base64編碼,以便可以安全地存儲或傳輸字符集,而不用擔(dān)心字符集。
使用派生的HMAC密鑰創(chuàng)建SHA-512 HMAC認(rèn)證消息,以確保數(shù)據(jù)完整性并將其預(yù)先添加到Base64字符串中。
$this->encryption->decrypt($ciphertext)
使用SHA-512摘要算法,通過HKDF 從您配置的encryption_key導(dǎo)出加密密鑰和HMAC密鑰。由于您配置的encryption_key是相同的,所以會產(chǎn)生與上述encrypt()
方法相同的結(jié)果- 否則您將無法解密它。
檢查字符串是否足夠長,將HMAC從中分離出來并驗證它是否正確(這樣做是為了防止定時攻擊)。如果任一檢查失敗,則返回FALSE。
Base64解碼字符串。
將IV從密文中分離出來,并使用該IV和派生的加密密鑰對所述密文進(jìn)行解密。
假設(shè)您必須與另一個無法控制的系統(tǒng)進(jìn)行交互,并使用其他方法來加密數(shù)據(jù)。這種方法肯定不符合上述順序,也可能不會使用所有步驟。
加密庫允許您更改其加密和解密過程的工作方式,以便您可以輕松地為這種情況量身定制解決方案。
注意
可以以這種方式使用庫,而無需在配置文件中設(shè)置encryption_key。
你所要做的就是將一個帶有幾個參數(shù)的關(guān)聯(lián)數(shù)組傳遞給encrypt()
or decrypt()
方法。這是一個例子:
// Assume that we have $ciphertext, $key and $hmac_key// from on outside source$message = $this->encryption->decrypt( $ciphertext, array( 'cipher' => 'blowfish', 'mode' => 'cbc', 'key' => $key, 'hmac_digest' => 'sha256', 'hmac_key' => $hmac_key ));
在上面的例子中,我們使用CBC模式使用Blowfish密碼對消息進(jìn)行解密,并通過SHA-256 HMAC進(jìn)行驗證。
重要
請注意,在此示例中使用了'key'和'hmac_key'。在使用自定義參數(shù)時,加密和HMAC密鑰不會像庫的默認(rèn)行為那樣派生。
以下是可用選項的列表。
但是,除非您真的需要并且您知道自己在做什么,否則我們建議您不要更改加密過程,因為這可能會影響安全性,所以請謹(jǐn)慎操作。
選項 | 默認(rèn)值 | 強制/可選 | 描述 |
---|---|---|---|
cipher | N / A | 是 | 加密算法(請參閱支持的加密密碼和模式)。 |
模式 | N / A | 是 | 加密模式(請參閱加密模式)。 |
鍵 | N / A | 是 | 加密密鑰。 |
HMAC | 真正 | 沒有 | 是否使用HMAC。布爾。如果設(shè)置為FALSE,則hmac_digest和hmac_key將被忽略。 |
hmac_digest | SHA512 | 沒有 | HMAC消息摘要算法(請參閱支持的HMAC認(rèn)證算法)。 |
hmac_key | N / A | 是的,除非hmac是FALSE | HMAC密鑰。 |
原始數(shù)據(jù) | 假 | 沒有 | 密文是否應(yīng)該是原始的。布爾。如果設(shè)置為TRUE,則不會執(zhí)行Base64編碼和解碼,并且HMAC不會是十六進(jìn)制字符串。 |
重要
encrypt()decrypt()
如果沒有提供強制性參數(shù)或提供的值不正確,將返回FALSE。這包括hmac_key,除非hmac設(shè)置為FALSE。
對于HMAC消息認(rèn)證,加密庫支持使用SHA-2系列算法:
算法 | 原始長度(字節(jié)) | 十六進(jìn)制編碼的長度(字節(jié)) |
---|---|---|
SHA512 | 64 | 128 |
SHA384 | 48 | 96 |
SHA256 | 32 | 64 |
SHA224 | 28 | 56 |
不包括其他常用算法(如MD5或SHA1)的原因是它們不再被認(rèn)為是安全的,因此我們不希望鼓勵它們的使用。如果您絕對需要使用它們,通過PHP的本地hash_hmac()函數(shù)很容易實現(xiàn)。
當(dāng)然,更強大的算法將來會隨著它們的出現(xiàn)而被廣泛使用。
class CI_Encryptioninitialize($params)
參數(shù): | $ params(array) - 配置參數(shù) |
---|---|
返回: | CI_加密實例(方法鏈接) |
返回類型: | CI_Encryption |
$ params(array) - 配置參數(shù)
Returns: CI\_Encryption instance (method chaining)
Return type: CI\_Encryption
初始化(配置)庫以使用不同的驅(qū)動程序,密碼,模式或密鑰。
例:
$this->encryption->initialize( array('mode' => 'ctr') );
有關(guān)詳細(xì)信息,請參閱配置庫部分。
encrypt($data[, $params = NULL])
參數(shù): | $ data(string) - 要加密$ params(數(shù)組)的數(shù)據(jù) - 可選參數(shù) |
---|---|
返回: | 加密數(shù)據(jù)或失敗時為FALSE |
返回類型: | 串 |
$ data(string) - 要加密的數(shù)據(jù)
$ params(array) - 可選參數(shù)
返回:加密的數(shù)據(jù)或失敗時的FALSE
返回類型:字符串
加密輸入數(shù)據(jù)并返回其密文。
例:
$ciphertext = $this->encryption->encrypt('My secret message');
有關(guān)可選參數(shù)的信息,請參閱使用自定義參數(shù)部分。
decrypt($data[, $params = NULL])
參數(shù): | $ data(string) - 解密$ params(array)的數(shù)據(jù) - 可選參數(shù) |
---|---|
返回: | 解密數(shù)據(jù)或失敗時失敗 |
返回類型: | 串 |
$ data(string) - 要解密的數(shù)據(jù)
$ params(array) - 可選參數(shù)
返回:解密的數(shù)據(jù)或失敗時的FALSE
返回類型:字符串
解密輸入數(shù)據(jù)并以純文本形式返回。
例:
echo $this->encryption->decrypt($ciphertext);
有關(guān)可選參數(shù)的信息,請參閱使用自定義參數(shù)secrion。
create_key($length)
參數(shù): | $ length(int) - 輸出長度 |
---|---|
返回: | 具有指定長度的偽隨機加密密鑰,或失敗時為FALSE |
返回類型: | 串 |
$ length(int) - 輸出長度
返回:具有指定長度的偽隨機加密密鑰,或失敗時為FALSE
返回類型:字符串
通過從操作系統(tǒng)的源中獲取隨機數(shù)據(jù)(即/ dev / urandom)創(chuàng)建加密密鑰。
hkdf($key[, $digest = 'sha512'[, $salt = NULL[, $length = NULL[, $info = '']]]])
參數(shù): | $ key(字符串) - 輸入密鑰材料$ digest(字符串) - 一個SHA-2家族摘要算法$ salt(string) - 可選salt $ length(int) - 可選輸出長度$ info(字符串) - 可選上下文/具體信息 |
---|---|
返回: | 偽隨機密鑰或FALSE失敗 |
返回類型: | 串 |
$ key(字符串) - 輸入密鑰材料
$ digest(字符串) - 一個SHA-2家族摘要算法
$salt(字符串) - 可選鹽
$ length(int) - 可選輸出長度
$ info(字符串) - 可選的上下文/特定于應(yīng)用程序的信息
返回:失敗時的偽隨機密鑰或FALSE
返回類型:字符串
從另一個推導(dǎo)出一個密鑰,推測是較弱的密鑰。
此方法在內(nèi)部用于從您配置的encryption_key派生加密和HMAC密鑰。
由于其他一般目的,它是公開可用的。它在RFC 5869中有描述。
但是,與RFC 5869中的描述相反,此實現(xiàn)不支持SHA1。
例:
$hmac_key = $this->encryption->hkdf( $key, 'sha512', NULL, NULL, 'authentication' ); // $hmac_key is a pseudo-random key with a length of 64 bytes