3

iOS 5.x の CommonCrypto ライブラリで暗号化された文字列を PHP で復号化するのに問題があります。パラメータは次のとおりです。

Algorithm: AES-128
Mode: CTR
Mode options: CTR Little-Endian
Padding: None

これが私の最善の試みのサンプルです。

<?php
$encrypted = base64_decode('MlNFlnXE1sqIsmKZRtjChBvUMgiJlXgdjHVxQJ6JK24Id4uaN9NK/nBtY+cgrMJR/PRJRCmIUx0boQO5XqJYZ8VJ0w==');
$key = base64_decode('HB+dD1Irj2rXQ/nO+IuqSiK9xVE3PD9cZGIGzrMtwtA=');
$iv = base64_decode('2gxxKYU/G4lj7174e5wj+g==');

$cryptor = mcrypt_module_open('rijndael-128', '', 'ctr', '');
mcrypt_generic_init($cryptor, $key, $iv);
echo mdecrypt_generic($cryptor, $encrypted);

mcrypt_generic_deinit($cryptor);
mcrypt_module_close($cryptor);

出力は次のようになります。

Lorem ipsum dolo?N??]ѕȢ?+?
                                             ????x??k????}??'???Ŧ??;t

しかし、それは " Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do... " (末尾の省略記号を含む) である必要があります。

ブロック サイズは 16 で、最初の 16 文字を正しく取得しています。これは、Mcrypt と CommonCrypto の間の AES CTR カウンターインクリメント プロセスの不一致を示しているようです。私がこれまでに聞いたすべての人は、これはビッグ エンディアンとリトル エンディアンの問題だと示唆しています。

私はこのエンディアンとカウンターインクリメントのすべてを自分で理解しようと何日も費やしましたが、それでも私にとってはブードゥーです。:-( 文字列を適切に復号化する PHP コードが必要なだけです。アルゴリズムがどれほど速く動作するかは気にしません。Mcrypt を捨てて、PHP ネイティブ ソリューションまたはその他の PHP 拡張機能を使用することにオープンです。ただし、iOS 側で変更することはできません

助けてください!

4

2 に答える 2

0

PHP の mcrypt は他の CTR モード (リトル エンディアンではなくビッグ エンディアン) を使用しているようです。キー スケジュールと IV は問題ありませんが (最初のブロックの復号化でわかるように)、IV インクリメント関数で問題が発生しています。

IV を手動でインクリメントし、ECB モードでガンマを暗号化することで問題を解決する次の PHP コードを参照してください。

<?php
$encrypted = base64_decode('MlNFlnXE1sqIsmKZRtjChBvUMgiJlXgdjHVxQJ6JK24Id4uaN9NK/nBtY+cgrMJR/PRJRCmIUx0boQO5XqJYZ8VJ0w==');
$key = base64_decode('HB+dD1Irj2rXQ/nO+IuqSiK9xVE3PD9cZGIGzrMtwtA=');
$iv = base64_decode('2gxxKYU/G4lj7174e5wj+g==');

$ivarr = array_values(unpack('C*', $iv));
$ivdata = array_merge($ivarr);
$blocklen = count($ivarr);

for ($i = 1; $i < strlen($encrypted)/strlen($iv); $i++)
{
    // incrementing IV
    $ivarr[0] += 1;
    if ($ivarr[0] == 256)
    $ivarr[0] = 0;

    $j = 0;
    while ($ivarr[$j] == 0)
    {   
    $j++;
    if ($j == $blocklen)
        break;
    $ivarr[$j]++;
    }
    // appending to array
    var_dump($ivarr);
    $ivdata = array_merge($ivdata, $ivarr);
}

// now ivdata contains the full CTR gamma. Encrypting it.

$cryptor = mcrypt_module_open('rijndael-128', '', 'ecb', '');
$res = mcrypt_generic_init($cryptor, $key, "");

$ivdatastr = implode(array_map("chr", $ivdata));
$ivdecr = mcrypt_generic($cryptor, $ivdatastr);

$ivdecr = array_values(unpack('C*', $ivdecr));
$decrypted = array_values(unpack('C*', $encrypted));
$i = 0;

for ($i = 0; $i < count($decrypted); $i++)
{
    $decrypted[$i] = $decrypted[$i] ^ $ivdecr[$i % count($ivdecr)];
}    

$string = implode(array_map("chr", $decrypted));

var_dump($string);

mcrypt_generic_deinit($cryptor);
mcrypt_module_close($cryptor);
?>
于 2013-05-10T19:41:31.667 に答える