I am trying to create a PKCS#7 signature file from a raw signature of type RSASSA-PSS. The verification of the raw signature is successful but the verification of the PKCS#7 object fails with NoSuchAlgorithmException: SHA256withRSASSA-PSS Signature not available
.
The code is below. Calling verifyRawSignature
returns true but calling verifyPkcs7Signature
fails with the stacktrace in the javadoc. There is probably an error in createPkcs7
but where is it?
package dev.example;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PSSParameterSpec;
public class Pkcs7Tool {
/**
* The data to verify.
*/
private final byte[] data;
/**
* The raw 256 signature bytes as returned from the remote signing service.
*/
private final byte[] rawSignature;
/**
* The signing certificate;
*/
private final X509Certificate certificate;
public Pkcs7Tool(byte[] data, byte[] rawSignature, X509Certificate certificate) {
this.data = data;
this.rawSignature = rawSignature;
this.certificate = certificate;
}
/**
* Verifies the raw signature.
*/
public boolean verifyRawSignature() {
try {
final Signature signatureVerifier = Signature.getInstance( "RSASSA-PSS" );
signatureVerifier.setParameter( new PSSParameterSpec( "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1 ) );
signatureVerifier.initVerify(certificate);
signatureVerifier.update(data);
return signatureVerifier.verify(rawSignature);
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | SignatureException e) {
throw new RuntimeException("failed to verify raw signature", e);
}
}
/**
* Verifies the signature packaged into a pkcs7 file.
* Fails with
* <pre>
* java.security.NoSuchAlgorithmException: SHA256withRSASSA-PSS Signature not available
* at java.base/java.security.Signature.getInstance(Signature.java:267)
* at java.base/sun.security.pkcs.SignerInfo.verify(SignerInfo.java:431)
* at java.base/sun.security.pkcs.PKCS7.verify(PKCS7.java:578)
* at java.base/sun.security.pkcs.PKCS7.verify(PKCS7.java:595)
* at java.base/sun.security.pkcs.PKCS7.verify(PKCS7.java:617)
* at dev.example.Pkcs7Tool.verifyPkcs7Signature(Pkcs7Tool.java:60)
* </pre>
*/
public SignerInfo[] verifyPkcs7Signature() {
try {
return createPkcs7().verify();
} catch (SignatureException | NoSuchAlgorithmException e) {
throw new RuntimeException("failed to verify pkcs7 signature", e);
}
}
/**
* Create a DER encoded PKCS7 file from a raw signature.
* Inspired by https://stackoverflow.com/a/56015231/1581276
*/
public PKCS7 createPkcs7() {
final X500Name xName = X500Name.asX500Name(certificate.getIssuerX500Principal());
final BigInteger serial = certificate.getSerialNumber();
final AlgorithmId digestAlgorithmId = new AlgorithmId(AlgorithmId.SHA256_oid);
final AlgorithmParameters algorithmParameters;
try {
algorithmParameters = AlgorithmParameters.getInstance("RSASSA-PSS");
final AlgorithmParameterSpec algorithmParameterSpec = new PSSParameterSpec( "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1 );
algorithmParameters.init(algorithmParameterSpec);
} catch (NoSuchAlgorithmException | InvalidParameterSpecException e) {
throw new RuntimeException("Failed to initialize signature algorithm parameters", e);
}
final AlgorithmId signAlgorithmId = new AlgorithmId(AlgorithmId.RSASSA_PSS_oid, algorithmParameters);
final SignerInfo signerInfo = new SignerInfo(xName, serial, digestAlgorithmId, signAlgorithmId, rawSignature);
final ContentInfo contentInfo = new ContentInfo(ContentInfo.DATA_OID, null);
return new PKCS7(new AlgorithmId[]{digestAlgorithmId}, contentInfo,
new java.security.cert.X509Certificate[]{certificate},
new SignerInfo[]{signerInfo});
}
}