4

文字列値の暗号化と復号化を実行できる暗号化クラスを持つC#アプリケーションがあるプロジェクトに取り組んでいます。ここで、PHPを使用してC#アプリケーションと一緒に機能するWebインターフェイスを作成したいと思います。

C#プロジェクトがPHP Webサイトで実行しているのと同じ種類の暗号化を実行しようとしていますが、実行する必要があることを理解できません。

以下は私のC#アプリケーションのコードです。

public static string encrypt(string encryptionString)
        {
            byte[] clearTextBytes = Encoding.UTF8.GetBytes(encryptionString);

            SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();

            MemoryStream ms = new MemoryStream();
            byte[] rgbIV = Encoding.ASCII.GetBytes("PRIVATE");

            byte[] key = Encoding.ASCII.GetBytes("PRIVATE");
            CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write);

            cs.Write(clearTextBytes, 0, clearTextBytes.Length);

            cs.Close();

            return Convert.ToBase64String(ms.ToArray());
        }

PHPWebインターフェイスで次のコードを試しています

define("CIPHERKEY", "PRIVATE");
function encrypt($data) 
    { 
        //$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_ECB, '');
        $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
        //$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($cipher), MCRYPT_RAND);
        $iv = 'PRIVATE';
        //$key = substr(CIPHERKEY, 0, mcrypt_enc_get_key_size($cipher));
        $key =CIPHERKEY;
        if (mcrypt_generic_init($cipher, $key, $iv) != 1) 
        {
            $cipherData = mcrypt_generic($cipher, $data);

            mcrypt_generic_deinit($cipher);
            mcrypt_module_close($cipher);

            $sanitizedCipherData = trim(base64_encode($cipherData)); 

            return $sanitizedCipherData;
        } 
    }

さまざまなバリエーションを試しましたが、正しい方法が見つかりません。

iv変数はC#アプリ内のrgbIV変数と同じキーを使用しており、PHP WebインターフェイスのCIPHERKEYは私のc#アプリ内のキー変数と同じキーを使用しています。

あなたが提供できるどんな助けにも感謝します

更新 現時点では、さまざまな結果が得られ続けています。文字列を渡してテストしていますpassword

上記のPHPの現在のコードではNHHloywxlybbANIH5dS7SQ==、暗号化された文字列として取得します。

ただし、同じ文字列を使用すると、次の結果が得られます。n86Mwc5MRXzhT3v3A/uxEA==

4

2 に答える 2

3

異なる結果が得られる理由は、デフォルトで C# の暗号モードが CBC であるのに対し、PHP では ECB モードを使用しているためです。2 つの異なるモードについては、ウィキペディアを参照してください。

CBC は ECB よりも安全であるため、デフォルトの .NET 実装に固執し、CBC を使用するように PHP コードを変更することをお勧めしますが、2 つのオプションがあります。

オプション 1 - ECB モードを使用するように .NET を変更します (レガシー コードがあり、それを使用する必要がある場合) ただし、ECB モードは暗号文にアーティファクトを残し、攻撃者が何についての知識を得ることができるかをお読みください。暗号化しました (ウィキペディアの記事のペンギンの画像を参照してください)。

ECB を使用するように .NET コードを変更するには、モードの行を追加するだけです。

// Start of your code ...
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
rijn.Mode = CipherMode.ECB;

MemoryStream ms = new MemoryStream();
byte[] rgbIV = Encoding.ASCII.GetBytes("PRIVATE");
// Rest of your code ...

オプション 2 - CBC モードを使用するように PHP スクリプトを変更する

$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');

更新 これをさらに詳しく調べたところ、平文にもパディングを追加する必要があることがわかりました。次のコードで一致が得られます。

PHP コード:

function encrypt($data) 
{ 
    $iv = "AAAAAAAAAAAAAAAA";
    $key = CIPHERKEY;

    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, addpadding($data), MCRYPT_MODE_CBC, $iv));
}

function addpadding($string, $blocksize = 16)
{
    $len = strlen($string);
    $pad = $blocksize - ($len % $blocksize);
    $string .= str_repeat(chr($pad), $pad);
    return $string;
}

C# コードは、PKCS7 に基づいてパディングを自動的に追加します。

Update 2 Strip Padding: コメントに記載されているように、パディングは復号化後に削除する必要があります。

function strippadding($string)
{
    $slast = ord(substr($string, -1));
    $slastc = chr($slast);
    $pcheck = substr($string, -$slast);
    if(preg_match("/$slastc{".$slast."}/", $string)){
        $string = substr($string, 0, strlen($string)-$slast);
        return $string;
    } else {
        return false;
    }
}
于 2013-01-27T19:43:20.427 に答える
1

これを試して:

   function encrypt_str($str) 
    {
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_DEV_URANDOM);
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, "PRIVATE", $str, MCRYPT_MODE_ECB, $iv);
    return rtrim($encrypted);
    }

そしてこれをあなたのC#に追加してください

rijn.Mode = CipherMode.ECB;
于 2013-01-27T19:41:01.523 に答える