Как я использую RSACryptoServiceProvider, чтобы расшифровать, учитывая, что у меня только есть p, q, d и u?

Я создаю простое приложение клиента, чтобы экспериментировать с Мега и я испытываю затруднения при обертывании моей головы вокруг способа, которым используется RSA. Давайте возьмем, например, декодирование ID сессии - это - одна из первых вещей, которые должны быть сделаны, чтобы авторизоваться.

API предоставляет мне следующие данные RSA:

  • p (1024 бита)
  • q (1024 бита)
  • d (2044 бита)
  • u (1024 бита)

Прежде всего, я не знаю то, что обозначает "u". Я вижу из кода, что он вычисляется modinverse (p, q) - это, что обычно упоминается как qInverse?

Это - значительно меньше данных RSA для закрытого ключа, чем я использовал ранее, таким образом, я не совсем уверен, что сделать из них. Однако мне дают, чтобы понять, что некоторые данные RSA, используемые RSACryptoServiceProvider, являются просто предварительными расчетными данными в целях оптимизации, поэтому возможно, остальное не необходимо?

Используя эти данные, JavaScript места расшифровывает ID сессии со следующей функцией:

// Compute m**d mod p*q for RSA private key operations.

function RSAdecrypt(m, d, p, q, u)
{
 var xp = bmodexp(bmod(m,p), bmod(d,bsub(p,[1])), p);
 var xq = bmodexp(bmod(m,q), bmod(d,bsub(q,[1])), q);

 var t=bsub(xq,xp);
 if(t.length==0)
 {
  t=bsub(xp,xq);
  t=bmod(bmul(t, u), q);
  t=bsub(q,t);
 }
 else
 {
  t=bmod(bmul(t, u), q);
 } 
 return badd(bmul(t,p), xp);
}

Я хотел бы сделать это в.NET использование RSACryptoServiceProvider, но если я даю ему 4 части данных, я имею (принимающий u == qInverse), ключ отклонен во время импорта за исключением "Неправильных данных".

Я должен делать что-то больше к данным? Действительно ли RSACryptoServiceProvider применим в этой ситуации вообще?

Пример параметров и зашифрованных данных, с которыми я проверяю, следует.

 var p = Convert.FromBase64String("1AkMwy3SPbJtL/k2RUPNztBQKow0NX9LVr5/73+zR3cuwgUToYkVefKdzlTgeri9CAVUq/+jU6o+P7sUpPUN+V97quZa00m3GSIdonRMdaMrDDH5aHnkQgOsCjLJDWXU6+TQBqLumR3XMSat3VO09Dps+6NcMc+uMi5atC3tb+0=");
 var q = Convert.FromBase64String("qtnlmPbATJajNdihw1K6cwSormySATp7g75vYfilYx6RXN3xpNCZR/i8zFbx/lDh+n1a2rdHy1nWyuaD3UmE26d1xUkmsPDfBc72WXt88UqWE/gF7NJjtgTxS2Ui+2GGKUCloi5UA/pOI7R5TBvGI8zna00SH78bctyE0dcAcwM=");
 var d = Convert.FromBase64String("CFL4QPQ8zLzrf2bUzCVX8S2/eALzo/P2cvQsW9lft7uelHYfC1CvHP+z4RvQgXABpgT8YTdU+sgdMHrhHT1vxeUaDRkcQv9lV0IP6YtAcD+gk5jDQkXk4ruYztTUF3v4u8rlMuZ8kAKKWKw+JH6grLWD/vXjMv2RybxPqq3fKI6VJaj/Y/ZnDjD5HrQmJopnCbOrZrPysNb/rGrN3ad9ysaZwBvQtIE0/tQvmL+lsI+PfF9oGKeHkciIo0D4N2abOKT2fiazNm1U9LnrQih687ge0aeAlP2OO8c0h/nbEkMbNg83n1GGEt3DNojIWbT5uHaj12M6G81leS77mfLvSQ==");
 var u = Convert.FromBase64String("CNlUzgCf6Ymd/qeWiv3ScCIXYCwjP3SNLHxRgozIbNg2JEKpJn2M3vO72qLI+FT34xckaAGIcKWMkmpoaKy6PYF4jsAz2atLEClLimbMEPvpWxK7b/I5yvXMT7i2r5hr0OjjplL0wFQYL1IS2M8DTrL99rd9zXCoCWg5Tax6zQM=");

 var encryptedData = Convert.FromBase64String("CABt/Qp7ZODvweEk5RY9JNMXoyFfUwMnc53zbP5jB4jnwWXibLLvjc+Dv5CwQAtUYRme+vRd80++178BiWl0YSOKKhQaDQKoeOUONn3KbZVWyCtyWyQZNtASPoQfizay/Dw3yP5BKsJmDpEv47awdEZzh8IqTcTKeQbpHFL+3uL5EjIENpxMh15rJUsY9w+jq6Yax+379tq67EPMUON0aYkRQ3k1Rsp9fOL6qrgoqOPmOc0cIQgx76t6SFB9LmDySkyBhtK+vcEkdn9GwzZqc6n/Jqt9K8a+mbBv3K7eO3Pa37SDncsaxEzlyLwQ2om1+bK2QwauSQl+7QwQS1a9Ejb9");

 var rsa = new RSACryptoServiceProvider();

