3

サーバーでC#を使用して文字列を復号化できるようにする必要がありますが、文字列はクライアントでcryptico.jsを使用した公開鍵暗号化を使用して暗号化されました。詳細については、最後のコンテキストを参照してください。

Crypticoは、次のような秘密RSAキーを提供します(注-「このような」-この質問用に新しいキーを作成しました):

Array ( [n] => 8029845567507477803775928519657066509146751167600087041355508603090505634905205233922950527978886894355290423984597739819216469551137046641801207199138209 [e] => 3 [d] => 5353230378338318535850619013104711006097834111733391360903672402060337089936682996269976597251251223844095913209399106464214877696419418951728015128013411 [p] => 102067954277225510613941189336789903269738979633396754230261162567549753196947 [q] => 78671563708406591396117399809764267229341143260756252277657051641634753921147 [dmp1] => 68045302851483673742627459557859935513159319755597836153507441711699835464631 [dmq1] => 52447709138937727597411599873176178152894095507170834851771367761089835947431 [coeff] => 26458340158787140383846156526777567128582042036682248240414722856369310516021 

...さらに多くのメソッド。

私はこのようにそれを解読しようとしています:

                RSAParameters parameters = new RSAParameters();

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();

            parameters.Exponent = encoding.GetBytes("3");

            //dmp1
            parameters.DP =
                encoding.GetBytes("68045302851483673742627459557859935513159319755597836153507441711699835464631");

            //dmq1
            parameters.DQ =
                encoding.GetBytes("52447709138937727597411599873176178152894095507170834851771367761089835947431");

            //d
            parameters.D =
                encoding.GetBytes(
                    "5353230378338318535850619013104711006097834111733391360903672402060337089936682996269976597251251223844095913209399106464214877696419418951728015128013411");

            //p
            parameters.P =
                encoding.GetBytes("102067954277225510613941189336789903269738979633396754230261162567549753196947");

            //q
            parameters.Q =
                encoding.GetBytes("78671563708406591396117399809764267229341143260756252277657051641634753921147");

            //n
            parameters.InverseQ =
                encoding.GetBytes(
                    "8029845567507477803775928519657066509146751167600087041355508603090505634905205233922950527978886894355290423984597739819216469551137046641801207199138209");

            //coeff
            parameters.Modulus =
                encoding.GetBytes("26458340158787140383846156526777567128582042036682248240414722856369310516021");

            RSA rsa = new RSACryptoServiceProvider();
            rsa.ImportParameters(parameters);

            var decryptThis = encoding.GetBytes(ciphertext);

            var result = rsa.DecryptValue(decryptThis);

            resultString = encoding.GetString(result);

しかし、これは例外「不良データ」をチャックします。

C#の経験が豊富な人は、私が間違っているところについて何か考えを持っていますか?

ありがとう、

G


コンテキストの詳細:アプリのクライアント側とサーバー側の両方にパスワード強度チェック機能を実装しようとしていますが、サーバー側のコードのみを使用しています。クライアント側でこれを実現するために、推定パスワードをサーバーに送信し、その強度を判断してから、クライアントに表示されるスコアを返します。これは、サーバー上でパスワード強度チェックコードを維持するだけでよいことを意味します。追加のセキュリティ対策として、cryptico.jsライブラリを使用して推定パスワードを暗号化してから、サーバーに送信して判断します。

4

1 に答える 1

1

BigIntegerクラスとRSAParameterクラスは、数値を異なる形式で格納します。

BigIntegerは、数値をリトルエンディアンとして格納します。これは、16進数の0xABCD(43981)を保持するBigIntegerを作成した場合、ToByteArrayがバイト{ 0xCD、0xAB、0x00 }を返すことを意味します(追加のゼロについては後で詳しく説明します)。

RSAParameterは、数値をビッグエンディアン形式で格納するように設計されています。これは、たとえばExponentプロパティに書き込まれたバイト{ 0xCD、0xAB、0x00 }が、RSA実装によって番号0xCDAB00(13478656)として解釈されることを意味します。

さらに複雑なことに、RSAParametersは常に正の数ですが、BigIntegerは符号をサポートしています。同じ番号の0xFF-は異なって解釈されます。RSAの場合は10進数の255です。BigIntegerの場合は、最上位ビットを符号として解釈するため、-1を意味します。これがゼロが追加される理由です-構築時に、BigIntegerは正の値43981を渡していることを認識しています。ただし、この値を2バイトとして格納すると、バイト0xCD(11001101 inバイナリ)。したがって、BigIntegerは正の数を示すためにゼロを追加します。自分で試してみてください:

Console.WriteLine(new BigInteger(new byte[]{0xCD,0xAB}));
Console.WriteLine(BitConverter.ToString(new BigInteger(0xABCD).ToByteArray()));

したがって、10進文字列「1234567 ...」として大きな整数が渡され、RSAで使用される表現に変換したいと思います。これを行うには、次のものが必要です。

  1. 文字列をBigIntegerに解析します。
  2. BigIntegerバイトを抽出します。
  3. BigIntegerが符号を補正するために先行ゼロを追加していないことを確認してください。
  4. アレイをリバースエンディアン形式に戻し、RSAにフィードします。

コード(パラメーターを使用):

using System;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;

class App
{
    static void Main()
    {
      var parameters = new RSAParameters();
      parameters.Exponent=B("3"); 
      parameters.Modulus=B("8029845567507477803775928519657066509146751167600087041355508603090505634905205233922950527978886894355290423984597739819216469551137046641801207199138209"); 
      parameters.D=B("5353230378338318535850619013104711006097834111733391360903672402060337089936682996269976597251251223844095913209399106464214877696419418951728015128013411");
      parameters.P=B("102067954277225510613941189336789903269738979633396754230261162567549753196947");
      parameters.Q=B("78671563708406591396117399809764267229341143260756252277657051641634753921147");
      parameters.DP=B("68045302851483673742627459557859935513159319755597836153507441711699835464631");
      parameters.DQ=B("52447709138937727597411599873176178152894095507170834851771367761089835947431");
      parameters.InverseQ=B("26458340158787140383846156526777567128582042036682248240414722856369310516021");

      var rsa = new RSACryptoServiceProvider();
      rsa.ImportParameters(parameters);
      var ciphertext = rsa.Encrypt(Encoding.ASCII.GetBytes("Hello"), false);
      Console.WriteLine(Encoding.ASCII.GetString(rsa.Decrypt(ciphertext, false)));
    }

    static byte[] B(string s)
    {
      var b = BigInteger.Parse(s);
      var ret = b.ToByteArray();
      if (ret[ret.Length - 1] == 0) 
      {
        Array.Resize(ref ret, ret.Length - 1);
      }
      Array.Reverse(ret);
      return ret;
    }
}
于 2013-04-04T11:05:47.263 に答える