简体   繁体   English

如何在PHP类上修复mcrypt字符长度

[英]How to fix mcrypt character length on PHP Class

I'm here to explain my website and show the "bug" or "error" that appears to my web. 我在这里解释我的网站,并显示出现在我的网站上的“错误”或“错误”。

Some days ago I did a page, the topic is encrypt and decrypt with AES, using the php class called "mcrypt". 几天前,我做了一个页面,主题是使用称为“ mcrypt”的php类通过AES进行加密和解密。

Here's a screenshot: 这是屏幕截图:

Fist Image 拳头形象

The problem is: the page only allow me to put a key length of "16, 24 or 32" characters. 问题是:该页面只允许我输入长度为“ 16、24或32”个字符的密钥。

So when I choose another character length it appears an error. 因此,当我选择另一个字符长度时,会出现一个错误。 Example: If I choose a 8 key character length it appears: 示例:如果我选择8键字符长度,则会出现:

Error or Bug that I want to fix 我要修复的错误或错误

I was searching on internet and I found that I have to pad with "\\0" 我在互联网上搜索时,发现必须用“ \\ 0”填充

I found this 我找到了这个

But I wonder, where exacly do this. 但是我不知道在哪里可以做到这一点。

Here's the php class: 这是php类:

<?php

class AES {

    const M_CBC = 'cbc';
    const M_CFB = 'cfb';
    const M_ECB = 'ecb';
    const M_NOFB = 'nofb';
    const M_OFB = 'ofb';
    const M_STREAM = 'stream';

    protected $key;
    protected $cipher;
    protected $data;
    protected $mode;
     protected $IV;

    /**
     * 
     * @param type $data
     * @param type $key
     * @param type $blockSize
     * @param type $mode
     */
    function __construct($data = null, $key = null, $blockSize = null, $mode = null) {
        $this->setData($data);
        $this->setKey($key);
        $this->setBlockSize($blockSize);
        $this->setMode($mode);
        $this->setIV("");
    }

    /**
     * 
     * @param type $data
     */
    public function setData($data) {
        $this->data = $data;
    }

    /**
     * 
     * @param type $key
     */
    public function setKey($key) {
        $this->key = $key;
    }

    /**
     * 
     * @param type $blockSize
     */
    public function setBlockSize($blockSize) {
        switch ($blockSize) {
            case 128:
                $this->cipher = MCRYPT_RIJNDAEL_128;
                break;

            case 192:
                $this->cipher = MCRYPT_RIJNDAEL_192;
                break;

            case 256:
                $this->cipher = MCRYPT_RIJNDAEL_256;
                break;
        }
    }

    /**
     * 
     * @param type $mode
     */
    public function setMode($mode) {
        switch ($mode) {
            case AES::M_CBC:
                $this->mode = MCRYPT_MODE_CBC;
                break;
            case AES::M_CFB:
                $this->mode = MCRYPT_MODE_CFB;
                break;
            case AES::M_ECB:
                $this->mode = MCRYPT_MODE_ECB;
                break;
            case AES::M_NOFB:
                $this->mode = MCRYPT_MODE_NOFB;
                break;
            case AES::M_OFB:
                $this->mode = MCRYPT_MODE_OFB;
                break;
            case AES::M_STREAM:
                $this->mode = MCRYPT_MODE_STREAM;
                break;
            default:
                $this->mode = MCRYPT_MODE_ECB;
                break;
        }
    }

    /**
     * 
     * @return boolean
     */
    public function validateParams() {
        if ($this->data != null &&
                $this->key != null &&
                $this->cipher != null) {
            return true;
        } else {
            return FALSE;
        }
    }

     public function setIV($IV) {
        $this->IV = $IV;
    }

     protected function getIV() {
    if ($this->IV == "") {
        $this->IV = mcrypt_create_iv(mcrypt_get_iv_size($this->cipher, $this->mode), MCRYPT_RAND);
    }
        return $this->IV;
    }

    /**
     * @return type
     * @throws Exception
     */
    public function encrypt() {

        if ($this->validateParams()) {
            return trim(base64_encode(
                            mcrypt_encrypt(
                                    $this->cipher, $this->key, $this->data, $this->mode, $this->getIV())));
        } else {
            throw new Exception('Invlid params!');
        }
    }

