Pregunta

Estoy teniendo problemas con nuestro proveedor de terceros implimenting un sso. Están recibiendo el siguiente error al verificar mi firma:

java.lang.ArithmeticException: BigInteger: módulo no positiva - en java.math.BigInteger.modPow (BigInteger.java:1556)

No tengo ningún control sobre su código Java. Esto es lo que estoy haciendo ahora:

He creado un par de claves en C # usando este código:

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

Este es el código para la firma:

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

(Sí, sé que la clave privada debe estar en un almacén de claves).

Este es el código que utilizan para convertir claves XML (esto es 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;
}
¿Fue útil?

Solución

La excepción tiene que ver con la clave pública RSA que Java está utilizando. Ninguno de sus direcciones de código de ese punto. ¿Cómo logró el lado de Java esa clave, qué formato se está utilizando?

Un error común que puede tener en cuenta el error es que si el módulo se convierte en una matriz de bytes pero a byte cero no está presente cuando se necesita ser. Básicamente, este BigInteger constructor es un poco más difícil de usar que puede parecer al principio. Está diseñado para la compatibilidad con números enteros ASN.1 DER-codificado. El resultado de todo esto es que si el primer byte del b su módulo tiene el conjunto de bit alto, es decir 128 <= b < 256, debe anteponer un byte cero o su módulo será interpretado como un número negativo. Por simplicidad siempre se puede anteponer un byte cero a la izquierda; no sufrirá ningún daño si no era necesario.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top