Шифрование RSA в .NET - дешифрование в JAVA -> Java выдает ошибку «модуль не положительный» - PullRequest
3 голосов
/ 19 октября 2010

У меня проблемы с нашим сторонним поставщиком, который поддерживает sso. Они получают следующую ошибку при проверке моей подписи:

java.lang.ArithmeticException: BigInteger: модуль не положителен - в java.math.BigInteger.modPow (BigInteger.java:1556)

У меня нет контроля над их Java-кодом. Вот что я делаю сейчас:

Я создал пару ключей в C #, используя этот код:

        CspParameters csp = new CspParameters();
        csp.KeyNumber = (int)KeyNumber.Signature;
        using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024, csp))
        {

            File.AppendAllText(path + "PrivateKey.xml", rsa.ToXmlString(true));
            File.AppendAllText(path + "PublicKey.xml", rsa.ToXmlString(false));
        }

Вот код для подписи:

public string MD5withRSASignature(string encryptedStringToSign)
    {

        byte[] signature;
        using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024))
        {
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(PRIVATE_KEY_PATH);
            rsa.FromXmlString(xDoc.OuterXml);
            byte[] bytes = Encoding.UTF8.GetBytes(encryptedStringToSign);
            signature = rsa.SignData(bytes, new MD5CryptoServiceProvider());
        }

        return Convert.ToBase64String(signature);
    }

(Да, я знаю, что закрытый ключ должен находиться в хранилище ключей).

Вот код, который они используют для преобразования ключей XML (это Java)

private static RSAPublicKey ReadXMLKey(String fileName)
{

        DocumentBuilderFactory factory =     DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse( new File(fileName) );
        byte[] modBytes = GetBytesFromElement(document, "Modulus");
        byte[] expBytes = GetBytesFromElement(document, "Exponent");
        RSAPublicKeySpec rsaKeyspec = new RSAPublicKeySpec(new BigInteger(modBytes), new BigInteger(expBytes));
        RSAPublicKey key = (RSAPublicKey)KeyFactory.getInstance("RSA").generatePublic(rsaKeyspec);

        return key;
         }

private static byte[] GetBytesFromElement(Document doc, String tag) throws IOException
{
    BASE64Decoder decoder = new BASE64Decoder();
    NodeList list = doc.getElementsByTagName(tag);
    byte[] results = null;
    if (list.getLength() == 1)
    {
        Element item = (Element)list.item(0);
        Text text = (Text)item.getFirstChild();
        results = decoder.decodeBuffer(text.getNodeValue().trim());
    }
    return results;
}

1 Ответ

4 голосов
/ 20 октября 2010

Исключение связано с открытым ключом RSA, который использует Java.Ни один из ваших кодов не указывает на это.Как сторона Java получила этот ключ, какой формат используется?

Одна распространенная ошибка, которая может объяснить ошибку, заключается в том, что модуль преобразуется в массив байтов , но лидирующийнулевого байта нет, когда это должно быть.По сути, этот конструктор BigInteger немного сложнее в использовании, чем может показаться на первый взгляд.Он разработан для совместимости с целыми числами ASN.1 в кодировке DER.Результатом всего этого является то, что если первый байт b вашего модуля имеет установленный старший бит, то есть 128 <= b < 256, вы должны добавить начальный нулевой байт, иначе ваш модуль будет интерпретирован как отрицательное число.Для простоты вы всегда можете добавить начальный нулевой байт;никакого вреда не будет, если в этом нет необходимости.

...