//Throws exception saying "Bad data"
 rsa.ImportParameters(new RSAParameters
 {
      D = d,
      P = p,
      Q = q,
      InverseQ = u
  });

Приложение 2 февраля

Я вырыл вокруг в связанных ответах StackOverflow и достиг точки, где я думаю, что определил, как произвести недостающий компонент. Однако теперь я получаю "Плохое ключевое" исключение, которому озадачили меня.

Я напишу код, который я использую, чтобы произвести недостающие компоненты - возможно, можно ли определить ошибку где-нибудь?

Я также вычислил InverseQ и D вручную, и ценности соответствуют тем в моих входных данных. Ниже моя функция для создания необходимых данных, базирующихся только на q, p и e.

private static RSAParameters CalculateRsaParameters(BigInteger p, BigInteger q, BigInteger e)
{
    var modulus = BigInteger.Multiply(p, q);

    var phi = BigInteger.Multiply(BigInteger.Subtract(p, BigInteger.One), BigInteger.Subtract(q, BigInteger.One));

    BigInteger x, y;
   //From http://www.codeproject.com/Articles/60108/BigInteger-Library
   //Returns 1 with my test data.
    ExtendedEuclidGcd(e, phi, out x, out y);

    var d = BigInteger.Remainder(x, phi);

    var dp = BigInteger.Remainder(d, BigInteger.Subtract(p, BigInteger.One));
    var dq = BigInteger.Remainder(d, BigInteger.Subtract(q, BigInteger.One));

    BigInteger x2, y2;
   //Returns 1 with my test data.
    ExtendedEuclidGcd(q, p, out x2, out y2);

   //y2 since it matched the pre-generated inverseQ data I had and x2 was some negative value, so it did not seem to fit. I have no idea what the logic behind which to pick really is.
    var qInverse = BigInteger.Remainder(y2, p);

    return new RSAParameters
    {
        D = ToBigEndianByteArray(d, 256),
        DP = ToBigEndianByteArray(dp, 128),
        DQ = ToBigEndianByteArray(dq, 128),
        InverseQ = ToBigEndianByteArray(qInverse, 128),
        Exponent = ToBigEndianByteArray(e, 1),
        Modulus = ToBigEndianByteArray(modulus, 256),
        P = ToBigEndianByteArray(p, 128),
        Q = ToBigEndianByteArray(q, 128)
    };
}

Мои входные данные:

e = 17
p = 148896287039501678969147386479458178246000691707699594019852371996225136011987881033904404601666619814302065310828663028471342954821076961960815187788626496609581811628527023262215778397482476920164511192915070597893567835708908996890192512834283979142025668876250608381744928577381330716218105191496818716653
q = 119975764355551220778509708561576785383941026741388506773912560292606151764383332427604710071170171329268379604135341015979284377183953677973647259809025842247294479469402755370769383988530082830904396657573472653613365794770434467132057189606171325505138499276437937752474437953713231209677228298628994462467

И вот то, как я использую произведенную структуру:

var rsa = new RSACryptoServiceProvider(2048);
rsa.ImportParameters(CalculateRsaParameters(p, q, e));

ImportParameters требование бросает исключение, говоря "Плохой ключ". Что я делаю неправильно?

