1

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?

mkl
  • 90,588
  • 15
  • 125
  • 265
tulak.hord
  • 63
  • 1
  • 9
  • Can you share an example file signed with your code for analysis? – mkl May 15 '23 at 08:38
  • here is the link with valid and invalid signed pdf: https://drive.google.com/drive/folders/1GaOb-_o6jUGGsxRKopydUaLa5wFch75Z?usp=sharing – tulak.hord May 16 '23 at 07:04
  • Could it be that you misnamed the files? Adobe Acrobat shows `validSignature_oldMethod.pdf` as having invalid signatures while it shows `invalidSignature_newMethod.pdf` as having mathematically valid signatures. – mkl May 16 '23 at 13:31
  • 1
    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 and 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. – mkl May 16 '23 at 14:16
  • Yes, looked like I misnamed the file. Just tried with mechanism PKCS11Constants.CKM_RSA_PKCS and the signature is coming out to be valid. Thanks very much ! – tulak.hord May 16 '23 at 15:05
  • Ok, I'll make that an actual answer, not a mere comment. – mkl May 16 '23 at 15:22
  • Out of curiosity, Given a pdf document, is there any way on how to check why the document got corrupted? I am implementing a digital signature validation tool like adobe has Signature Validation Status but it just says the document is alerted or corrupted since the signature was applied. How to debug the same, like there could be multiple reasons: - Mismatch in digital signature algorithm used - Alteration in the document - Integrity of signature container – tulak.hord May 20 '23 at 15:57
  • Well, there are some issues you can identify. E.g. if the signer certificate public key is a RSA key but the claimed signature algorithm is ECDSA, you can try to validate the signature assuming the signature algorithm is actually based on RSA. Or if the hash value calculated with the claimed signature hash algorithm does not validate, you can try using hash values calculated with other algorithms. But seriously, does it really make sense to try and identify such reasons for signature validation failures? You still don't know whether they are caused by a bug or by some manipulation. – mkl May 21 '23 at 21:18
  • Yes, that's what it doesn't make sense. It could be because of anything, how to go about making a digital signature validation tool? Any documentation to follow or anything as such. – tulak.hord May 23 '23 at 08:29
  • Well, usually digital signature validation tools only determine whether they consider a signature valid or not and don't try to guess the cause in the latter case. Also validation itself depends on the validation policy to be applied. For qualified signatures in the EU, for example, ETSI EN 319 102-1 describes in detail how to validate. – mkl May 23 '23 at 22:18

1 Answers1

1

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.

mkl
  • 90,588
  • 15
  • 125
  • 265