2017-04-19 3 views
1

Aufgrund einiger Implementierung Detail, ich brauche Hashing und Signaturerzeugung zu spalten. Ich habe versucht, dies mit dem Signaturalgorithmus 'NONEwithRSA' zu erreichen.Separate Digest & Signierung mit Java-Sicherheitsanbieter

Dies ist eine grundlegende Arbeitsbeispiel:

public void rsaSignatureIntegrityTest() { 
    KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); 
    gen.initialize(2048, new SecureRandom()); 
    KeyPair pair = gen.generateKeyPair(); 

    byte[] digest = MessageDigest.getInstance("SHA-256").digest(MESSAGE); 
    Signature signer = Signature.getInstance("NONEwithRSA"); 
    signer.initSign(pair.getPrivate()); 
    signer.update(digest); 
    byte[] signed = signer.sign(); 

    Signature verifier = Signature.getInstance("SHA256withRSA"); 
    verifier.initVerify(pair.getPublic()); 
    verifier.update(MESSAGE); 
    verifier.verify(signed); 
} 

des Lauf, wirft die verifier.verify() Methode eine Signatur Ausnahme:

java.security.SignatureException: Signature encoding error 
    at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:204) 
    at java.security.Signature$Delegate.engineVerify(Signature.java:1219) 
    at java.security.Signature.verify(Signature.java:652) 
    at testing.rsaSignatureIntegrityTest(testing.java:38) 
    ... 
Caused by: java.io.IOException: Sequence tag error 
    at sun.security.util.DerInputStream.getSequence(DerInputStream.java:297) 
    at sun.security.rsa.RSASignature.decodeSignature(RSASignature.java:229) 
    at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:195) 
    ... 26 more 

Das Verifizierer Objekt scheint eine Art von DER-kodierte Struktur zu erwarten, die wird nicht vom Unterzeichnerobjekt erzeugt.

Vorschläge, wie dies zur Arbeit kommen?

Antwort

1

Wie vermutet, RSA-Signaturen werden mit einem eingewickelten Digest-Wert erzeugt wird, mit dem Hash-OID. Mit bouncycastle kann dies sehr bequem gemacht werden.

Beispiel:

public void rsaSignatureIntegrityTest() { 
    KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); 
    gen.initialize(2048, new SecureRandom()); 
    KeyPair pair = gen.generateKeyPair(); 

    byte[] digest = MessageDigest.getInstance("SHA-256").digest(MESSAGE); 
    Signature signer = Signature.getInstance("NONEwithRSA"); 
    signer.initSign(pair.getPrivate()); 
    signer.update(wrapForRsaSign(digest, "SHA-256")); 
    byte[] signed = signer.sign(); 
    System.out.println(Base64.getEncoder().encodeToString(signed)); 

    Signature verifier = Signature.getInstance("SHA256withRSA"); 
    verifier.initVerify(pair.getPublic()); 
    verifier.update(MESSAGE); 
    verifier.verify(signed); 
} 

private byte[] wrapForRsaSign(byte[] dig, String hashAlgo) { 
    ASN1ObjectIdentifier oid = new DefaultDigestAlgorithmIdentifierFinder().find(hashAlgo).getAlgorithm(); 
    ASN1Sequence oidSeq = new DERSequence(new ASN1Encodable[] { oid, DERNull.INSTANCE }); 
    ASN1Sequence seq = new DERSequence(new ASN1Encodable[] { oidSeq, new DEROctetString(dig) }); 
    try { 
     return seq.getEncoded(); 
    } catch (IOException e) { 
     throw new DigestException(e); 
    } 
} 
+1

Referenz: Schritt 2 von [EMSA-PKCS1-v1_5] (https://tools.ietf.org/html/rfc3447#section-9.2). Beachten Sie die DER-Codierung beträgt in diesem Fall ein festes Präfix hinzugefügt, wie in Anmerkung 1 auf Seite 43. –

+0

@ dave_thompson_085 Danke für den Hinweis expained, ich habe gerade Reverse-engineered it! – Horst

Verwandte Themen