, Что происходит, если я переключаю Q и P?

По-видимому, это заставляет RSACryptoServiceProvider принять данные! Но что это означает точно?

Я получил идею от способа, которым я должен был использовать ExtendedEuclidGcd в моем коде поколения. Необходимость использовать различную продукцию для этих двух случаев беспокоила меня много, таким образом, я выполнил этот эксперимент.

Одна вещь - тот u! = qInverse - это правильно? Я не понимаю математику в оригинальной функции JavaScript, таким образом, я не уверен, каковы последствия. Действительно ли я прав в предположении, что стоимость u в оригинале - на самом деле некоторый внутренний короткий путь и не QInverse?

Далее проверяя, чтобы следовать (т.е. фактическое декодирование данных). Я отредактирую вопрос с любыми новыми разработками, однажды сделанными.

Декодирование терпит неудачу с этим набором параметра

Зашифрованные данные тестирования, которые я имею (base64-закодированы):

/TYSvVZLEAztfglJrgZDtrL5tYnaELzI5UzEGsudg7Tf2nM73q7cb7CZvsYrfasm/6lzajbDRn92JMG9vtKGgUxK8mAufVBIeqvvMQghHM055uOoKLiq+uJ8fcpGNXlDEYlpdONQzEPsutr2++3HGqarow/3GEsla16HTJw2BDIS+eLe/lIc6QZ5ysRNKsKHc0Z0sLbjL5EOZsIqQf7INzz8sjaLH4Q+EtA2GSRbcivIVpVtyn02DuV4qAINGhQqiiNhdGmJAb/Xvk/zXfT6nhlhVAtAsJC/g8+N77Js4mXB54gHY/5s851zJwNTXyGjF9MkPRblJOHB7+Bkewr9bQ==
or
bf0Ke2Tg78HhJOUWPSTTF6MhX1MDJ3Od82z+YweI58Fl4myy743Pg7+QsEALVGEZnvr0XfNPvte/AYlpdGEjiioUGg0CqHjlDjZ9ym2VVsgrclskGTbQEj6EH4s2svw8N8j+QSrCZg6RL+O2sHRGc4fCKk3EynkG6RxS/t7i+RIyBDacTIdeayVLGPcPo6umGsft+/bauuxDzFDjdGmJEUN5NUbKfXzi+qq4KKjj5jnNHCEIMe+rekhQfS5g8kpMgYbSvr3BJHZ/RsM2anOp/yarfSvGvpmwb9yu3jtz2t+0g53LGsRM5ci8ENqJtfmytkMGrkkJfu0MEEtWvRI2/Q==

Две альтернативы, данные, так как я не уверен в порядке байтов. Это - те же самые данные в обеих последовательностях.

Декодирование обоих из них терпит неудачу за исключением, говоря, что "Неправильные данные" в первом случае и "Недостаточно хранения доступны, чтобы обработать эту команду". во втором случае (какие требования MSDN могли бы означать, что ключ не соответствует зашифрованным данным). Я говорю RSACryptoServiceProvider, что дополнение PKCS используется, хотя я также экспериментировал с OAEP (который просто дал ошибку об отказе расшифровать дополнение).

Оригинальный JavaScript расшифровывает данные без проблемы, хотя ее "p" и "q" передвинуты от моего.

Прямо сейчас мои вопросы:

  • - выключатель P и Q - вокруг действительной операции, чтобы сделать?
  • мое рассуждение действительно или я сделал ошибку где-нибудь?
  • , Что я должен сделать рядом с успешно, расшифровывает мои данные тестирования?
