2010-10-19 5 views
3

J'ai des problèmes avec notre fournisseur tiers qui implémente un sso. Ils reçoivent l'erreur suivante lors de la vérification de ma signature:Cryptage RSA dans .NET - décryptage dans JAVA -> Java lance l'erreur "module non positif"

java.lang.ArithmeticException: BigInteger: module non positif - à java.math.BigInteger.modPow (BigInteger.java:1556)

Je ne contrôle sur leur code Java. Voici ce que je fais maintenant:

J'ai créé une paire de clés en C# en utilisant ce code:

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

Voici le code de la signature:

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

(Oui, je sais que la la clé privée doit être dans un magasin de clés).

Voici le code qu'ils utilisent pour convertir les clés xml (ce qui est 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; 
} 
+0

Pourriez-vous publier toute la pile d'exceptions Java? – andrewmu

+0

Malheureusement, je ne peux pas. Ils refusent de le fournir. Cela vient apparemment des classes Java RSA standard. –

+0

J'ai supplié et j'ai obtenu leur code de conversion de clé XML. Voir ci-dessus –

Répondre

4

L'exception a à voir avec la clé publique RSA que Java utilise. Aucune de vos adresses de code ne pointe sur ce point. Comment le côté Java a-t-il obtenu cette clé, quel format est utilisé?

Une erreur courante qui peut expliquer l'erreur est si le module est converti en un tableau d'octets mais un octet nul principal n'est pas présent quand il doit être. Fondamentalement, this BigInteger constructor est un peu plus délicat à utiliser que cela puisse paraître. Il est conçu pour la compatibilité avec les entiers ASN.1 codés en DER. Le résultat de tout cela est que si le premier octet b de votre module a le bit haut défini, c'est-à-dire 128 <= b < 256, vous devez ajouter un octet de début zéro ou votre module sera interprété comme un nombre négatif. Pour plus de simplicité, vous pouvez toujours ajouter un octet de début nul. aucun mal ne viendra si ce n'était pas nécessaire.

+0

Je génère la clé au format xml et je l'envoie. J'ai récupéré leur code qui prend une clé au format xml et le convertit. Le constructeur BigInteger est-il le problème ici? Comment serais-je en mesure de préfixer un 0 octet à un module dans une clé xml? (le code est au-dessus) –

+0

Il s'avère que je n'utilisais pas le bon format de clé (PKCS # 8), et utilisait juste ce que .NET crache. Merci cependant - vous m'a indiqué dans la bonne direction. –