【问题标题】:Warning: mcrypt_generic_init(): Iv size is incorrect警告:mcrypt_generic_init():IV 大小不正确
【发布时间】:2014-06-15 06:10:22
【问题描述】:

我正在尝试制作一个 PHP AES 解密器,但它不起作用。

现在我有这个代码:

<?php

require_once('padCrypt.php');
require_once('AES_Encryption.php');

$key              = "1234567890123456";
$iv               = "";
$padding          = "ZERO";
$mode             = "ecb";
$message          = "dlQO04ftNjSgj/XNdLmz29MtqB1wK15/5E9wpfIenvWkkYXkK/BMCuUKjIyPUvcUFVJpxyJDit6EiiO4l0KifXu/9Y4LB26OzfV4DRsTWL1civllo07Wicw7tlQiUcmu";

$AES              = new AES_Encryption($key, $iv, $padding, $mode);
$decrypted        = $AES->decrypt($message);

echo $decrypted;
?>

返回此错误:

警告:mcrypt_generic_init() [function.mcrypt-generic-init]: Iv 大小 不正确;提供长度:0,需要:16 英寸 /var/www/krellers.dk/public_html/tester/AES_Encryption.php 在第 152 行

有人可以帮我理解为什么会出现这个错误,尽管 ECB 明确指出 iv 应该是空字符串、null 等。

我使用的示例和库来自:http://www.coderelic.com/2011/10/aes-256-encryption-with-php/

AES_Encryption.php 文件:

<?php

/***
 * AES_Encryption
 * This class allows you to easily encrypt and decrypt text in AES format
 * The class automatically determines whether you need 128, 192, or 256 bits
 * based on your key size. It handles multiple padding formats.
 * 
 * Dependencies:
 * This class is dependent on PHP's mcrypt extension and a class called padCrypt
 * 
 * Information about mcrypt extension is at:
 * http://us.php.net/mcrypt
 * 
 * padCrypt class is published at:
 * http://dev.strategystar.net/2011/10/php-cryptography-padding-ansi-x-923-iso-10126-pkcs7-bit-zero/
 * 
 * The padCrypt class provides methods for padding strings with the 
 * common methods described at:
 * http://en.wikipedia.org/wiki/Padding_%28cryptography%29
 * 
 * -- AES_Encryption Information
 * 
 * Key Sizes:
 * 16 bytes = 128 bit encryption
 * 24 bytes = 192 bit encryption
 * 32 bytes = 256 bit encryption
 * 
 * Padding Formats:
 * ANSI_X.923
 * ISO_10126
 * PKCS7
 * BIT
 * ZERO
 * 
 * The default padding method in this AES_Encryption class is ZERO padding
 * ZERO padding is generally OK for paddings in messages because 
 * null bytes stripped at the end of a readable message should not hurt
 * the point of the text. If you are concerned about message integrity, 
 * you can use PKCS7 instead
 * 
 * This class does not generate keys or vectors for you. You have to 
 * generate them yourself because you need to keep track of them yourself 
 * anyway in order to decrypt AES encryptions.
 * 
 * -- Example Usage:
 * 
 * $key     = "bac09c63f34c9845c707228b20cac5e0";
 * $iv      = "47c743d1b21de03034e0842352ae6b98";
 * $message = "Meet me at 11 o'clock behind the monument.";
 * 
 * $AES              = new AES_Encryption($key, $iv);
 * $encrypted        = $AES->encrypt($message);
 * $decrypted        = $AES->decrypt($encrypted);
 * $base64_encrypted = base64_encode($encrypted);
 * 
 * -- Credits:
 * 
 * @author Strategy Star Inc.
 * @website http://www.strategystar.net
 **/

class AES_Encryption
{
    private $key, $initVector, $mode, $cipher, $encryption = null;
    private $allowed_bits = array(128, 192, 256);
    private $allowed_modes = array('ecb', 'cfb', 'cbc', 'nofb', 'ofb');
    private $vector_modes = array('cbc','cfb','ofb');
    private $allowed_paddings = array(
        'ANSI_X.923' => 'ANSI_X923',
        'ISO_10126'  => 'ISO_10126',
        'PKCS7'      => 'PKCS7',
        'BIT'        => 'BIT',
        'ZERO'       => 'ZERO',
    );

    private $padCrypt_url   = 'http://dev.strategystar.net/2011/10/php-cryptography-padding-ansi-x-923-iso-10126-pkcs7-bit-zero/';
    private $aesEncrypt_url = 'http://dev.strategystar.net/';