1
nl ja de
Спасибо, owlstead и @GregS - ваши комментарии помогли мне перейти к сути дела, где я могу произвести недостающие данные. Однако я теперь получаю "Плохую ключевую" ошибку, и я не знаю, что сделать с нею. Мои произведенные данные, кажется, совпадают с моими входными данными, таким образом, я озадачен. Соответствующий код добавляется к вопросу.
добавлено автор Sander, источник
Спасибо, owlstead и @GregS - ваши комментарии помогли мне перейти к сути дела, где я могу произвести недостающие данные. Однако я теперь получаю "Плохую ключевую" ошибку, и я не знаю, что сделать с нею. Мои произведенные данные, кажется, совпадают с моими входными данными, таким образом, я озадачен. Соответствующий код добавляется к вопросу.
добавлено автор Sander, источник
Хорошо, я попытался расшифровать свои данные тестирования с Q и обменянным P (который заставляет RSACryptoServiceProvider принять мой набор параметра), но это приводит к неудаче. Оригинальное внедрение JavaScript делает что-то нестандартное, которое не совместимо с.NET RSACryptoServiceProvider? Или я испортил что-то?
добавлено автор Sander, источник
Хорошо, я попытался расшифровать свои данные тестирования с Q и обменянным P (который заставляет RSACryptoServiceProvider принять мой набор параметра), но это приводит к неудаче. Оригинальное внедрение JavaScript делает что-то нестандартное, которое не совместимо с.NET RSACryptoServiceProvider? Или я испортил что-то?
добавлено автор Sander, источник
Это наконец щелкнуло в моей голове, как простой RSA действительно и как большинство этих параметров только для алгоритмической оптимизации. Игнорируя RSACryptoServiceProvider и просто используя самый простой алгоритм декодирования на Википедию (m ** d ультрасовременный n), мои данные тестирования расшифровывают прекрасный! Этого достаточно, чтобы сделать меня счастливым. Хотя любые комментарии, которые можно дать на возможной причине для неудачи RSACryptoServiceProvider, вероятно, было бы интересно иметь, @GregS. Спасибо за помощь в любом случае!
добавлено автор Sander, источник
Это наконец щелкнуло в моей голове, как простой RSA действительно и как большинство этих параметров только для алгоритмической оптимизации. Игнорируя RSACryptoServiceProvider и просто используя самый простой алгоритм декодирования на Википедию (m ** d ультрасовременный n), мои данные тестирования расшифровывают прекрасный! Этого достаточно, чтобы сделать меня счастливым. Хотя любые комментарии, которые можно дать на возможной причине для неудачи RSACryptoServiceProvider, вероятно, было бы интересно иметь, @GregS. Спасибо за помощь в любом случае!
добавлено автор Sander, источник
@GregS я думаю, что вы помещаете его здесь приятно: stackoverflow.com/questions/14192335/…
добавлено автор Maarten Bodewes, источник
@GregS я думаю, что вы помещаете его здесь приятно: stackoverflow.com/questions/14192335/…
добавлено автор Maarten Bodewes, источник
Необходимо вычислить остающиеся параметры. См.: stackoverflow.com/questions/14229040/…
добавлено автор CodesInChaos, источник
Вы пропускаете ' e' параметр. Это, по-видимому, 17.
добавлено автор James K Polk, источник
Вы пропускаете ' e' параметр. Это, по-видимому, 17.
добавлено автор James K Polk, источник

3 ответы

У RsaParameters есть восемь областей. Я думаю, что необходимо инициализировать всех их, создавая закрытый ключ.

Take a look at http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters.aspx

2
добавлено
Кажется разумным, хотя я надеюсь дело не в этом, так как у меня нет всего этого доступными данными мне. Существующее внедрение JavaScript в состоянии выполнить эту операцию по декодированию RSA только с 4 частями данных, которые я перечислил - это - поведение, которое я хочу копировать.
добавлено автор Sander, источник
См., что мой комментарий указывает на ответ GregS. Вероятно, необходимо обеспечить все данные, но должно быть относительно легко вычислить данные тем более, что у вас уже есть частная экспонента D .
добавлено автор Maarten Bodewes, источник

У RsaParameters есть восемь областей. Я думаю, что необходимо инициализировать всех их, создавая закрытый ключ.

Take a look at http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters.aspx

2
добавлено
Кажется разумным, хотя я надеюсь дело не в этом, так как у меня нет всего этого доступными данными мне. Существующее внедрение JavaScript в состоянии выполнить эту операцию по декодированию RSA только с 4 частями данных, которые я перечислил - это - поведение, которое я хочу копировать.
добавлено автор Sander, источник
См., что мой комментарий указывает на ответ GregS. Вероятно, необходимо обеспечить все данные, но должно быть относительно легко вычислить данные тем более, что у вас уже есть частная экспонента D .
добавлено автор Maarten Bodewes, источник

Есть много возможных ловушек, за которые можно споткнуться в использовании.NET BigIntegers и параметров RSA. Два, которые, вероятно, влияют на вас, являются подавлением начального нуля и endianness.

