Frage

Ich möchte C#-Code in das Äquivalent in Java konvertieren.

Der C#-Code nimmt einige Zeichenfolgeninhalte und eine Signatur (generiert mit dem privaten Schlüssel auf einem separaten Computer) und überprüft in Kombination mit dem öffentlichen Schlüssel die Signaturübereinstimmungen, wodurch ein gewisses Maß an Sicherheit geboten wird, dass die Anfrage nicht manipuliert wurde.

  public bool VerifySignature(string content, byte[] signatureBytes, AsymmetricAlgorithm publicKey)
  {
        var hash = new MD5CryptoServiceProvider();

        byte[] dataBuffer = Encoding.ASCII.GetBytes(content);

        var cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write);
        cs.Write(dataBuffer, 0, dataBuffer.Length);
        cs.Close();

        var deformatter = new RSAPKCS1SignatureDeformatter(publicKey);
        deformatter.SetHashAlgorithm("MD5");

        return deformatter.VerifySignature(hash, signatureBytes);
  }

Der öffentliche Schlüssel selbst ist ein X509-Zertifikat – erstellt aus einer .cer-Datei, gespeichert als Assembly-Ressource, d. h.

byte[] data; // data is read from a resource stream.
var publicKey = new X509Certificate2(data, "", X509KeyStorageFlags.MachineKeySet).PublicKey.Key

Ich möchte diese Funktionalität in Java emulieren, damit ich die von einem Code in C# generierte Signatur überprüfen kann ...Ich habe begonnen, die Krypto-Funktionalität von Java zu untersuchen, bin aber eher ein Java-Neuling.Folgendes habe ich bisher herausgefunden:

byte[] certContents=null;
byte[] signature=null;
String contents = "abc";

// load cert
CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certContents));

// grab public key
RSAPublicKey publicKey = (RSAPublicKey)cert.getPublicKey();

// get sha1 hash for contents        
Mac mac = Mac.getInstance("HmacSHA1");
mac.update(contents.getBytes());                
byte[] hash = mac.doFinal();

// get cipher
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);

// verify signature of contents matches signature passed to method somehow (and this is where I'm stuck)

Kann mir jemand einen Einblick geben, wie ich die Signatur überprüfen kann – oder Links zu einigen Ressourcen bereitstellen, die die Verwendung von java.crypto und java.security.cert besser erklären könnten als die gewöhnlichen Java-Dokumente?

War es hilfreich?

Lösung

Dieser C#-Code sieht für mich wirklich verwirrend aus.Es verwendet SHA1CryptoServiceProvider, aber MD5-Hash, sodass ich nicht sagen kann, welchen Hashing-Algorithmus es verwendet.Ich gehe davon aus, dass es MD5 ist.

Bei der Signaturüberprüfung ist eine Auffüllung erforderlich, damit Ihr Code nicht funktioniert.Im Folgenden finden Sie einen Ausschnitt meines Codes, mit dem Sie die Signatur überprüfen können.Daten sind die zu signierenden Bytes und sigBytes enthält die Signatur.

String algorithm = "MD5withRSA";

// Initialize JCE provider    
Signature verifier = Signature.getInstance(algorithm);

// Do the verification   
boolean result=false;

try {
    verifier.initVerify(cert); // This one checks key usage in the cert
    verifier.update(data);
    result = verifier.verify(sigBytes);
}
catch (Exception e) {
    throw new VerificationException("Verification error: "+e, e);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top