    /**
     * 
     * @return type
     * @throws Exception
     */
    public function decrypt() {
        if ($this->validateParams()) {
            return trim(mcrypt_decrypt(
                            $this->cipher, $this->key, base64_decode($this->data), $this->mode, $this->getIV()));
        } else {
            throw new Exception('Invlid params!');
        }
    }

}

I also found this, I think could be the solution 我也发现了这一点,我认为可能是解决方案

function pad_key($key){
    // key is too large
    if(strlen($key) > 32) return false;

    // set sizes
    $sizes = array(16,24,32);

    // loop through sizes and pad key
    foreach($sizes as $s){
        while(strlen($key) < $s) $key = $key."\0";
        if(strlen($k) == $s) break; // finish if the key matches a size
    }

    // return
    return $key;
}

Maybe this last one is the fix, by the way, I'm a little amateur with php. 也许这最后一个是解决方法,顺便说一句,我对php有点业余。

Thanks to everyone! 谢谢大家! Hope u can help me. 希望你能帮助我。

An AES key has a specific key size. AES密钥具有特定的密钥大小。 If you want to use a different size, then you're likely using passwords instead of keys. 如果要使用其他大小,则可能使用密码而不是密钥。 Please don't confuse them. 请不要混淆他们。 A password can be easily remembered. 密码很容易记住。 A key is supposed to be chosen randomly and should look like random noise. 密钥应该是随机选择的,看起来应该像随机噪声。 You need to use a password-based key derivation function like PBKDF2. 您需要使用基于密码的密钥派生功能,例如PBKDF2。


Keep in mind that mcrypt will be removed in PHP 7.2. 请记住,mcrypt将在PHP 7.2中删除。 It is abandonware and should not be used anymore. 它是一种废弃软件,不应再使用。

There's a lot of issues with the code you've shown, too many to explain in a single answer. 您显示的代码有很多问题,太多的问题无法在一个答案中解释。 The TL;DR is: TL; DR为:

  1. Don't use mcrypt, it's abandonware. 不要使用mcrypt,它是废弃软件。
  2. Don't roll your own crypto. 不要推出自己的加密货币。 Instead, use a well-vetted library that will handle everything for you. 相反,请使用经过严格审查的库来为您处理所有事情。

I know this isn't the answer you were expecting, but I assure you - every expert in the field would echo it. 我知道这不是您所期望的答案,但我向您保证-该领域的每位专家都将予以回应。
Cryptography is very complex, very easy to screw up, and certainly not a generic programming problem. 密码学非常复杂,很容易搞砸,当然也不是一般的编程问题。 That's just the way it is. 就是那样子。

That being said, here's the obviously incorrect: 话虽如此,这显然是不正确的:

AES is only a subset of Rijndael ... AES只是Rijndael的一个子集...

AES-128 is Rijndael-128 with a 128-bit (16-byte) key AES-128是Rijndael-128,具有128位(16字节)密钥
AES-256 is Rijndael-128 with a 256-bit (32-byte) key AES-256是Rijndael-128,具有256位(32字节)密钥
Rijndael-192 and Rijndael-256 are NOT AES! Rijndael-192和Rijndael-256 不是 AES!

And that also hints at the answer to what you asked - you can't use arbitrary key sizes; 这也暗示了您所要求的答案-您不能使用任意密钥大小; just the 16 or 32 bytes, depending on which AES variation you want. 仅16或32个字节,具体取决于您想要的AES变体形式。

Padding with zero bytes may hide the error message, but that's because you're tricking mcrypt into thinking that you're giving it a proper key, while you are in fact not - this doesn't help you, don't do it. 用零字节填充可能会隐藏错误消息,但这是因为您在欺骗 mcrypt认为您给了它正确的密钥,而实际上却并非如此-这无济于事,请不要这样做。

Again, if you're building something for real-world usage - don't roll your own. 同样,如果您要构建用于实际用途的东西-不要自己动手。 But if you're in it only for the learning experience, here's a fairly good resource to point you in the right direction: http://timoh6.github.io/2014/06/16/PHP-data-encryption-cheatsheet.html 但是,如果您只是出于学习经验而来,那么这里是一个相当不错的资源,可为您指明正确的方向: http : //timoh6.github.io/2014/06/16/PHP-data-encryption-cheatsheet。 html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM