3

私はこれを理解するために数時間を費やしましたが、それを機能させることができません。PHPで照合する必要のあるC#暗号化ルーチンがあります。C#のバージョンを変更することはできません。これはオプションではありません(サードパーティはこれに固執しています)。

C#コードは次のとおりです。

//In C#
// Console.WriteLine(ApiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl"));
// Results in: 
//     XvHbR/CsLTo=
public static string ApiEncode(string data, string secret)
{
  byte[] clear;

  var encoding = new UTF8Encoding();
  var md5 = new MD5CryptoServiceProvider();

  byte[] key = md5.ComputeHash(encoding.GetBytes(secret));

  TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
  des.Key = key;
  des.Mode = CipherMode.ECB;
  des.Padding = PaddingMode.PKCS7;

  byte[] input = encoding.GetBytes(data);
  try { clear = des.CreateEncryptor().TransformFinalBlock(input, 0, input.Length); }
  finally
  {
    des.Clear();
    md5.Clear();
  }

  return Convert.ToBase64String(clear);
}

これが私がPHPで思いついたものの中で最高のものです:

//In PHP
// echo apiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl");
// Results in: 
//    5aqvY6q1T54=
function apiEncode($data, $secret)
{    
  //Generate a key from a hash
  $key = md5(utf8_encode($secret), true);
  //Create init vector  
  $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_ecb), MCRYPT_RAND); 

  //Pad for PKCS7
  $blockSize = mcrypt_get_block_size('tripledes', 'ecb');
  $len = strlen($data);
  $pad = $blockSize - ($len % $blockSize);
  $data .= str_repeat(chr($pad), $pad);

  //Encrypt data
  $encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb'); //, $iv);
  return base64_encode($encData);
}

私の知る限り、PHP側でPKCS7のパディングを適切に処理しています。他に何を試すべきかわかりません。

注意すべき点の1つは、C#はWindowsで、PHPはLinuxで発生していることですが、それが違いを生むかどうかはわかりません。

4

4 に答える 4

10

PHP バージョンのパディングの長さは、パスワードの長さに基づいています。これは正しくありません。代わりに、メッセージの長さに基づく必要があります。

に置き換えstrlen($password)てみてくださいstrlen($data)


2 つ目の問題は、mcryptライブラリが 24 バイトのキーを必要とすることです。トリプル DES は通常の DES を 3 回適用するため、DES K 1、K 2、および K 3の各ラウンドで使用される 8 バイトのキーを呼び出すことができます。これらのキーを選択するには、さまざまな方法があります。最も安全なのは、3 つの異なるキーを選択することです。もう 1 つの方法は、K 3を K 1に等しく設定することです。最も安全でない方法 (DES と同等) は、K 1 = K 2 = K 3にすることです。

ほとんどのライブラリは、16 バイトの 3DES キーを上記の 2 番目のオプションとして解釈できるほど「スマート」です: K 3 = K 1。.NET 実装はこれを行っていますが、mcryptライブラリはそうではありません。代わりに、K 3 = 0 を設定しています。これを自分で修正しmcrypt、24 バイトのキーを渡す必要があります。

MD5 ハッシュを計算した後、 の最初の 8 バイトを取得し、$keyそれらを の末尾に追加して、$keyに渡す 24 バイトの値を取得しmcrypt_encrypt()ます。

于 2011-01-14T20:28:59.557 に答える
1

解決策を見つけました。このリンクを確認してください。役立つ場合があります。http://sanity-free.com/131/triple_des_between_php_and_csharp.html

念のため、復号化関数を次に示します。

    public static string Decrypt(string cypherString)
    {

        byte[] key = Encoding.ASCII.GetBytes("icatalogDR0wSS@P6660juht");
        byte[] iv = Encoding.ASCII.GetBytes("iCatalog");
        byte[] data = Convert.FromBase64String(cypherString);
        byte[] enc = new byte[0];
        TripleDES tdes = TripleDES.Create();
        tdes.IV = iv;
        tdes.Key = key;
        tdes.Mode = CipherMode.CBC;
        tdes.Padding = PaddingMode.Zeros;
        ICryptoTransform ict = tdes.CreateDecryptor();
        enc = ict.TransformFinalBlock(data, 0, data.Length);
        return UTF8Encoding.UTF8.GetString(enc, 0, enc.Length);
    }
于 2012-01-31T16:04:43.707 に答える
0

encoding.getBytesを見てください。UTF8からの秘密鍵Bytesが必要です...

于 2011-01-14T20:18:41.153 に答える
-1

C# バージョンではIVが設定されていないようです。msdn が次のように述べているため、それが何であるかわからない場合、これは問題になる可能性があります。

SymmetricAlgorithm クラスの 1 つの新しいインスタンスを作成するか、GenerateIV メソッドを手動で呼び出すと、IV プロパティは自動的に新しいランダム値に設定されます。

PHP バージョンでは、IVを使用しているようです。IV を指定しないようにして、C# バージョンでもゼロが使用されることを期待できます。

編集: ECB のように見えますが、IV は無視されます。

utf8-encodeを使用して C# バージョンのようにキーをエンコードする必要がある場合もあります

于 2011-01-14T20:16:05.177 に答える