2016-10-24 1 views
1

Ich muss die aus C# erstellte Signatur mithilfe des "SHA1" -Algorithmus in meinem JAVA-Programm überprüfen, das "SHA1withRSA" verwendet. Signaturbytes stimmen nicht überein. Ich verwende den öffentlichen Schlüssel, der vom C# -Programm erzeugt wurde, um die Signatur zu überprüfen, die in einer Datei gespeichert ist. Ich bin neu in der Kryptographie. Im Folgenden finden Sie Code C# erstellen Unterschrift:Die in C# erstellte digitale Signatur stimmt nicht mit der Java-Verifizierung überein.

 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); 

     RSA.FromXmlString(privateKey); 

     var encoder = new UTF8Encoding(); 
     byte[] originalData = encoder.GetBytes(message); 
     SHA1 sha1 = SHA1.Create(); 

     byte[] signedBytes = RSA.SignData(originalData, sha1); 

     return signedBytes; 

Ich versuche, wie unten Signatur in Java-Programm zu überprüfen:

//read xml file to get modulus and exponent bytes 
      File publicKeyFileQA = new File(PUBLIC_KEY_FILE_QA); 

      Map<String, BigInteger> publicKeyModulusExponentValues = DSXCRM_3YBP_Global_WebServicesUtil.readXMLFile(publicKeyFileQA); 

      BigInteger publicKeyModulus = publicKeyModulusExponentValues.get("modulus"); 
      BigInteger publicKeyExponent = publicKeyModulusExponentValues.get("exponent"); 

      System.out.println("BigInteger Modulus : "+ publicKeyModulus + "BigInteger Exponent : " + publicKeyExponent); 

      String messageWithSignature = (String) mapDataToPost.get("SignedMessage"); 
      String encryptedMessage = (String) mapDataToPost.get("EncryptedMessage"); 

      byte[] signatureBytes = DatatypeConverter.parseBase64Binary(messageWithSignature); 

      System.out.println("Signature bytes : "+ new String(signatureBytes)); 


      byte[] cipherMessage = DatatypeConverter.parseBase64Binary(encryptedMessage); 

      System.out.println("Cipher Message : "+ new String(cipherMessage)); 

      KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 
      RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(publicKeyModulus, publicKeyExponent); 
      PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); 
      Signature sig = Signature.getInstance("SHA1withRSA"); 
      sig.initVerify(publicKey); //public key of sender 
      sig.update(cipherMessage); 

      boolean isRightSender = sig.verify(signatureBytes); 
      System.out.println("isRightSender : "+isRightSender); 

aber Ergebnis übereinstimmen Signatur falsch ist. Ich verstehe nicht, was falsch ist. Kannst du bitte irgendwelche Vorschläge machen? Gibt es einen anderen Algorithmus, der sowohl mit C# als auch mit JAVA kompatibel ist, um dieselben Signaturen zu haben? Vielen Dank!

+0

Ich sehe keine offensichtlichen Fehler in Ihrem Code. Kann die Codierung der Nachrichten- und Signaturbytes sein, die von C# an Java gesendet werden? – pedrofb

+0

ja, ich stimme dir zu. Es könnte ein Codierungsfehler sein, dem ich gegenüberstehe. – Coder

Antwort

0

Sie lesen ein Feld namens "SignedMessage", speichern dieses in einer Variablen namens "messageWithSignature" und behandeln es dann so, als wäre es nur die Signatur. Welche Daten sind in diesem Blob tatsächlich vorhanden?

Sie drucken weiter binäre Daten als wäre es Text (über new String(byte[])). Sie sollten Base64 oder Hex auf beiden Seiten drucken, um zu sehen, ob sie übereinstimmen, sowohl für die Nachrichtenbytes (die in Ihrem Verifier cipherMessage genannt werden) als auch für die Signatur.

Wenn Sie auf statische Daten umschalten (um die Dinge zu vermeiden wie neue Zeilen auf Lesezählung) dann sollte es gültig sein zu tun, nehmen

byte[] originalData = Encoding.UTF8.GetBytes("This is a static message test."); 
Console.WriteLine(Convert.ToBase64String(rsa.SignData(originalData), "SHA1")); 

dann diese Ausgabe, legen Sie sie in Ihr Java-Programm und überprüfen

byte[] originalData = "This is a static message test.".getBytes("UTF-8"); 
byte[] signature = Base64.getDecoder().decode(theOutputFromTheCSharpProgram); 
Signature verifier = new Signature("SHA1withRSA"); 
verifier.initVerify(publicKey); 
verifier.update(originalData); 
System.out.println(verifier.verify(signature)); 

Wenn dieser Teil nicht funktioniert, dann müssen Sie nicht den gleichen Schlüssel auf beiden Seiten treu darstellen.

Das Binärformat der Signaturen für RSA ist in C# und Java identisch; Sobald Sie den Datentransport in Ordnung gebracht haben, sollte alles funktionieren.

+0

Ich versuchte oben Teil, Problem ist nach Parsing Base64 String in Byte [] in Java ist es nicht das gleiche wie wir von C# bekommen. Ich verwende DatatypeConverter.parseBase64Binary (messageWithSignature); – Coder

+0

Ich habe diese richtige Richtung, die ich Base64 String nur verwenden müssen, um von C# nach Java in Byte [] zu bekommen, da kein anderes Format zwischen C# und Java kompatibel ist, akzeptiere ich Ihre Antwort. Dennoch habe ich Schwierigkeiten, dass die Signatur nicht übereinstimmt. – Coder

+0

@Coder Sind Sie sicher, dass Sie 'publicKey' korrekt erstellen? Insbesondere interpretiert BigInteger alles mit dem hohen Bit, das als negative Zahl gesetzt ist. Überprüfen Sie, ob es weniger als BigInteger.zero testet. – bartonjs

Verwandte Themen