    /***
     * String $key        = Your secret key that you will use to encrypt/decrypt
     * String $initVector = Your secret vector that you will use to encrypt/decrypt if using CBC, CFB, OFB, or a STREAM algorhitm that requires an IV
     * String $padding    = The padding method you want to use. The default is ZERO (aka NULL byte) [ANSI_X.923,ISO_10126,PKCS7,BIT,ZERO]
     * String $mode       = The encryption mode you want to use. The default is cbc [ecb,cfb,cbc,stream,nofb,ofb]
     **/
    public function __construct($key, $initVector='', $padding='ZERO', $mode='cbc')
    {
        $mode = strtolower($mode);
        $padding = strtoupper($padding);

        if(!class_exists('padCrypt'))
        {
            throw new Exception('The padCrypt class must be loaded for AES_Encryption to work: '.$padCrypt_url);
        }

        if(!function_exists('mcrypt_module_open'))
        {
            throw new Exception('The mcrypt extension must be loaded.');
        }

        if(strlen($initVector) != 16 && in_array($mode, $this->vector_modes))
        {
            throw new Exception('The $initVector is supposed to be 16 bytes in for CBC, CFB, NOFB, and OFB modes.');
        }
        elseif(!in_array($mode, $this->vector_modes) && !empty($initVector))
        {
            throw new Exception('The specified encryption mode does not use an initialization vector. You should pass an empty string, zero, FALSE, or NULL.');
        }

        $this->encryption = strlen($key)*8;

        if(!in_array($this->encryption, $this->allowed_bits))
        {
            throw new Exception('The $key must be either 16, 24, or 32 bytes in length for 128, 192, and 256 bit encryption respectively.');
        }

        $this->key = $key;
        $this->initVector = $initVector;

        if(!in_array($mode, $this->allowed_modes))
        {
            throw new Exception('The $mode must be one of the following: '.implode(', ', $this->allowed_modes));
        }

        if(!array_key_exists($padding, $this->allowed_paddings))
        {
            throw new Exception('The $padding must be one of the following: '.implode(', ', $this->allowed_paddings));
        }

        $this->mode = $mode;
        $this->padding = $padding;
        $this->cipher = mcrypt_module_open('rijndael-128', '', $this->mode, '');
        $this->block_size = mcrypt_get_block_size('rijndael-128', $this->mode);
    }

    /***
     * String $text = The text that you want to encrypt
     **/
    public function encrypt($text)
    {
        mcrypt_generic_init($this->cipher, $this->key, $this->initVector);
        $encrypted_text = mcrypt_generic($this->cipher, $this->pad($text, $this->block_size));
        mcrypt_generic_deinit($this->cipher);
        return $encrypted_text;
    }

    /***
     * String $text = The text that you want to decrypt
     **/
    public function decrypt($text)
    {
        mcrypt_generic_init($this->cipher, $this->key, $this->initVector);
        $decrypted_text = mdecrypt_generic($this->cipher, $text);
        mcrypt_generic_deinit($this->cipher);
        return $this->unpad($decrypted_text);
    }

    /***
     * Use this function to export the key, init_vector, padding, and mode
     * This information is necessary to later decrypt an encrypted message
     **/
    public function getConfiguration()
    {
        return array(
            'key'           => $this->key,
            'init_vector'   => $this->initVector,
            'padding'       => $this->padding,
            'mode'          => $this->mode,
            'encryption'    => $this->encryption . ' Bit',
            'block_size'    => $this->block_size,
        );
    }

    private function pad($text, $block_size)
    {
        return call_user_func_array(array('padCrypt', 'pad_'.$this->allowed_paddings[$this->padding]), array($text, $block_size));
    }

    private function unpad($text)
    {
        return call_user_func_array(array('padCrypt', 'unpad_'.$this->allowed_paddings[$this->padding]), array($text));
    }

    public function __destruct()
    {
        mcrypt_module_close($this->cipher);
    }
}

padCrypt.php 文件:

<?php

/**
 * padCrypt.php
 * 
 * This class can be used to pad strings with the following methods:
 * ANSI X.923, ISO 10126, PKCS7, Zero Padding, and Bit Padding
 * 
 * The methods are implemented as documented at:
 * http://en.wikipedia.org/wiki/Padding_(cryptography)
 *
 * @author Strategy Star Inc.
 * @website http://www.strategystar.net
 */

class padCrypt
{
    public static function pad_ISO_10126($data, $block_size)
    {
        $padding = $block_size - (strlen($data) % $block_size);

        for($x=1; $x<$padding; $x++)
        {
            mt_srand();
            $data .= chr(mt_rand(0,255));
        }

        return $data . chr($padding);
    }

    public static function unpad_ISO_10126($data)
    {
        $length = ord(substr($data, -1));
        return substr($data, 0, strlen($data)-$length);
    }

