I have a base64 encoded message digest (signing bytes of a pdf), which I want to sign and return PKCS7. Previously, I was using SUNPKCS11 and was able to attach the same to the pdf.
I have started using IAIK PKCS11 Wrapper. Below is the process, I have a IAIKPKCS11ContentSigner defined like:
public class IAIKPKCS11ContentSigner implements ContentSigner {
private final Session session;
private final RSAPrivateKey privateKey;
private final ByteArrayOutputStream outputStream;
public IAIKPKCS11ContentSigner(Session session, RSAPrivateKey privateKey) {
this.session = session;
this.privateKey = privateKey;
this.outputStream = new ByteArrayOutputStream();
}
@Override
public byte[] getSignature() {
try {
AlgorithmIdentifier sha256Aid = new DefaultDigestAlgorithmIdentifierFinder().find("SHA-256");
DigestInfo digestInfo = new DigestInfo(sha256Aid, this.outputStream.toByteArray());
byte[] encodedDigestInfo = digestInfo.getEncoded();
Mechanism signingMechanism = Mechanism.get(PKCS11Constants.CKM_SHA256_RSA_PKCS);
session.signInit(signingMechanism, privateKey);
return session.sign(encodedDigestInfo);
} catch (Exception e) {
throw new RuntimeException("Error", e);
}
}
@Override
public org.bouncycastle.asn1.x509.AlgorithmIdentifier getAlgorithmIdentifier() {
return new org.bouncycastle.asn1.x509.AlgorithmIdentifier(
org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers.sha256WithRSAEncryption);
}
@Override
public OutputStream getOutputStream() {
return outputStream;
}
}
and now I am signing the hash like:
//already initialize session and extracted RSAPrivateKey
//taking current session (iaik.pkcs.pkcs11) and RSAPrivateKey
IAIKPKCS11ContentSigner signer = new IAIKPKCS11ContentSigner(session, pk);
OutputStream outputStream = signer.getOutputStream();
outputStream.write(hash); //writing the hash of the document to sign
byte[] signature = signer.getSignature(); //fetching signature from the content signer
ContentInfo contentInfo = new ContentInfo(ContentInfo.DATA_OID, null);
X509Certificate[] certificates; //certificate for the key above;
AlgorithmId[] digestAlgorithmIds; // SHA-256
SignerInfo si; //creating signer info using cert attributes and signed content signature;
SignerInfo[] signerInfos = {si};
PKCS7 p7 = new PKCS7(digestAlgorithmIds, contentInfo, certificates, signerInfos);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
p7.encodeSignedData(bytes);
output = bytes.toByteArray();
But while attaching this pkcs7 as deferred signature on a pdf, getting document has been altered or corrupted. Is this the right approach to sign? Any pointers if I am doing anything wrong here?
You use the mechanism PKCS11Constants.CKM_SHA256_RSA_PKCS
. But that mechanism does calculate the hash of the data, wrap it in a DigestInfo
structure, apply PKCS#1 1.5 padding, and encrypt.
As far as I understand your code, though, you already have calculated the hash and wrapped it in a DigestInfo
structure. So you only want PKCS#1 1.5 padding and encryption to be applied.
Thus, you may want to use the mechanism PKCS11Constants.CKM_RSA_PKCS
instead.