1

私はC#で次のコードを持っています

string s = "hellowld";
byte[] bytes = new UnicodeEncoding().GetBytes(s);
FileStream stream = new FileStream(inputFile, FileMode.Open);
RijndaelManaged managed = new RijndaelManaged();
CryptoStream stream2 = new CryptoStream(stream, managed.CreateDecryptor(bytes, bytes), CryptoStreamMode.Read);
FileStream stream3 = new FileStream(outputFile, FileMode.Create);
try
{
    int num;
    while ((num = stream2.ReadByte()) != -1)
    {
        stream3.WriteByte((byte) num);
    }
 [....]

このコード スニペットは、特定のファイルを復号化し、復号化されたバージョンを出力します。RijndaelManaged im の CreateDecryptor メソッドで、パスワードを KEY および IV として使用します。

ここでPHPのstackoverflowでいくつかのコードを見つけましたが、C#のようにキーと同じバイト配列をivに渡そうとしても何も起こりません。

$Pass = "hellowld";
$Clear = file_get_contents('./file.dat', FILE_USE_INCLUDE_PATH);

$bytePass=array();
$i = 0;
foreach (str_split($Pass) as $value) {
    $bytePass[$i]=ord($value);
    $i++;
}

echo decryptAES($Clear,$bytePass,$bytePass);

function decryptAES($content,$iv, $key,$aes) {

// Setzt den Algorithmus
switch ($aes) {
    case 128:
       $rijndael = 'rijndael-128';
       break;
    case 192:
       $rijndael = 'rijndael-192';
       break;
    default:
       $rijndael = 'rijndael-256';
}

// Setzt den Verschlüsselungsalgorithmus
// und setzt den Output Feedback (OFB) Modus
$cp = mcrypt_module_open($rijndael, '', 'ofb', '');

 // Ermittelt die Anzahl der Bits, welche die Schlüssellänge des Keys festlegen
$ks = mcrypt_enc_get_key_size($cp);

// Erstellt den Schlüssel, der für die Verschlüsselung genutzt wird
$key = substr(md5($key), 0, $ks);

// Initialisiert die Verschlüsselung
mcrypt_generic_init($cp, $key, $iv);

// Entschlüsselt die Daten
$decrypted = mdecrypt_generic($cp, $content);

// Beendet die Verschlüsselung
mcrypt_generic_deinit($cp);

// Schließt das Modul
mcrypt_module_close($cp);

return trim($decrypted);

}

PHPでコードを適切に作成する方法について、本当に助けが必要です。PHP でファイルを出力する必要はありません。文字列で十分です。

UPDATE : デフォルトの C# RijndaelManaged 暗号方式は AES-128-CBC です。PHPコードをそのmcryptモジュールに変更しました(デフォルトのC#暗号メソッド

更新 2: Java Decryptor を作成することができたので、別のことがわかりました。PHP は PKCS7 パディングを使用する必要があります。

4

1 に答える 1

1

あなたの C# コードは実際には安全に見えません。変更できる場合は、以下のヒントを参照してください。これは、指定された C# コードと同等になるように変更された、指定された PHP コードです。

function decryptAES128CBC($content,$iv, $key) {

    // AES is Rijndael-128
    $rijndael = 'rijndael-128';

    // key size is 128 bit = 16 bytes
    $ks = 16;

    // CBC mode, not OFB
    $cp = mcrypt_module_open($rijndael, '', 'cbc', '');

    // pad key and IV by zeros (this is not a good idea)
    $key = str_pad($key, $ks, "\0");
    $iv = str_pad($key, $iv, "\0");

    // initialize the decryptor with key and IV
    mcrypt_generic_init($cp, $key, $iv);

    // the actual work
    $decrypted = mdecrypt_generic($cp, $content);

    // clean up
    mcrypt_generic_deinit($cp);
    mcrypt_module_close($cp);

    // remove padding, see below
    return unpad($decrypted);
}

最後unpadに、暗号化関数によって追加された可能性が高いパディングを削除して、メッセージ サイズを完全なブロック数に拡大します。RijndaelManaged で使用されるデフォルトのパディングは PKCS7-padding で、これはバイト数 (1 から 16 の間) を追加します。各バイト数は、追加されたバイト数と同じです。実際の実装では、パディングが有効であること (つまり、これらすべてのバイトが同じ値であること) を復号​​化後に確認しますが、「迅速で汚い」場合は、最後のバイトを確認してそのバイト数を削除するものを単純に使用できます。例については、mcrypt_decryptへのコメントを参照してください。

C# コードを変更できる場合:

  • 通常、(キーごとに) 固定値を初期化ベクトルとして使用することはお勧めできません。また、キー自体を初期化ベクトルとして使用することも適切ではないことに注意してください。(メッセージと一緒に送信される) ランダムな初期化ベクトルを使用するか、次のポイントを参照してください。

  • また、通常は (かなり短い) パスワードをキーとして直接使用したくありませんが、代わりに長いパスフレーズを使用し、それをソルト (メッセージに含まれています) でハッシュしてキーを導出します。これを行うと、同じ 2 つのデータから初期化ベクトルを導出することもできます (ただし、キー導出関数を使用して異なる方法で)。暗号化されたファイルからパスワードを総当たり攻撃するのを避けるには、ここで低速ハッシュ関数 (PBKDF-2 または bcrypt) を使用します。

于 2011-12-07T23:28:14.983 に答える