Summarized and clarified:
Using origami, extracting a certificate from a signed pdf (signed within e.g. Adobe Reader) I cannot verify the signature:
origami = Origami::PDF.read(File.open('/path/to/file.pdf', 'r'))
pdf_signature = origami.signature[:Contents]
cert = OpenSSL::PKCS7.new(pdf_signature).certificates.first
origami.verify(trusted_certs: [cert]) #=> false
As far as I can tell, this should always be true. So maybe Adobe uses a different byte range that it takes a SHA of when signing the PDF? How do I get that verify to work?
If it's any help, after tiptoing through the changes on origami master, I was able to get the exact OpenSSL error from the storecontext: V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY - I presume it means from the X509::Store it sets up.
Full background
I'm trying to verify the digital signature of a PDF. Here's what I've got:
A PDF that I've signed using Adobe Acrobat (tried both Pro 10 and Reader DC)
The key was generated in Acrobat Pro, I have access to the .p12, or exporting as FDF, PKCS#7 or just "Certificate File". Have also tried loading this "Certificate File" via Apple's "Keychain Access" and exporting that as a .pem This gives the same result as OpenSSL::PKCS7.new(File.read('/path/to/exported.p7c')).certificates.first.to_pem
which gives the same result as:
openssl pkcs7 -print_certs -inform der -in pkcs7file.p7c -out certificate.cer
So, I'm pretty sure I've extracted the certificate correctly.
Also, I can verify that exact same certificate is embedded in the PDF -
pdf_signature = origami.signature[:Contents]
OpenSSL::PKCS7.new(pdf_signature).certificates.first.to_pem #=> Same as above
With the Origami gem, I've tried loading the certificate and attempting verification:
cert = OpenSSL::X509::Certificate.new(File.read('/path/to/pem.cer'))
Origami::PDF.read(File.open('/path/to/file.pdf', 'r')).verify(trusted_certs: [cert])
Origami's output confirms the document has been signed, but the verify(..)
method returns false.
Note that working through the code from this excellent answer works fine, but it only seems to work if you generate the X.509 keypair using openssl (e.g. the ruby-land bindings as per that code). Unfortunately I'm required to use the pre-existing Adobe-blessed signatures from the user's machines.
That said, aside from this I have very few restraints; I can ask the users to export their certificate in any other way that is useful to us (I can even run some simple code on their machines if necessary), though I mustn't transmit the private key in the procedure. I don't have to use Origami for the verification, but it does have to be a command accessible from ruby on an ubuntu server. The users are all running on Macs with reasonably up-to-date software.