©
本文档使用 PHP中文网手册 发布
重要
不要将这个或任何其他加密库用于用户密码存储!密码必须进行散列处理,您应该通过PHP自己的密码散列扩展来实现。
加密库提供双向数据加密。为了以密码安全的方式这样做,它使用了PHP扩展,但不幸的是,这些扩展在所有系统上都不可用。您必须满足以下某个依赖项才能使用此库:
OpenSSL的
MCrypt(和MCRYPT_DEV_URANDOM
可用性)
如果上述依赖关系都不符合,我们根本无法为您提供足够好的实现来满足正确加密所需的高标准。
使用加密库
便携式密码
驱动程序特定的密码
加密模式
初始化类
默认行为
设置您的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中的大多数其他类一样,Encryption库在您的控制器中使用以下$this->load->library()
方法进行初始化:
$this->load->library('encryption');
加载后,加密库对象将可用:
$this->encryption
默认情况下,加密库将使用CBC模式下的AES-128密码,使用您配置的encryption_key和SHA512 HMAC验证。
注意
选择AES-128是因为它被证明是强大的,并且因为它在不同的加密软件和编程语言的API中具有广泛的可用性。
但是,encryption_key没有按原样使用。
如果您对密码学有所了解,则应该已经知道HMAC也需要一个密钥,并且使用相同的密钥进行加密和身份验证是一种不好的做法。
因此,从已经配置的encryption_key派生出两个单独的密钥:一个用于加密,一个用于验证。这是通过称为基于HMAC的密钥导出函数(HKDF)的技术完成的。
的加密密钥是一条信息,其控制密码处理并且允许以加密的纯文本字符串,事后-解密。这是整个过程中的秘密“成分”,它使您成为唯一能够解密您决定隐藏在公众眼中的数据的人。在使用一个密钥加密数据后,同一个密钥提供唯一的解密方法,所以不仅必须仔细选择一个密钥,而且不能丢失数据,否则您将无法访问数据。
必须指出的是,以确保最大的安全性,比如关键应该不仅是越强越好,而且还经常变化。然而,这样的行为很难实现或者不可能实现,这就是为什么CodeIgniter允许您配置每次使用(几乎)使用的单个密钥的能力。
不用说,你应该小心地保护你的钥匙。如果有人能够访问您的密钥,数据将很容易解密。如果你的服务器不完全在你的控制之下,那么确保关键的安全是不可能的,所以你可能需要仔细思考,然后将它用于需要高度安全性的任何事情,比如存储信用卡号码。
您的加密密钥必须与正在使用的加密算法一致。对于AES-128,这是128位或16字节(charcters)长。您会在下面找到一张表格,显示不同密码支持的密钥长度。
密钥应尽可能随机,并且不能是常规文本字符串,也不能是哈希函数的输出等。为了创建适当的密钥,您必须使用加密库的create_key()
方法
// $key will be assigned a 16-byte (128-bit) random key$key = $this->encryption->create_key(16);
密钥可以存储在application / config / config.php中,也可以设计自己的存储机制并在加密/解密时动态传递密钥。
要将你的密钥保存到你的application / config / config.php中,打开该文件并设置:
$config['encryption_key'] = 'YOUR KEY';
你会注意到create_key()
方法输出二进制数据,这是很难对付(即复制粘贴可能会损坏),所以您可以使用bin2hex()
,hex2bin()
或Base64编码以更友好的方式的关键工作。例如:
// 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>);
注意
术语'密码'和'加密算法'是可以互换的。
由于MCrypt和OpenSSL(在本文档中也称为驱动程序)各自支持不同的加密算法集,并且通常以不同的方式实现它们,因此我们的加密库旨在以便携式方式使用它们,换句话说 - 它使您可以使用它们可以互换,至少对于两个司机都支持的密码。
它也以一种旨在与其他编程语言和库中的标准实现相匹配的方式实现。
以下是所谓的“便携式”密码列表,其中“CodeIgniter名称”是您必须传递给加密库以使用该密码的字符串值:
密码名称 | CodeIgniter名称 | 密钥长度(比特/字节) | 支持的模式 |
---|---|---|---|
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的工作原理,如果您未能提供适当长度的密钥,最终可能会使用与配置的算法不同的算法,因此请小心!
注意
如果从上表不清楚,Blowfish,CAST5和RC4支持可变长度密钥。也就是说,所示范围内的任何数字都是有效的,尽管只是以8位增量发生。
注意
尽管CAST5支持的密钥长度低于128位(16字节),但实际上它们只会被填充到最大长度,正如RFC 2144中所规定的那样。
注意
Blowfish支持小至32位(4字节)的密钥长度,但我们的测试表明,只有128位(16字节)或更高的长度才能被MCrypt和OpenSSL正确支持。无论如何,使用这种低长度的密钥也是不好的做法。
如上所述,MCrypt和OpenSSL支持不同的加密密码组。出于可移植性的原因,并且由于我们没有正确测试它们,我们不建议您使用特定于驱动程序的驱动程序,但不管如何,这里列出了大多数驱动程序:
Cipher 名称 | Driver | 关键字长度(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 |
注意
如果您希望使用其中一种密码,则必须将其名称以小写形式传递到加密库。
注意
您可能已经注意到,所有AES cipers(和Rijndael-128)也列在便携式密码列表中。这是因为驱动程序支持这些密码的不同模式。此外,重要的是要注意AES-128和Rijndael-128实际上是相同的密码,但只有在与128位密钥一起使用时才是如此。
注意
CAST-128 / CAST-5也列在便携式和驱动程序专用密码列表中。这是因为OpenSSL的实现似乎无法正确使用80位或更低的密钥。
注意
RC2被列为支持MCrypt和OpenSSL。但是,这两个驱动程序都以不同的方式实现它们,并且它们不具有便携性 可能值得注意的是,我们只发现了一个不明确的来源,确认它是MCrypt没有正确实施它。
不同的加密模式具有不同的特征并用于不同的目的。有些比其他更强,有些更快,有些提供额外的功能。我们不会深入讨论这个问题,我们会将其留给加密专家。下表是为我们更有经验的用户提供简要的信息参考。如果你是初学者,只需坚持CBC模式 - 它被广泛接受为强大和安全的一般用途。
模式名称 | CodeIgniter名称 | 驱动程序支持 | 附加信息 |
---|---|---|---|
CBC | CBC | MCrypt,OpenSSL | 一个安全的默认选择 |
CTR | CTR | MCrypt,OpenSSL | 理论上认为比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的 | 通常用于加密随机存取数据,如RAM或硬盘存储。 |
Stream | stream | MCrypt,OpenSSL | 这实际上不是一种模式,它只是说正在使用流密码。由于通用密码+模式初始化过程而需要。 |
知道加密的字符串通常比原始的纯文本字符串长(取决于密码)可能很重要。
这受到密码算法本身,密文前置的IV和预先配置的HMAC认证消息的影响。此外,加密的消息也是Base64编码的,因此无论使用哪种字符集,都可以安全地进行存储和传输。
选择数据存储机制时请记住这些信息。例如,Cookie只能保存4K条信息。
为了可用性,性能以及与我们以前的加密类相关的历史原因,加密库旨在重复使用相同的驱动程序,加密密码,模式和密钥。
如上面的“默认行为”部分所述,这意味着使用自动检测的驱动程序(OpenSSL具有更高的优先级),CBC模式下的AES-128钳位和您的$config['encryption_key']
值。
但是,如果您想更改该initialize()
方法,则需要使用该方法。它接受一个参数的关联数组,所有这些参数都是可选的:
选项 | 可能的值 |
---|---|
司机 | 'mcrypt','openssl' |
暗号 | 密码名称(请参阅支持的加密密码和模式) |
模式 | 加密模式(请参阅加密模式) |
键 | 加密密钥 |
例如,如果要在CTR模式下将加密算法和模式更改为AES-256,则应该这样做:
$this->encryption->initialize( array( 'cipher' => 'aes-256', 'mode' => 'ctr', 'key' => '<a 32-character random string>' ));
请注意,我们只提到要更改钳位和模式,但我们还在示例中包含了一个键。如前所述,为使用的算法选择适当大小的密钥非常重要。
如果出于某种原因,您也可以更改驱动程序,但是希望使用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'));
使用已配置的库设置加密和解密数据很简单。就像将字符串传递给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);
就是这样!加密库将完成整个过程所需的一切,以加密保护开箱即用。你不需要担心它。
重要
如果发生错误,两种方法都将返回FALSE。虽然encrypt()
这只能意味着配置不正确,但您应该始终检查decrypt()
生产代码的返回值。
如果你必须知道这个过程是如何工作的,下面是发生的一切:
$this->encryption->encrypt($plain_text)
使用SHA-512摘要算法,通过HKDF 从您配置的encryption_key导出加密密钥和HMAC密钥。
生成随机初始化向量(IV)。
使用上述导出的加密密钥和IV,以CBC模式(或其他先前配置的密码和模式)通过AES-128对数据进行加密。
在结果密文上面加上IV。
对结果字符串进行Base64编码,以便可以安全地存储或传输字符集,而不用担心字符集。
使用派生的HMAC密钥创建SHA-512 HMAC认证消息,以确保数据完整性并将其预先添加到Base64字符串中。
$this->encryption->decrypt($ciphertext)
使用SHA-512摘要算法,通过HKDF 从您配置的encryption_key导出加密密钥和HMAC密钥。由于您配置的encryption_key是相同的,所以会产生与上述encrypt()
方法相同的结果- 否则您将无法解密它。
检查字符串是否足够长,将HMAC从中分离出来并验证它是否正确(这样做是为了防止定时攻击)。如果任一检查失败,则返回FALSE。
Base64解码字符串。
将IV从密文中分离出来,并使用该IV和派生的加密密钥对所述密文进行解密。
假设您必须与另一个无法控制的系统进行交互,并使用其他方法来加密数据。这种方法肯定不符合上述顺序,也可能不会使用所有步骤。
加密库允许您更改其加密和解密过程的工作方式,以便您可以轻松地为这种情况量身定制解决方案。
注意
可以以这种方式使用库,而无需在配置文件中设置encryption_key。
你所要做的就是将一个带有几个参数的关联数组传递给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密码对消息进行解密,并通过SHA-256 HMAC进行验证。
重要
请注意,在此示例中使用了'key'和'hmac_key'。在使用自定义参数时,加密和HMAC密钥不会像库的默认行为那样派生。
以下是可用选项的列表。
但是,除非您真的需要并且您知道自己在做什么,否则我们建议您不要更改加密过程,因为这可能会影响安全性,所以请谨慎操作。
选项 | 默认值 | 强制/可选 | 描述 |
---|---|---|---|
cipher | N / A | 是 | 加密算法(请参阅支持的加密密码和模式)。 |
模式 | N / A | 是 | 加密模式(请参阅加密模式)。 |
键 | N / A | 是 | 加密密钥。 |
HMAC | 真正 | 没有 | 是否使用HMAC。布尔。如果设置为FALSE,则hmac_digest和hmac_key将被忽略。 |
hmac_digest | SHA512 | 没有 | HMAC消息摘要算法(请参阅支持的HMAC认证算法)。 |
hmac_key | N / A | 是的,除非hmac是FALSE | HMAC密钥。 |
原始数据 | 假 | 没有 | 密文是否应该是原始的。布尔。如果设置为TRUE,则不会执行Base64编码和解码,并且HMAC不会是十六进制字符串。 |
重要
encrypt()decrypt()
如果没有提供强制性参数或提供的值不正确,将返回FALSE。这包括hmac_key,除非hmac设置为FALSE。
对于HMAC消息认证,加密库支持使用SHA-2系列算法:
算法 | 原始长度(字节) | 十六进制编码的长度(字节) |
---|---|---|
SHA512 | 64 | 128 |
SHA384 | 48 | 96 |
SHA256 | 32 | 64 |
SHA224 | 28 | 56 |
不包括其他常用算法(如MD5或SHA1)的原因是它们不再被认为是安全的,因此我们不希望鼓励它们的使用。如果您绝对需要使用它们,通过PHP的本地hash_hmac()函数很容易实现。
当然,更强大的算法将来会随着它们的出现而被广泛使用。
class CI_Encryptioninitialize($params)
参数: | $ params(array) - 配置参数 |
---|---|
返回: | CI_加密实例(方法链接) |
返回类型: | CI_Encryption |
$ params(array) - 配置参数
Returns: CI\_Encryption instance (method chaining)
Return type: CI\_Encryption
初始化(配置)库以使用不同的驱动程序,密码,模式或密钥。
例:
$this->encryption->initialize( array('mode' => 'ctr') );
有关详细信息,请参阅配置库部分。
encrypt($data[, $params = NULL])
参数: | $ data(string) - 要加密$ params(数组)的数据 - 可选参数 |
---|---|
返回: | 加密数据或失败时为FALSE |
返回类型: | 串 |
$ data(string) - 要加密的数据
$ params(array) - 可选参数
返回:加密的数据或失败时的FALSE
返回类型:字符串
加密输入数据并返回其密文。
例:
$ciphertext = $this->encryption->encrypt('My secret message');
有关可选参数的信息,请参阅使用自定义参数部分。
decrypt($data[, $params = NULL])
参数: | $ data(string) - 解密$ params(array)的数据 - 可选参数 |
---|---|
返回: | 解密数据或失败时失败 |
返回类型: | 串 |
$ data(string) - 要解密的数据
$ params(array) - 可选参数
返回:解密的数据或失败时的FALSE
返回类型:字符串
解密输入数据并以纯文本形式返回。
例:
echo $this->encryption->decrypt($ciphertext);
有关可选参数的信息,请参阅使用自定义参数secrion。
create_key($length)
参数: | $ length(int) - 输出长度 |
---|---|
返回: | 具有指定长度的伪随机加密密钥,或失败时为FALSE |
返回类型: | 串 |
$ length(int) - 输出长度
返回:具有指定长度的伪随机加密密钥,或失败时为FALSE
返回类型:字符串
通过从操作系统的源中获取随机数据(即/ dev / urandom)创建加密密钥。
hkdf($key[, $digest = 'sha512'[, $salt = NULL[, $length = NULL[, $info = '']]]])
参数: | $ key(字符串) - 输入密钥材料$ digest(字符串) - 一个SHA-2家族摘要算法$ salt(string) - 可选salt $ length(int) - 可选输出长度$ info(字符串) - 可选上下文/具体信息 |
---|---|
返回: | 伪随机密钥或FALSE失败 |
返回类型: | 串 |
$ key(字符串) - 输入密钥材料
$ digest(字符串) - 一个SHA-2家族摘要算法
$salt(字符串) - 可选盐
$ length(int) - 可选输出长度
$ info(字符串) - 可选的上下文/特定于应用程序的信息
返回:失败时的伪随机密钥或FALSE
返回类型:字符串
从另一个推导出一个密钥,推测是较弱的密钥。
此方法在内部用于从您配置的encryption_key派生加密和HMAC密钥。
由于其他一般目的,它是公开可用的。它在RFC 5869中有描述。
但是,与RFC 5869中的描述相反,此实现不支持SHA1。
例:
$hmac_key = $this->encryption->hkdf( $key, 'sha512', NULL, NULL, 'authentication' ); // $hmac_key is a pseudo-random key with a length of 64 bytes