    public static function pad_ANSI_X923($data, $block_size)
    {
        $padding = $block_size - (strlen($data) % $block_size);
        return $data . str_repeat(chr(0), $padding - 1) . chr($padding);
    }

    public static function unpad_ANSI_X923($data)
    {
        $length = ord(substr($data, -1));
        $padding_position = strlen($data) - $length;
        $padding = substr($data, $padding_position, -1);

        for($x=0; $x<$length; $x++)
        {
            if(ord(substr($padding, $x, 1)) != 0)
            {
                return $data;
            }
        }

        return substr($data, 0, $padding_position);
    }

    public static function pad_PKCS7($data, $block_size)
    {
        $padding = $block_size - (strlen($data) % $block_size);
        $pattern = chr($padding);        
        return $data . str_repeat($pattern, $padding);
    }

    public static function unpad_PKCS7($data)
    {
        $pattern = substr($data, -1);
        $length = ord($pattern);
        $padding = str_repeat($pattern, $length);
        $pattern_pos = strlen($data) - $length;

        if(substr($data, $pattern_pos) == $padding)
        {
            return substr($data, 0, $pattern_pos);
        }

        return $data;
    }

    public static function pad_BIT($data, $block_size)
    {
        $length = $block_size - (strlen($data) % $block_size) - 1;
        return $data . "\x80" . str_repeat("\x00", $length);
    }

    public static function unpad_BIT($data)
    {   
        if(substr(rtrim($data, "\x00"), -1) == "\x80")
        {
            return substr(rtrim($data, "\x00"), 0, -1);
        }

        return $data;
    }

    public static function pad_ZERO($data, $block_size)
    {
        $length = $block_size - (strlen($data) % $block_size);
        return $data . str_repeat("\x00", $length);
    }

    public static function unpad_ZERO($data)
    {
        return rtrim($data, "\x00");
    }
}

?>

【问题讨论】:

  • 我也试过这个: 那也不起作用,只是一个空白页。
  • 您的意思是使用return 而不是echo?如果您使用null 而不是$iv 的空字符串会发生什么?
  • 如果我使用 null,它会返回相同的错误。我也试过这个代码示例,它返回但没有正确的文本: $key = "1234567890123456"; echo mcrypt_decrypt('rijndael-128', $key, $data, 'ecb'); ?> 见 www.krellers.dk/tester/test2.php
  • 我已将其从返回更改为回显,现在给我:警告:mcrypt_generic_init() [function.mcrypt-generic-init]:IV 大小不正确;提供的长度:0,需要:16 在 /var/www/krellers.dk/public_html/tester/AES_Encryption.php 第 152 行 Õ³‰%EÛ{áÉj8ªÏ'áUÍ๽KT8–”¬ˆñ{¹`Œ„¶Ora}]d „…Ÿ-;c¤{«ß ƒ 78^žór‰áã]¹Q¬ÂÉL(”X®O*|½œ gFPü†ÿ´L...ÔËçéA¸.Vk%{°üCH·Í¡G¿Œv'¢
  • 请记住,要解密的原始消息看起来像是经过 base64 编码的,因此您可能需要先通过base64_decode() 传递它。

标签: php encryption aes


【解决方案1】:

根据上面的讨论,为了取回正确的数据,我怀疑您需要进行以下更改:

$decrypted = $AES->decrypt(base64_decode($message));

已编辑以修复 cmets 中指出的错误

【讨论】:

  • 我希望你不介意,结果是我试图拆分的 json 字符串,但是如果没有运气,我应该在 json_decode 之前做点什么吗? // 解码字符串 $dataFetched = $_GET['data']; $data = base64_decode($dataFetched); $key = "1234567890123456"; $decStr = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB);回声 $decStr; $obj = json_decode($decStr, TRUE);打印 obj->{'msisdn'};
  • $decStr 是否包含警告信息?如果是这样,那么json_decode() 函数将不起作用。
  • 不,它返回:{"msisdn":"22222222","hash":"b46ec1f3e919fadcfb3cf2b66658f383e34e45fb1d473badb98c731028515e25"}
  • 问题在于你告诉json_decode 返回一个关联数组而不是一个对象(这就是第二个参数的作用)。使用var_dump($obj)查看。
  • 好的,刚刚添加了它 - 它说:NULL。我现在删除了 TRUE。仍然 var_dump 返回 NUll 并且没有返回任何内容。这对我来说毫无意义。
猜你喜欢
  • 2016-10-15
  • 1970-01-01
  • 2017-10-15
  • 2023-03-26
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
相关资源
最近更新 更多