3

我在与我们的第三方供应商实施 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;
}
4

1 回答 1

4

该异常与 Java 使用的 RSA 公钥有关。您的代码都没有解决这一点。Java端是如何获得那个key的,使用的是什么格式?

可以解释该错误的一个常见错误是,如果模数转换为字节数组,在需要时不存在前导零字节。基本上,这个 BigInteger 构造函数使用起来比它最初看起来要复杂一些。它旨在与 DER 编码的 ASN.1 整数兼容。这一切的结果是,如果b您的模数的第一个字节设置了高位,即128 <= b < 256,您必须在前面加上一个前导零字节,否则您的模数将被解释为负数。为简单起见,您始终可以添加前导零字节;如果没有必要,不会有任何伤害。

于 2010-10-20T11:51:47.547 回答