首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用原始的rijndael构建PHP扩展,但是正确的加密/解密会拖着额外的字节

使用原始的rijndael构建PHP扩展,但是正确的加密/解密会拖着额外的字节
EN

Stack Overflow用户
提问于 2017-06-16 14:09:35
回答 1查看 78关注 0票数 0

因此,我刚刚开始使用最初的Rijndael代码(现在是形式上的AES)编写PHP扩展。

然而,在代码中似乎有一个bug,我知道它正确地加密/解密,但是在输出中它为字符串增加了6个字节,我认为这与从uint8_t数组到char数组的转换有关。

我没有在这里发布代码,因为它占用了页面的一半,所以我在这里将其发布到github:

https://github.com/Hect0rius/PHPEXT-Rijndael

我所指的主要代码是php_rijndael.c (2个函数)中的以下代码:

代码语言:javascript
复制
    /* {{{ proto resource rijndael_encrypt(string inData, string key)

使用rijndael / PHP_FUNCTION(rijndael_encrypt) {/inData */ char *inData;// Data加密字符串。size_t inDataLen;//数据长度。char * Key;// Key Ptr.size_t keyLen;// Key长度。zend_ulong keyBits;// Bits,介于128/192/256之间。

代码语言:javascript
复制
        /* Get Parameters from Zend */
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s|l", &inData, &inDataLen, &key, &keyLen, &keyBits) == FAILURE) {
        return;
        }

        /* Since rijndael takes what it needs via key bits, then we just allow the overflow of the key. */
        switch(keyBits) {
            case 128:
                if(keyLen < 16) { php_error_docref(NULL, E_WARNING, "Key length must be 16 characters long."); RETURN_FALSE; }
                break;
            case 192:
                if(keyLen < 24) { php_error_docref(NULL, E_WARNING, "Key length must be 24 characters long."); RETURN_FALSE; }
                break;
            case 256:
                if(keyLen < 32) { php_error_docref(NULL, E_WARNING, "Key length must be 32 characters long."); RETURN_FALSE; }
                break;
        }

        /* Convert from original pointers to uin8_t arrays */
        uint8_t dataU8[16];
        uint8_t keyU8[16];
        uint8_t output[16],  i = 0;
        do {
            dataU8[i] = (uint8_t)inData[i];
            keyU8[i] = (uint8_t)key[i];
            i++;
        }
        while(i < 16);

        /* Setup Rijndael stack */
        uint32_t rk[4 * (MAXNR + 1)];
        int32_t Nr = rijndaelKeySetupEnc(rk, keyU8, keyBits);

        /* Decrypt Buffer. */
        rijndaelEncrypt(rk, Nr, dataU8, output);

        /* Now return data back into a char array*/
        char outChar[16], *ptr = outChar;
        i = 0;
        do {
            ptr[i] = (char)output[i];
            i++;
        }
        while(i < 16);
        RETURN_STRING(outChar);
    }
    /* }}} */

    /* {{{ proto resource rijndael_decrypt(string inData, string key)

用rijndael / PHP_FUNCTION(rijndael_decrypt) {/inData */ char *inData;// Data Ptr解密字符串。size_t inDataLen;//数据长度。char * Key;// Key Ptr.size_t keyLen;// Key长度。zend_ulong keyBits;// Bits,介于128/192/256之间。

代码语言:javascript
复制
        /* Get Parameters from Zend */
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s|l", &inData, &inDataLen, &key, &keyLen, &keyBits) == FAILURE) {
        return;
        }

        /* Since rijndael takes what it needs via key bits, then we just allow the overflow of the key. */
        switch(keyBits) {
            case 128:
                if(keyLen < 16) { php_error_docref(NULL, E_WARNING, "Key length must be 16 characters long."); RETURN_FALSE; }
                break;
            case 192:
                if(keyLen < 24) { php_error_docref(NULL, E_WARNING, "Key length must be 24 characters long."); RETURN_FALSE; }
                break;
            case 256:
                if(keyLen < 32) { php_error_docref(NULL, E_WARNING, "Key length must be 32 characters long."); RETURN_FALSE; }
                break;
        }

        /* Convert from original pointers to uin8_t arrays */
        uint8_t dataU8[16];
        uint8_t keyU8[16];
        uint8_t output[16],  i = 0;
        do {
            dataU8[i] = (uint8_t)inData[i];
            keyU8[i] = (uint8_t)key[i];
            i++;
        }
        while(i < 16);

        /* Setup Rijndael Stack */
        uint32_t rk[4 * (MAXNR + 1)];
        int32_t Nr = rijndaelKeySetupDec(rk, keyU8, keyBits);

        /* Decrypt input uint8_t array */
        rijndaelDecrypt(rk, Nr, dataU8, output);

        /* Convert data back to a char */
        char outChar[16], *ptr = outChar;
        i = 0;
        do {
            ptr[i] = (char)output[i];
            i++;
        }
        while(i < 16);
        RETURN_STRING(ptr);
    }
    /* }}} */

    #endif /* HAVE_RIJNDAEL */

我只猜它正确地解密了加密的缓冲区,因为它输出到所有的零,下面是test.php文件:

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-16 14:59:10

你看到的是垫子。

AES (和Rijndael)是块密码,因此是以块为单位的处理数据,对于AES来说是16字节。

如果输入不是块大小的确切倍数,则需要在解密时将一些填充添加到要加密和删除的数据中。最常见的填充是PKCS#7,但是有些实现是脑死亡的,不支持PKCS#7,有时使用空填充,它不支持加密二进制数据。

注意: PHP mcrypt实现不支持标准PKCS#7 (née PKCS#5)填充,只支持不能与二进制数据一起使用的非标准空填充。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44591397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档