-
-
Notifications
You must be signed in to change notification settings - Fork 182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sign PDF with external service returning signature + certificate from hash (no private key access) #46
Comments
Take a look at those issues that are related: You should be able to achieve what you want with a slight modification of the code so that instead of using forge something else is used for generating the signature. @andres-blanco I think has done something in this direction in the past. Also, there are other people aronud this repo that could help. |
Hey! If you want to use an external signature you can do it by passing a custom function as a key to forge when building the p7 message. You can check how it's done for pkcs11 here:
You may need to do some byte prepending, check this: https://stackoverflow.com/a/47106124 |
I tried to hook your code using pcks 11 but I notice md.digest() value changes each time I run the code despite inputs are the same. My idea was to call the external service provider who will sign this value and return it. Is it normal md.digest() value change with same PDF input? |
This issue has been automatically marked as stale because it has not had activity in the past 90 days. It will be closed if no further activity occurs. Thank you for your contributions. |
This issue has been automatically because it was stale. |
@joelviel have you found a workaround for your requirement. I have do something similar to that |
Hi @tafelito, Yes I found the solution, I built the CMS with the lib jsrsasign (not forge, it does not support ECDSA) ans then overwrite the signature value computed by the external provider.
pdf object definition is attached |
thanks @joelviel for showing your solution In my case, I don't have a certificate, my external provider expects a hash and returns the signed signature I have a similar solution made in Java using PDFBox where it only does this ExternalSigningSupport externalSigning = pdDocument.saveIncrementalForExternalSigning(pdfFOS); and then it creates the hash I send the external provider like this byte[] content = IOUtils.toByteArray(externalSigning.getContent());
MessageDigest md = MessageDigest.getInstance("SHA256", new BouncyCastleProvider());
digestA = md.digest(content);
// this saves the file with a 0 signature
externalSigning.setSignature(new byte[0]);
// remember the offset (add 1 because of "<")
int offset = signature.getByteRange()[1] + 1;
String hashToBeSigned = new String(Base64.encode(digestA)) Also, how did you come up with the I'm trying to figure out how would this translate to the examples used with |
You will need to change from that line |
What do you mean by that? because you are creating the How would you use And how did you come up with the signatureLength number? is that a random length? Thanks for the help by te way |
One more thing In your example you assume that the response from the external service is right after hashing the document. In my case that could happen in some other time, how would you load the signature coming from the service later on? |
The value you need to sign is dSignedAttrs not the whole signedData object. You can use a dummy certificate as a first step, dSignedAttrs wont be affected. But you need to update the certificate when you will have it to produce a valid signedData (i.e. CMS). I suppose with such method signedData.signerInfoList[0].setSignerIdentifier(certPEM). signatureLength will depend on what you use for the signature algo, in my case, SHA256withECDSA. For your last question: use a dummy certificate to generate the value to be signed (dSignedAttrs), and update signedData attributes (signerInfoList[0].setSignerIdentifier(certPEM) and signerInfoList[0].dSig.hV) when you have the response of your provider |
@tafelito read the note regarding the signature length in our readme. |
So If I create the signedData in a step 1, then step 2 (apply the response from the provider) I won't have access to that variable since this happens in a different time. If i create the signedData object again in step 2, will it be the same? Otherwise, how do I get access to the signedData? |
TL:DR It will be the same. Everyone in the process (signer and verifier) is relying on the signedData not being modified. This is exactly what you prove with applying a signature: document was not altered since it was signed. This is exactly what the verifier will check. They will construct the signed data, generate a hash, check the signature and also check that the hash that was signed is the same they have constructed. |
Hey joelviel, I'm trying to do the same kind of thing but I can't get a valid signature to be inserted in the pdf. Can you explain what format the dSignedAttrs is and what format the signedData.signerInfoList[0].dSig.hV is supposed to be ? Cheers |
Hi @jchapelle , example of signature by external service (smartcard in my case): |
Great, thanks for the feedback.
What is the format of
3169301806092a864886f70d010903310b06092a864886f70d010701301c06092a864886f70d010905310f170d3231303732333038313833315a302f06092a864886f70d010904312204202c2c0a3e069410fb2f747d0225ec453e90f8c8c82847999e088baa589ca80a0b
?
Is it an hex ? Or a Sha256->hex ? Or an hex->sha256 ? Or an sha256 ?
…On Fri, Jul 23, 2021 at 10:37 AM Joel Viellepeau ***@***.***> wrote:
Hi @jchapelle <https://github.com/jchapelle> ,
example of value of dSignedAttrs:
3169301806092a864886f70d010903310b06092a864886f70d010701301c06092a864886f70d010905310f170d3231303732333038313833315a302f06092a864886f70d010904312204202c2c0a3e069410fb2f747d0225ec453e90f8c8c82847999e088baa589ca80a0b
It is asn1 value that can be parsed on https://lapo.it/asn1js/ to see its
content (signingTime, hash of the PDF with placeholder, ...)
example of signature by external service (smartcard in my case):
30650231008506d2bc16fda88c71477fa98864e7cd6e2b29a2b23cceac241b20060d08d265b1c526d8095145ec0715e2038e8341480230140d57364f5f3090a6be90677dcfc4843007cde102c8431e8b4d7cdb818285f4fa59971c522432b825350fe0b4479f35
It is asn1 value that can be parsed on https://lapo.it/asn1js/ to see its
content (ecdsa signature i.e. 2 big integers). External service may return
a concatSignature, this function
KJUR.crypto.ECDSA.concatSigToASN1Sig(concatSig) can help to convert to ASN1
format
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#46 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABPAMXJVA3UEN6LILF7RJ7TTZES3LANCNFSM4JWPPDEA>
.
--
Jean Chapelle
|
Hi @joelviel, Thank you for your provided solution. But I guess since the post, the jsrsasign library has been updated and it no longer supports these
Is detached can probably be set by passing datached = true in params object. Do you have any idea in this regard? P.S. This is the error (given I change the line isDetached with detach=true):
|
Hello, |
@sbsatter @kacimi03hamza Have you guys found any solution? |
Hi,
The application is great but in my case I don't have access to a p12 certificate containing a private key to build the CMS. I only have access to an external provider that takes a hash I give him as input and return user certificate as well as signature of the hash in response (never access to the private key from my point of view). Would it be possible to achieve the construction of the signature to be inserted in the PDF with such external provider?
Thank you for your help
The text was updated successfully, but these errors were encountered: