質問

私は今これを理解しようとして数時間費やしましたが、私はそれを機能させることができません。 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で発生していること、LinuxでPHPが発生しているため、それが違いを生むかどうかはわかりません。

役に立ちましたか?

解決

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

交換してみてください strlen($password)strlen($data).


2番目の問題は、です mcrypt ライブラリには24バイトのキーが必要です。 Triple DEは通常のDESを3回適用するため、DES Kの各ラウンドで使用される8バイトキーを呼び出すことができます1, 、k2, 、k3. 。これらのキーを選択するには、さまざまな方法があります。最も安全なのは、3つの異なるキーを選択することです。別の方法は、kを設定することです3 kに等しい1. 。最も安全な方法(DESに相当)は、kを作成することです1 = k2 = k3.

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

MD5ハッシュを計算した後、最初の8バイトを取ります $key, 、そしてそれらを終了に追加します $key, 、そのため、24バイトの値があります mcrypt_encrypt().

他のヒント

解決策を見つけ、このリンクをチェックして、あなたを助けるかもしれません。 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);
    }

Encoding.getBytesをご覧ください。UTF8からの秘密のキーバイトが必要です...

C#バージョンが設定されていないようです IV. 。 MSDNが言っているので、これが何であるかわからない場合、これは問題になる可能性があります。

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

PHPバージョンのように見えますが、 IV. 。 IVを提供せず、C#バージョンがZerosも使用することを願っています。

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

また、C#バージョンのようにキーをエンコードする必要があるかもしれません utf8-encode

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top