【问题标题】:cryptico.js encrypted message, must decrypt in C#cryptico.js 加密消息,必须在 C# 中解密
【发布时间】:2012-11-18 15:11:25
【问题描述】:

我需要能够在服务器上使用 C# 解密字符串,但该字符串是使用公钥加密和客户端上的 cryptico.js 加密的。详情见文末。

Cryptico 给了我一个这样的私有 RSA 密钥(注意 - 'like' this - 我为这个问题创建了一个新密钥):

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 库对假定的密码进行加密,然后将其发送到服务器进行判断。

【问题讨论】:

  • 我希望您没有向我们展示真正的私钥。
  • 哈哈,没有。请放心,这是专门为此问题生成的测试密钥。它的密码是“特殊的天使巨齿鲨孵化器”,顺便说一下,它是 512 位。这些值也会因生产系统而改变。
  • 我不知道您是如何生成这些字符串的,例如264583401587871403838461.....,但 encoding.GetBytes 在我看来并不正确。我会尝试BigInteger.Parse("..").ToByteArray()
  • 数字字符串取自 cryptico 创建的 RSA 私钥对象的转储 - 他们的方法在他们的 github 页面上描述。我试过 BigInteger.Parse("..").ToByteArray();正如建议的那样,但不幸的是没有快乐。感谢您的建议。
  • 我认为你已经交换了 InverseQ 和 Modulus。

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


【解决方案1】:

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

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

RSAParameter 旨在以大端格式存储数字。 这意味着写入例如 Exponent 属性的字节 {0xCD, 0xAB, 0x00} 将被解释 通过 RSA 实现,编号为 0xCDAB00 (13478656)。

让事情变得更复杂 - RSAParameters 总是正数,而 BigInteger 支持符号。 和相同的数字,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。

代码(使用您的参数):

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

【讨论】:

  • 感谢您的回答。我将回到代码上(自 2012 年 11 月以来,我已转到该项目的另一个部分)并尝试一下。
  • 有人让这个工作吗?调用 rsa.ImportParameters(parameters); 时,我仍然遇到错误的数据异常
  • 它是否会抛出来自答案的数据或您的自定义数据的异常?答案中的代码对我来说毫无例外。
猜你喜欢
  • 1970-01-01
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
  • 2018-02-13
  • 1970-01-01
  • 2020-11-01
  • 2021-07-04
  • 1970-01-01
相关资源
最近更新 更多