我对此代码的问题很少:
<?php
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "This is a very secret key";
$text = file_get_contents('path/to/your/file');
echo strlen($text) . "\n";
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv);
file_put_contents('path/to/your/file', $crypttext);
?>
它对文件加密很好,但是它最后添加了额外的空值,所以如果我加密:
a test string is this one
and here is a new line
解密成为:
a test string is this one
and here is a new line 000000000000000
发生了什么事?
其次,MCRYPT_RIJNDAEL_256
是否与AES-128
兼容?
最后,我如何让另一方解密我加密的文件?他们需要知道使用了哪种加密技术,我不知道该告诉他们什么。
答案 0 :(得分:7)
我要解释的大部分内容都可以从@ircmaxwell优秀的幻灯片中收集:Cryptography For The Average Developer你应立即查看。我将重申他的一个要点:避免编写处理加密/解密的代码。除非您了解所有因素,否则您可能会对其进行处理。
Advanced Encryption Standard由国家标准与技术研究所创建。 NIST从competitive pool of cryptographic experts中选择 Rijandael密码。
密钥大小是指用于加密/解密的密码长度。 256位密钥是32个字节,大约32个字符。
阻止大小是block ciphers(即所有AES候选者)的属性,它会在密码过程中将数据分块为特定大小。
模式是一个重要元素。
ECB 和 CBC 模式将您的明文填充到块大小中。如果您使用128位块大小加密1字节数据,则将获得15个空字节。填充打开了padding oracle attack的可能性。
超越填充ECB不会使用初始化向量(IV),让您向a potential vulnerability开放:偏好 CBC 或 CFB 模式。
您可以使用 CFB模式 which does not need padding来避免这两个问题,因此不需要进行解密后修剪。
创建IV时,您需要加密密码随机来源:MCRYPT_RAND
不够随机 - 首选MCRYPT_DEV_RANDOM
或MCRYPT_DEV_URANDOM
。
$iv_size = mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_128,
MCRYPT_MODE_CFB
);
$iv = mcrypt_create_iv(
$iv_size,
MCRYPT_DEV_URANDOM
);
为了解密你的朋友需要知道:
MCRYPT_RIJNDAEL_128
MCRYPT_MODE_CFB
只有密钥需要保密。根据您的传输方法,您应考虑实施数据完整性检查,以确保密文数据未被篡改。再次,请参阅@ircmaxwell出色的幻灯片:Cryptography For The Average Developer,了解使用hash_hmac()
创建HMAC指纹的示例。
显而易见的是,所有这些运动部件的维护都很复杂。 小心踩。
Mcrypt给你其他cipher options。有些像DES一样不推荐。其他人是AES的候选人,如Blowfish,TwoFish和Serpent。 Rijandael是一个经过验证的经过验证的密码,recommended。
答案 1 :(得分:1)
MCRYPT_RIJNDAEL_128
是AES-128,MCRYPT_RIJNDAEL_256
是AES-256 - just another name:
[...]该标准包括三个区块 密码,AES-128,AES-192和AES-256, 从更大的收藏中采用 最初发表为Rijndael.originally出版为Rijndael。[...]
[...] Rijndael密码是由 两位比利时密码学家,琼 Daemen和Vincent Rijmen,和 他们提交给AES选择 处理。 Rijndael(发音为“Rhine dall“)是一个带有名字的文字游戏 两位发明家。[...]
在解密字符串末尾遇到的\x00
个字符是某些padding所需的block ciphers(ECB就是这样的分组密码)。 Mcyrpt
使用NULL
- 内部填充,如果输入数据需要填充到所需的块长度。还有其他填充模式可用(使用Mcyrpt
时必须用户编码),即PKCS7,ANSI X.923或ISO 10126. NULL
- 加密可能结束的二进制数据时填充有问题使用一个或多个\x00
字符,因为您无法检测数据的结束位置和填充开始 - 所提到的其他填充模式可以解决此类问题。如果您正在加密字符数据(字符串),则可以使用\x00
轻松删除尾随$data = trim($data, "\x00");
。
要解密您发送给消费者的数据,消费者需要知道IV(初始化向量)($iv
),使用的算法(MCRYPT_RIJNDAEL_256
/ AES-256),加密模式(ECB
),秘密加密密钥($key
)和使用的填充模式(NULL
- 填充)。 IV可以与加密数据一起传输,因为它不需要保密:
收件人必须知道IV 要加密的信息 能够解密它。这可以 通过多种方式确保: 传输IV与 密文,通过同意 事先在密钥交换期间或 握手,通过计算它 (通常是递增地),或者通过 测量电流等参数 时间(用于硬件认证 诸如RSA SecurID,VASCO等令牌 Digipass等),ID如发件人 和/或收件人的地址或ID,文件 ID,数据包,扇区或集群 数量等。许多变量都可以 合并或散列在一起, 取决于协议。取决于协议。
答案 2 :(得分:0)
MCRYPT_RIJNDAEL_128
相当于mcrypt中的AES-128。这在MCRYPT_RIJNDAEL_128
此处记录:http://mcrypt.sourceforge.net/