System.Numerics.BigInteger class, available starting in .NET 4.0, uses a litte-endian format for its ToByteArray() method and new BigInteger(byte []) constructor.

Unfortunately, the RSAParameters structure expects its byte array fields to be in big-endian order. There is also one other incompatibility that must be accounted for. A System.Numerics.BigInteger may be either positive or negative, and the ToByteArray() method accounts for this by using a variant of twos-complement representation. Effectively this means that a positive BigInteger whose byte array representation has a high-order byte >= 128 will have an additional zero byte placed in highest order position. However, the RSAParameter fields are assumed to be all positive, so a leading zero is gratuitously rejected with a "Bad Data" CryptographicException. You must delete these leading zeros where they occur.

Следующее - простой фрагмент примера кода, показывающий эти операции:

    static BigInteger ExtGCD(BigInteger a, BigInteger b, out BigInteger lastx, out BigInteger lasty)
    {
        var x = BigInteger.Zero;
        lastx = BigInteger.One;
        var y = BigInteger.One;
        lasty = BigInteger.Zero;
        while (!b.IsZero)
        {
            BigInteger remainder;
            BigInteger q = BigInteger.DivRem(a, b, out remainder);
            a = b;
            b = remainder;
            var t = x;
            x = lastx - q * x;
            lastx = t;
            t = y;
            y = lasty - q * y;
            lasty = t;
        }

        return a;
    }

    static BigInteger inverse(BigInteger a, BigInteger n)
    {
        BigInteger d, x, y;
        d = ExtGCD(a, n, out x, out y);
        if (d.IsOne)
        {
           //Always return the least positive value
            return (x + n) % n;
        }
        else
        {
            throw new ArgumentException("the arguments must be relatively prime, i.e. their gcd must be 1");
        }
    }

    static byte[] ToByteArrayBE(BigInteger b)
    {
        var x = b.ToByteArray();//x is little-endian
        Array.Reverse(x);       //now it is big-endian
        if (x[0] == 0)
        {
            var newarray = new byte[x.Length - 1];
            Array.Copy(x, 1, newarray, 0, newarray.Length);
            return newarray;
        } else
        {
            return x;
        }
    }
    static RSAParameters CalculateRsaParameters(BigInteger p, BigInteger q, BigInteger e)
    {
       //Given p, q, and e (the RSA encryption exponent) compute the remaining parameters

        var phi = (p - 1) * (q - 1);

        var d = inverse(e, phi);
        var dp = d % (p - 1);
        var dq = d % (q - 1);
        var qInv = inverse(q, p);

        var RsaParams = new RSAParameters
        {
            Modulus = ToByteArrayBE(p * q),
            Exponent = ToByteArrayBE(e),
            P = ToByteArrayBE(p),
            Q = ToByteArrayBE(q),
            D = ToByteArrayBE(d),
            DP = ToByteArrayBE(dp),
            DQ = ToByteArrayBE(dq),
            InverseQ = ToByteArrayBE(qInv)
        };
        return RsaParams;
    }

    static void Main(string[] args)
    {
        BigInteger p = BigInteger.Parse("148896287039501678969147386479458178246000691707699594019852371996225136011987881033904404601666619814302065310828663028471342954821076961960815187788626496609581811628527023262215778397482476920164511192915070597893567835708908996890192512834283979142025668876250608381744928577381330716218105191496818716653");
        BigInteger q = BigInteger.Parse("119975764355551220778509708561576785383941026741388506773912560292606151764383332427604710071170171329268379604135341015979284377183953677973647259809025842247294479469402755370769383988530082830904396657573472653613365794770434467132057189606171325505138499276437937752474437953713231209677228298628994462467");
        BigInteger e = new BigInteger(17);
        RSAParameters RsaParams = CalculateRsaParameters(p, q, e);
        var Rsa = new RSACryptoServiceProvider();
        Rsa.ImportParameters(RsaParams);
    }
}
0
добавлено
RU.CRYPTOGRAPHY — Криптография, алгоритмы, шифрование.
RU.CRYPTOGRAPHY — Криптография, алгоритмы, шифрование.
133 участник(ов)

Группа про криптографию, аналитику, алгоритмы, шифры и ключи.