为mcrypt选择加密密码

时间:2010-11-08 22:01:09

标签: php encryption

我对此代码的问题很少:

<?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兼容?

最后,我如何让另一方解密我加密的文件?他们需要知道使用了哪种加密技术,我不知道该告诉他们什么。

3 个答案:

答案 0 :(得分:7)

我要解释的大部分内容都可以从@ircmaxwell优秀的幻灯片中收集:Cryptography For The Average Developer你应立即查看。我将重申他的一个要点:避免编写处理加密/解密的代码。除非您了解所有因素,否则您可能会对其进行处理。


MCRYPT_RIJNDAEL_128与AES

紧密匹配

Advanced Encryption Standard由国家标准与技术研究所创建。 NIST从competitive pool of cryptographic experts中选择 Rijandael密码

常见的混淆:AES和Mycrpt中的数字指的是不同的东西

  • AES-128指 128位密钥大小
  • AES-256指 256位密钥大小
  • MCRYPT_RIJNDAEL_128是指 128位密码块
  • MCRYPT_RIJNDAEL_256是指 256位密码块大小

密钥大小和块大小

密钥大小是指用于加密/解密的密码长度。 256位密钥是32个字节,大约32个字符。

阻止大小block ciphers(即所有AES候选者)的属性,它会在密码过程中将数据分块为特定大小。

  • AES指定128位密码块
  • Mcrypt的Rijndaels都接受256位密钥
  • 基于键/块大小MCRYPT_RIJNDAEL_128似乎最接近AES-256
    • 还有其他因素需要考虑 - 比如有多少次转型? - 如果不深入研究源代码,很难验证这方面的内容

操作模式

模式是一个重要元素。

ECB CBC 模式将您的明文填充到块大小中。如果您使用128位块大小加密1字节数据,则将获得15个空字节。填充打开了padding oracle attack的可能性。

超越填充ECB不会使用初始化向量(IV),让您向a potential vulnerability开放:偏好 CBC CFB 模式。

您可以使用 CFB模式 which does not need padding来避免这两个问题,因此不需要进行解密后修剪。

初始化向量(IV)

创建IV时,您需要加密密码随机来源:MCRYPT_RAND不够随机 - 首选MCRYPT_DEV_RANDOMMCRYPT_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
  • IV - 您加密的每个元素都应该获得唯一的IV,因此您需要将IV附加到加密数据
  • 密钥 - 这是秘密的,并且应该对所有加密保持不变;如果您的密钥被泄露,请将其旋转

只有密钥需要保密。根据您的传输方法,您应考虑实施数据完整性检查,以确保密文数据未被篡改。再次,请参阅@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/