3

First of all, I see there are other posts with this question, but no one has the same problem as me, i.e. signature.verify() is unexpectedly returning false.

Here's my code:

private static String encriptar(String xmlSolicitud, PrivateKey privateKey)
        throws Exception {

    Signature signature=Signature.getInstance("SHA1withRSA");
    signature.initSign(privateKey);
    signature.update(xmlSolicitud.getBytes(Charset.forName("UTF-8")));
    byte[] signatureValue = signature.sign();
    String response = Base64.encode(signatureValue);
    signature.initVerify(keyReader.publicKeyRead(Reference.rutaPublicKeyTest));
    System.out.println(signature.verify(signatureValue));
    return response;
}

And here is how I read in the keys (if needed):

public static PrivateKey privateKeyRead(String filename)
        throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {

    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int)f.length()];
    dis.readFully(keyBytes);
    dis.close();

    PKCS8EncodedKeySpec spec =
                new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePrivate(spec);
}

public static PublicKey publicKeyRead(String filename)
        throws Exception {

    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int)f.length()];
    dis.readFully(keyBytes);
    dis.close();

    X509EncodedKeySpec spec =
                new X509EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePublic(spec);
}
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
leoxs
  • 425
  • 1
  • 5
  • 15
  • Can you help me on this? https://stackoverflow.com/questions/66117526/unable-to-verify-signed-xml-with-certificate-cer – moDev Feb 13 '21 at 10:48

1 Answers1

2

The state of the signature is reset after you call sign. As per the documentation:

A call to this method resets this signature object to the state it was in when previously initialized for signing via a call to initSign(PrivateKey). That is, the object is reset and available to generate another signature from the same signer, if desired, via new calls to update and sign.

You need to update the signature again with the bytes that were signed:

private static String encriptar(String xmlSolicitud, PrivateKey privateKey)
        throws Exception {

    Signature signature=Signature.getInstance("SHA1withRSA");
    signature.initSign(privateKey);
    signature.update(xmlSolicitud.getBytes(Charset.forName("UTF-8")));

    byte[] signatureValue = signature.sign();
    String response = Base64.encode(signatureValue);

    signature.initVerify(keyReader.publicKeyRead(Reference.rutaPublicKeyTest));
    signature.update(xmlSolicitud.getBytes(Charset.forName("UTF-8"))); // <-- Here

    System.out.println(signature.verify(signatureValue)); // <-- Will print true

    return response;
}

On a side note, it looks like you're signing XML content. Probably wise to use XML signatures to avoid being tripped up by canonicalization issues.

Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
  • 1
    Wow, thanks, it works! And thank you for the text corrections!. The WebService is still returning a invalid CMS error, but it should be another bug. thank you very much! – leoxs Jul 31 '15 at 04:25
  • XML signatures looks nice, but i'm not sure, I'm really noob with xml, but any WebService should understand it? Thanks! – leoxs Jul 31 '15 at 04:40
  • Obviously it depends on the service, but generally speaking a web service that requires signed XML content will in most cases be expecting an XML signature. – Robby Cornelissen Jul 31 '15 at 04:42
  • Well, maybe that's why i'm getting that error, I will take a look. Thanks for all your help! – leoxs Jul 31 '15 at 04:49
  • @RobbyCornelissen Here String *xmlSolicitud* means entire XML or only signature node in XML? – moDev Feb 09 '21 at 15:44
  • @RobbyCornelissen can you tell what I'm doing wrong? https://stackoverflow.com/questions/66117526/unable-to-verify-signed-xml-with-certificate-cer – moDev Feb 10 '21 at 10:48
  • @moDev See the final part of my answer. You're attempting to verify an XML signature (XML-DSig). There is *a lot* more involved than what you're doing in your code. I'm afraid that I currently don't have the time to write up a complete answer for you. Google something like "XML-DSig validation in Java" to get started. – Robby Cornelissen Feb 10 '21 at 11:24
  • @RobbyCornelissen ok, I need to understand the steps.1. Public Key 2. Update data in signature and 3. Verify. Do we need to encode xml data in step 2? – moDev Feb 13 '21 at 09:48
  • @RobbyCornelissen I'm not able to get proper solution – moDev Feb 16 '21 at 16:07
  • can you suggest or share any online tool where I can validate this process? Thank you! – moDev Feb 16 '21 at 18:15