1

Javascript ( pidCrypt AES CBC )を使用して短い文字列を暗号化し、 PHP ( phpseclib Crypt_AES CBC ) を使用して復号化する必要があります。

さまざまなライブラリ間に非常に多くの非互換性があり (それらの多くを試しましたが、ドキュメントが不足しているため使用を開始できなかったものもあります)、それらを理解し、克服しようとして頭を悩ませています (現在の「標準」は単に互換性がありません)。デバッグをカバーしておらず、意味不明または単にfalse間違った使用法で a が返されます)。

pidCrypt AES CBC は、OpenSSL 互換のエンコーディングを使用していると述べています。

これまでのところ、pidCrypt からの出力が phpseclib で復号化されない理由がわかりません。

pidCrypt

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

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 モードの "Key Derivation: None" の例 (setPassword の代わりに setKey と setIV) も試しましたが、結果は同じでした。

phpseclib で上記の pidCrypt AES CBC 出力をデコードするにはどうすればよいですか?

また

上記の pidCrypt 出力を復号化できる phpseclib の代替手段はありますか (コード API があります。OpenSSL の使用例は許可されていません)。

Javascript セキュリティとネットワーク セキュリティに関する講義はご遠慮ください。これは、インターネット/ネットワーク スニッフィングから保護するためのものではありません。

4

2 に答える 2

2

OpenSSLを使用して復号化するためのphp.netのコメントで解決策を見つけ、OpenSSL部分を削除してphpseclibに置き換えました(これは、phpのmcrypt、または独自のソフトウェアのみの実装を使用します)。

require_once("Crypt/AES.php");

//https://www.pidder.com/pidcrypt/?page=demo_aes-cbc
//"U2FsdGVkX18KqDRV4bSqJCauxP7004rQmPu3HD1FUrgbXEGpjJAKAfgYvxtWJ6iJ"
//Used the password: "password".
var_export(pidCryptAESCBCDecrypt("U2FsdGVkX18KqDRV4bSqJCauxP7004rQmPu3HD1FUrgbXEGpjJAKAfgYvxtWJ6iJ", "password"));
//Outputs: "Some text to encrypt..."

function pidCryptAESCBCDecrypt($strBase64OpenSSLCompatibleCipher, $strPassword)
{
    $data=base64_decode($strBase64OpenSSLCompatibleCipher);
    $salt=substr($data, 8, 8);
    $ct=substr($data, 16);

    /**
    * From https://github.com/mdp/gibberish-aes
    *
    * Number of rounds depends on the size of the AES in use
    * 3 rounds for 256
    *        2 rounds for the key, 1 for the IV
    * 2 rounds for 128
    *        1 round for the key, 1 round for the IV
    * 3 rounds for 192 since it's not evenly divided by 128 bits
    */

    $rounds = 3;
    $data00 = $strPassword.$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);


    $aes=new Crypt_AES(CRYPT_AES_MODE_CBC);
    $aes->setKey($key);
    $aes->setIV($iv);
    echo $aes->decrypt($ct);
}

更新: さらに単純に (私がそれを見なかったなんて信じられない)、 phpseclib に送信pidCryptUtil.encodeBase64(aes.pidcrypt.getParams().encryptOut)aes.pidcrypt.getParams().ivaes.pidcrypt.getParams().key.

于 2012-10-04T17:22:58.353 に答える
2

OKAY 、頭をひっかき、壁に叩きつけた後、最終的に両方の方法で機能する解決策を得ることができたと思いますが、それでも奇妙な異常に遭遇し、実際に何か間違ったことをしているのかどうかを知りたい. 私が達成しようとしてきたのは、AES 256 で PHP の文字列を暗号化し (MCrypt だけを使用してこれを行いたかったのですが、悲しいかな)、PidCrypt (JQuery) を使用して同じ文字列を復号化する機能です。このスレッドを発見するまで、自分のニーズに合ったソリューションを見つけることはほとんど不可能でした。

しかし、DECRYPT関数の実装に成功した後でも(Crypt_AES PHPライブラリとopenssl_decrypt/encryptの両方を使用して)、PHPで暗号化されたPidCryptのメッセージを適切に復号化できませんでした。

これが私が持っているものです(https://sourceforge.net/projects/pidcrypt/のAESデモページを使用して、 PidCrypt - 256 AESを介してメッセージを暗号化/復号化していることに注意してください)。

これは私のために働くPHPコードです:

//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);
}

、誰かが追加の文字を含める必要がある理由を教えてください。それが何であれ、暗号化する $data の最後に追加する必要があります。 PidCrypt サイトでは、追加の文字 (私の場合は改行) を含めていない場合、暗号化された文字列の最後の文字が切り取られますか?

何か悪いことをしていない限り、キャラクターを追加しても大丈夫です。PHP と PidCrypt の間のバグである場合は、動作する限りそのままにしておきます...

于 2012-12-14T06:23:54.437 に答える