cryptico.js加密消息,必须在C#中解密

时间:2012-11-30 11:37:30

标签: c# javascript public-key-encryption cryptico

我需要能够使用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#在我出错的地方有任何想法?

谢谢,


上下文详细信息:我正在尝试在应用程序的客户端和服务器端实现密码强度检查功能,但仅使用服务器端的代码。为了在客户端实现这一点,我想将假定的密码发送到服务器,判断其强度,然后返回客户端上显示的分数。这意味着我只需要在服务器上维护密码强度检查代码。作为额外的安全措施,我在使用cryptico.js库加密推定的密码,然后将其发送到服务器进行判断。

1 个答案:

答案 0 :(得分:1)

BigInteger和RSAParameter类以不同的格式存储数字。

BigInteger将数字存储为little-endian - 这意味着如果您创建BigInteger 保持十六进制数 0xABCD (43981) - ToByteArray将返回字节{ 0xCD,0xAB,0x00 }(稍后会有更多的额外零点)。

RSAParameter旨在以big-endian格式存储数字。 这意味着将写入例如Exponent属性的字节{ 0xCD,0xAB,0x00 } 通过RSA实现数字 0xCDAB00 (13478656)。

更复杂的事情 - RSAParameters总是正数,而BigInteger支持sign。 和相同的数字,0xFF - 将被不同地解释。对于RSA,它是十进制255.对于BigInteger,它表示-1, 因为它将最重要的位解释为符号。 这就是添加零的原因 - 在施工时,BigInteger意识到我们正在传递正值43981。 但是将该值存储为两个字节将产生负数(-21555),因为最高位设置为字节 0xCD (二进制为11001101)。 所以BigInteger加零表示正数。亲自尝试一下:

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

因此,我们将大整数作为十进制字符串“1234567 ...”传递给我们,我们希望将其转换为RSA使用的表示形式。 为此,我们需要:

  1. 将字符串解析为BigInteger。
  2. 提取BigInteger字节。
  3. 确保BigInteger没有添加任何前导零以补偿符号。
  4. 将数组反转回大端格式,并提供给RSA。
  5. 代码(使用您的参数):

    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;
        }
    }