I am using PKCS#1 2.0 (OAEP) standard (signature with appendix), but there are some issues not clear to me.
What is the physical object that is beeing signed? I know it's hash function value and so on (I do know the algorithm), but is it calculated from the binary fform of the file, no matter what is the content?
What is the physical result of signing? A file containing the signed hash? Should this file be placed in a specified location? What is the format or extension of such thing?
If I have several files that I want to sign, should this operation be performed separately for each of them? Or should they be concatenated? Once again - what is the result of such operation (file?) ?
PKCS#1 is sometimes called 'raw RSA' and is a low-level cryptographic primitive: it doesn't work on files and doesn't produce files, it works on raw data: input is a number smaller than the public key and output is a number of the size of the public key (e.g. 1024 bit for RSA-1024).
If you want a signature file, you probably want to use PKCS#7/CMS format, as that's the most used signature format both for attached and detached signatures (even signatures in PDF files are usually PKCS#7 envelopes actually).
PS: I don't know much about OAEP, but from what I read it seems to be a padding scheme (something you do to data before the raw signature) so my argument should be still valid.
Related
Preamble: I am not trying to merge different PDFs.
I was wondering. Does the signature of a PDF modify the signed portion of the document or is it appended to some other section of the file?
If the signed portion of the document does not include the signatures, it should be possible to transfer the signature of a document to another file containing the exact same document:
In practice, sending identical PDF to person A and B or signing, I get PDF[A] and PDF[B] back, I can then transfer signature of B to PDF[A], getting PDF[A, B].
Is that theoretically possible? Has someone already tried it?
First of all, I assume you mean a special case of electronic signatures which often are referred to as digital signatures: These signatures allow verification using the hash of the bytes signed by the signature.
Furthermore, I assume you mean the interoperable types of digital PDF signatures as specified in the PDF specifications and related documents with the extra condition that the signed bytes encompass the whole signed revision except only the placeholder for the signature container. (The PDF specification allows to sign less but common validators forbid that.)
Under these assumptions:
No, what you want to do is not possible.
Signing does not merely append a signature container somewhere; instead it first extends the PDF with some extra objects to represent the signature and hold its signature container, and then it creates a signature for that prepared PDF, not for the original one.
The preparations by two different persons A and B most likely are not identical, so the ranges signed by them differ.
Furthermore, real "parallel signing" of the identical content is not possible in interoperable digital PDF signing, only a consecutive, serial signing. Thus, if you have a PDF with multiple signatures, the bytes signed by the second one actually include the first signature:
Thus, you cannot simply transfer the signature of B as a second signature to the PDF already signed by A because a second signature has to sign something completely different than a first one.
(That being said, there is a larger signing software house whose software used to create signed PDFs with multiple SignerInfos in a single signature container; this is forbidden in the PDF specification for interoperable signatures but a situation validators seldom check for. During validation Adobe Acrobat here only validated the first SignerInfo; some other software only validated the last; in the end this only caused a lot of confusion.)
Quoting a jsign bug report related How to validate authenticode for Javascript in C#.
I've played a bit with VBScript and JScript files, it looks like the hashing method is different from the PowerShell scripts. For PowerShell the content is converted to UTF-16LE before being hashed. For VB and JS it doesn't work, the hash generated differs from the one computed by signtool. I tried various encodings (UTF-8, UTF-16BE, UTF-32BE/LE, with or without byte order marks) but it still doesn't match.
How does one create the .vbs signature block without signtool.exe (and without any proprietary and/or Microsoft tools?)
Edit:
So far, I've observed the following:
By default, signtool.exe uses SHA-1 signatures. It can be forced to use SHA-256 signatures using /fd sha256
By default, JSign adds some additional properties to the signature which throw off an exact signature match.
For reference, this is what the end-product signature normally looks like when using signtool.exe.
'' SIG '' Begin signature block
'' SIG '' MIIM4AYJKoZIhvcNAQcCoIIM0TCCDM0CAQExCzAJBgUr
' ... (a bunch of bas64 data) ...
'' SIG '' cSu0HJyT7v9OctFKlKj7aCB6JHPrR0il9GFdoZrQFNuU
'' SIG '' End signature block
The purpose of this signature is to allow Windows to verify the publisher of the file. It's not a well-documented standard, but can be found in solutions like this.
Modern purposes may include running a .vbs file as a standalone script or as part of an application. Leveraging Windows' built-in validation mechanism adds a layer of trust to the script for environments that need it.
Quoting Chapter 28 of Don Jones' "Managing Windows with VBScript and WMI."
Running Only Signed Scripts
If you don't want to mess around with software restriction policies, you can also rely on WSH's own built-in form of security policy. This policy allows you to specify that only signed scripts will be run; unsigned scripts won't be. This is probably the easiest and most effective way to prevent most unauthorized scripts.
Digital signatures are common enough so that we shouldn't be limited by closed source utilities like signtool.exe.
Quoting Emmanuel Bourg, the author of JSign from the bug that inspired this question:
I got it, the script is indeed hashed in UTF-16LE, but the size of the unsigned file encoded as a 4 bytes little endian integer is added to the hash.
So, common hashing algorithms will work against hashable content (SHA-1, SHA-256), but in order to pass WinVerifyTrust, the additional 4 bytes need to be added to the hashed data.
I have a theoretical question about PAdES. I want to know if it is possible to revoke a signature in PDF or remove it?
I don't know what exactly you technically mean by revoking a signature.
But it clearly is possible to remove a signature: An integrated PDF signature usually consists of a signature form field with a value that contains a CMS signature container.
You have the choice of either removing only that value or the whole field with the value.
The former option leaves an empty signature field, which can easily be used for a new signature with a visualization at the same location as your original signature (if it has any to start with).
The latter option removes your signature completely.
Two caveats, though:
If you don't merely want the signature not to appear anymore, make sure that
you don't save this edit as an incremental update - if it was done as an incremental update, the document version with your signature could easily be restored;
you don't merely remove the reference to the the value from the signature field but that you actually clear the value object - the signature value object might be referenced from other locations in the PDF, too, so if you don't clear it, its information might remain accessible inside the PDF.
If your PDF contains multiple signatures or document timestamps, and if the signature you want to remove is not the newest one, manipulating it will break at least all newer signatures / time stamps. This is due to the way multiple signatures are applied to PDFs:
As you can recognize in this sketch, the bytes signed by newer signatures contain all older signatures.
In such a situation, therefore, don't only implement "remove a single target signature" but instead "remove all signature starting at a single target signature".
For some more technical backgrounds on integrated PDF signatures cf. this answer and documents referenced from there.
With iText 5.5.4, if I choose to embed CRLs during the signature process, it breaks the PDF/A-2B conformance because of a String too long error :
Adobe Preflight http://img4.hostingpics.net/pics/234201so5.jpg
As you can see in the preflight from Adobe Acrobat Pro 11.0.09, the CRL is 67107 characters long whereas this specific PDF standard require that the maximum length for strings must not exceed 32767 bytes.
Is it a bug in Itext or is there a way to keep PDF/A-2B conformance in that case?
Is it a bug in Itext?
As you can see in the preflight from Adobe Acrobat Pro 11.0.09, the CRL is 67107 characters long whereas this specific PDF standard require that the maximum length for strings must not exceed 32767 bytes
Considering that the problem string is referenced as 1 0 obj/Contents seems to indicate that it actually is the string reserved for the CMS signature container, not the plain CRL.
Looking at the PDF/A specification (I only have part 3 at hands but the parts 2 and 3 should coincide here) there are two sections which seem to contradict each other:
A conforming file shall not contain any string longer than 32767 bytes.
(section 6.1.13 Implementation limits)
and
timestamping and revocation information should be included [in the PDF Signature (a DER-encoded PKCS#7 binary data object)] in order to improve the long-term non-repudiation properties of the signature.
(Annex B Requirements for digital signatures in PDF/A)
In your case following the latter recommendation breaks the former requirement because the PKCS#7 / CMS object is embedded as a string in the PDF.
But as we have a requirement against a recommendation, the recommendation need only be followed as long as the requirements are not violated. The specification even explicitly says so:
When generating signature appearances and any other PDF objects as part of the signing process, a
conforming reader shall ensure that it does not invalidate compliance with this part of ISO 19005
(section 6.4.3 Digital signatures)
Thus indeed, iText signing should fail during the signing process... if you have used the PDF/A aware API, that is. Unfortunately you have not provided your source code, so it is not clear whether or not you have used the PdfAStamper or merely the PdfStamper.
Or is there a way to keep PDF/A-2B conformance in that case?
You didn't supply your source code, so this can only be answered in a more general way.
First of all check whether the space reserved for the signature container is really required or whether there are many padding bytes. In the latter case fine tune the reservation code.
If that does not suffice, embedding the CRL into the signature container automatically results in a violation of PDF/A conformance and, therefore, is not allowed.
One option would then be to try to use OCSP responses instead of CRLs here. OCSP responses usually contain information for only one or at most very few certificates while CRLs can become quite big.
If the CA does not have OCSP servers, I don't see a true PDF/A-2'ish solution. You might want to try to embed validation related information in PAdES part 4 (ETSI TS 102 778-4) DSS (Document Security Store) structures instead of in the signature container. Plain PDF/A viewers most likely won't recognize, let alone use, the CRL there but more versatile viewers, e.g. current Adobe Reader versions, should.
I was developing a PDF signing tool. For this I will get a signed sha256 data of PDF in PKCS#1 format and a certificate from a device, I need to use these two to embed inside the PDF. Most of the PDF reader only support PKCS#7 signature.
Is there any way to convert a PKCS#1 signature to PKCS#7 signature (using certificate file) ?
I knew that PKCS#7 = Certificate + Optional raw data + Signature in PKCS#1 format
Your question somewhat oversimplifies the situation.
Concerning PKCS#7 <-> PKCS#1:
Yes, a PKCS#7 signature container contains SignerInfo objects which respectively essentially contain a PKCS#1 style signature and some attributes. BUT this PKCS#1 style signature generally is NOT merely signing the document data but instead is signing a structure of so called "signed attributes". One of these is a document hash, others can be the signing time, a link to the signer certificate, and other information; these extra information is required in many use cases. Only the most primitively built SignerInfo structures sign the document data directly.
In general, therefore, if you simply take a PKCS#1 signature of some data and wrap it in a PKCS#7 container, that signature container won't be accepted.
For details see RFC 3852.
Concerning integrated PDF signatures:
Your description of your implementation-to-be is somewhat vague. You seem to think that the document hash to sign is a hash of the original PDF. In case of integrated PDF signatures this is wrong: In order to create an integrated PDF signature, you first extend the PDF by some data which envelop a placeholder for the PKCS#7 signature container (recommended by the specification) or the PKCS#1 signature to integrate. Then you need to hash this extended PDF except the placeholder. (By the current PDF specification you could hash less than that but this won't be accepted by the current Adobe Acrobat/Reader and shouldn't be accepted by any serious verifier).
For details see ISO 32000-1:2008 as published by Adobe
Depending on the legal requirements you may also have to take into account PDF Advanced Electronic Signatures (PAdES) as specified by ETSI, cf. ETSI standard for EU-compliant electronic signatures. These will become part of ISO 32000-2, aka PDF 2.0.
So, are you still sure your use case allows for those very simple PKCS#7 signatures you have in mind, and are your PKCS#1 source signatures created for the right document? In that case building those containers is easily done by looking at RFC 3852.
Anyways, you should have a look at the whitepaper Digital Signatures for PDF documents by Bruno Lowagie (iText Software).
Looking at RFC 3852 > 5.4. Message Digest Calculation Process
It is possible to simply convert PKCS#1 to PKCS#7 as long as there are not signed attributes in it. If there are then you are stuck as the PKCS#1 coverts ONLY the hash of the content and PKCS#7 with signed attributes required to construct an intermediary structure and hash of that structure is being signed.