Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cryptographic signature verification has failed - issue during signature finalize #135

Open
Ashkehn opened this issue Sep 2, 2024 · 3 comments

Comments

@Ashkehn
Copy link

Ashkehn commented Sep 2, 2024

Hi all,

I am developing a simple digital signing application and closely followed the documentation. However, when I attempt to
finalize the signature using the finalize method from the DataToSign class, I encounter the following error:
eu.europa.esig.dss.model.DSSException: Cryptographic signature verification has failed / Signature verification failed against the best candidate.
image
image

I am using a self signed x509 certificate generated on my windows machine.

Thanks in advance.

@rsarendus
Copy link
Contributor

Hello,

Cryptographic signature verification failure indicates that the signature you provided fails to validate against the public key of your certificate. This could have many reasons, including:

  • The byte array provided to dataToSign::finalize does not represent a correct signature.
  • The signature is not created using the private key that corresponds to your certificate.
  • The input data signed by your private key did not correspond to the signature algorithm that you used for signing.

At the following line of your code:

signatureDTO.setBase64Signature(digestDTO.getHash());

What does digestDTO::getHash return? What does signatureDTO::setBase64Signature do?

At the following line of your code:

byte[] signatureBytes = DatatypeConverter.parseBase64Binary(signatureDTO.getBase64Signature());

How is the signature, returned by signatureDTO::getBase64Signature, obtained?

Is the signature creation implemented in Java or is the signing done remotely using some other means?


The exact way to sign the input data depends on the tool that you are using.

For example, in case of using java.security.Signature for signing in Java, you must also pay attention to the signature algorithm. Signature algorithms like "SHA256withRSA"* (in case of signing with an RSA key) and "SHA256withECDSA"* (in case of signing with an EC key), expect that you provide the raw, un-hashed data-to-sign:

Signature signature = Signature.getInstance("SHA256withRSA"); // or "SHA256withECDSA"
signature.init(yourPrivateKey); // Initialize the signature with your private key
signature.update(dataToSign.getDataToSign()); // Provide the raw, un-hashed input
return signature.sign();

But if you calculate the digest of the data-to-sign yourself, then you must use signature algorithms like "NONEwithRSA" (in case of signing with an RSA key) and "NONEwithECDSA" (in case of signing with an EC key).

Signature signature = Signature.getInstance("NONEwithECDSA");
signature.init(yourPrivateKey); // Initialize the signature with your private key
signature.update(digest); // Provide the digest that you have calculated
return signature.sign();

NB: "SHA256withRSA"* signature algorithm corresponds to RSASSA-PKCS1-v1_5 signature scheme. This means that when using RSA key for signing and you calculate the digest yourself, then you must also prepend the digest with appropriate padding:

Signature signature = Signature.getInstance("NONEwithRSA");
signature.init(yourPrivateKey); // Initialize the signature with your private key
signature.update(dataToSign.getDigestAlgorithm().digestInfoPrefix()); // Prepend the digest with padding
signature.update(digest); // Append the digest that you have calculated
return signature.sign();

* The digest algorithm in the above examples has been chosen based on your example code. When using a different digest algorithm, adapt the examples accordingly.

@Ashkehn Ashkehn closed this as completed Sep 9, 2024
@Ashkehn Ashkehn reopened this Sep 9, 2024
@Ashkehn
Copy link
Author

Ashkehn commented Sep 9, 2024

Hello,

I managed to resolve the issue, but now I am encountering another problem with the
(Signature ID: id-e68830f0f475537cb207ac01bb696c3b) - OCSP request failed. Kindly refer to the GitHub Wiki for more information: https://github.com/open-eid/digidoc4j/wiki/Questions-&-Answers#if-ocsp-request-has-failed.

I have checked the GitHub link but haven't found the solution.

I use a self-signed certificate, and the configuration mode is set to TEST.
Tried to set

Configuration::setOCSPAccessCertificateFileName("mypath");
 Configuration::setOCSPAccessCertificatePassword("");
 or 
 Configuration::setSignOCSPRequests(false);

Thank you

@naare
Copy link
Contributor

naare commented Sep 10, 2024

If you need to test the signing I suggest you use keystore that is already made for testing purposes in DD4J project (you can see references and pins):

protected static final PKCS12SignatureToken pkcs12SignatureToken = new PKCS12SignatureToken("src/test/resources/testFiles/p12/sign_RSA_from_TEST_of_ESTEIDSK2015.p12", "1234".toCharArray());

These keystores work out of the box with DD4J in TEST mode and can be used for testing purposes.

Using your own certificate for LT profile signature means that the issued certificate profile must match all the requirements, it must be trusted (present in TSL or trusted programmatically together with all needed qualifiers) and must have valid OCSP response. Fullfilling all these conditions with self issued certificates requires specific knowledge and is not easily achieved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants