首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用pidCrypt加密AES CBC,然后用phpseclib解密?

如何使用pidCrypt加密AES CBC,然后用phpseclib解密?
EN

Stack Overflow用户
提问于 2012-10-04 15:34:43
回答 1查看 2.9K关注 0票数 1

我需要使用Javascript (pidCrypt AES CBC)加密一个短字符串,然后使用PHP (AES CBC)解密它。

各种库之间存在着太多的不兼容(尝试了其中的许多,有些由于缺乏文档而无法开始使用),以至于我无法理解和克服它们(当前的“标准”只是不包括调试,或者只是一个错误使用的false )。

pidCrypt AES CBC表示,它正在使用OpenSSL兼容的编码。

到目前为止,我不明白为什么来自pidCrypt的输出不会在phpseclib中被解密:

pidCrypt

代码语言:javascript
复制
var aes=new pidCrypt.AES.CBC();
aes.encryptText("abcdefg", "secret", {nBits: 128});

console.log(aes.pidcrypt.getParams());
/**
A0_PAD: true
UTF8: true
blockSize: 16
clear: true
dataIn: "abcdefg"
dataOut: "U2FsdGVkX19p8dJctoZSgamat+UBHMWM/Zx64fBDYJY="
decryptIn: ""
decryptOut: ""
encryptIn: Array[16]
encryptOut: "©·åÅýzáðC`"
iv: "e314f8ebbcc5a1e0ae6c27033dd6725f"
key: "49f9bd99b7952b68b3bfa47404455fa7"
nBits: 128
salt: "69f1d25cb6865281"
*/

phpseclib

代码语言:javascript
复制
function hex2raw($strHexString)
{
    $strRawBytes="";
    $arrChunks=str_split($strHexString, 2);
    for($i=0; $i<count($arrChunks); $i++)
        $strRawBytes.=chr(hexdec($arrChunks[$i]));
    return $strRawBytes;
}

require_once("Crypt/AES.php");

$aes=new Crypt_AES(CRYPT_AES_MODE_CBC);

$aes->setPassword("secret");
$aes->setIV(hex2raw("e314f8ebbcc5a1e0ae6c27033dd6725f"));

var_export($aes->decrypt(base64_decode("U2FsdGVkX19p8dJctoZSgamat+UBHMWM/Zx64fBDYJY=")));
/**
false
*/

我还尝试了phpseclib AES CBC模式“键派生:无”示例(setKey和setIV而不是setPassword),结果相同。

如何使phpseclib解码上述pidCrypt AES CBC输出?

是否可以替代phpseclib来解密上面的pidCrypt输出(其中有一个代码API;不允许OpenSSL使用示例)?

请不要讲授Javascript安全和网络安全。这并不是为了防止互联网/网络嗅探。

EN

回答 1

Stack Overflow用户

发布于 2012-12-14 06:23:54

我想我终于找到了一个双向解决方案,但我还是遇到了一种奇怪的反常现象,我想看看我是否真的做错了什么。我一直在努力实现的是,在PHP中实现AES 256加密字符串的功能(我只想使用MCrypt,但可惜),然后使用PidCrypt (JQuery)解密相同的字符串。在我发现这条线之前,几乎不可能找到适合我需求的解决方案。

但是即使成功地实现了解密函数(使用Crypt_AES库,也只使用openssl_Crypt_AES/encrypt),我仍然无法正确地解密已经用PHP加密的PidCrypt中的消息。

下面是我得到的(请注意,我一直在使用https://sourceforge.net/projects/pidcrypt/的AES演示页面通过PidCrypt - 256 AES加密/解密消息)。

这是适用于我的PHP代码:

代码语言:javascript
复制
//for those who can't use openssl_encrypt because they don't have PHP >= 5.3.X
//the only solution I've found is to install phpseclib.sourceforge.net/crypt
require_once("Crypt/AES.php");

echo decrypt('TEST', 'U2FsdGVkX1/yPcPIrEGSGvkII+qMeyrOY+l3t09Gylc1td80g0VFtzRw1MbjYJZ3I1JJOW9G6wMlUxpu2gjHq68fwxo3Bds+PlpCnjgDBwL+VZe8QSOwS/CMPh9A+cOkyGQ+fCNp/KnKwgkqTziCpSWjgbFSlcOHtMWPoy1ecMM+CjhzyUZQ6SfJs+K8x9tj');
echo '<br />';
echo encrypt('TEST', 'TESTING RANDOM DATA PLEASE EXPLAIN WHY I HAVE TO PUT AN ADDITIONAL BYTE ON THE END OF THE DATA TO DECRYPT THE ORIGINAL STRING?');

function decrypt($password, $edata) {
    $data = base64_decode($edata);
    $salt = substr($data, 8, 8);
    $ct = substr($data, 16);
    $rounds = 3;
    $data00 = $password . $salt;
    $md5_hash = array();
    $md5_hash[0] = md5($data00, true);
    $result = $md5_hash[0];
    for($i = 1; $i < $rounds; $i++) {
      $md5_hash[$i] = md5($md5_hash[$i - 1] . $data00, true);
        $result .= $md5_hash[$i];
    }
    $key = substr($result, 0, 32);
    $iv  = substr($result, 32, 16);

    //phpseclib specifics
    $aes = new Crypt_AES(CRYPT_AES_MODE_CBC);
    $aes->setKey($key);
    $aes->setIV($iv);
    return $aes->decrypt($ct);

    //instead of using phpseclib with openssl_decrypt you would do the following
    //return openssl_decrypt($ct, 'aes-256-cbc', $key, true, $iv);
}

function encrypt($password, $data) {
    //my randomly generated 8 byte salt
    $salt = substr(time(), -8);
    //alternatively with openssl you would use
    //$salt = openssl_random_pseudo_bytes(8);
    $salted = '';
    $dx = '';
    while(strlen($salted) < 48) {
      $dx = md5($dx . $password . $salt, true);
      $salted .= $dx;
    }
    $key = substr($salted, 0, 32);
    $iv  = substr($salted, 32, 16);

    //phpseclib specifics
    $aes = new Crypt_AES(CRYPT_AES_MODE_CBC);
    $aes->setKey($key);
    $aes->setIV($iv);
    $encrypted_data = $aes->encrypt($data . "\n");

    //alternatively with openssl you would do the following
    //$encrypted_data = openssl_encrypt($data . "\n", 'aes-256-cbc', $key, true, $iv);

    return base64_encode('Salted__' . $salt . $encrypted_data);
}

NOW请告诉我为什么我必须增加一个字符,不管它是什么,只需要添加到要加密的$data末尾,否则当我去解密PidCrypt站点上的字符串时,如果我没有包含额外的字符(这是我的情况是换行符),那么它会切断加密字符串的最后一个字符吗?

只要我没有做错事,我就可以多加一个角色。如果它是PHP和PidCrypt之间的一个bug,那么只要它正常工作,我就不会管它.

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

https://stackoverflow.com/questions/12730761

复制
相关文章

相似问题

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