I am signing some data with a self signed X509Certificate in c#. Signature results as a binary byte[]. I want to save this signature to a pkcs#7 format file with extenstion .p7b. When I save this using FileStream as required. It generates an invalid p7b file.
Can anyone help save this signature as a valid external file? Or point out if there is something wrong with the approach?
// EDIT: Adding the code as asked by Eugene Mayevski
// Open Store Location & fetch certificate
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
X509Certificate2Collection certifcates = store.Certificates;
X509Certificate2 certificate = certifcates[0];`
// fetch private key
string publicKeyString = certificate.GetPublicKeyString();
RSACryptoServiceProvider privateKey = certificate.PrivateKey as RSACryptoServiceProvider;
// get binary of data & sign it.
byte[] buffer = Encoding.Default.GetBytes("Sample data to sign. Although it would be a document.");
byte[] signature = privateKey.SignData(buffer, new SHA1Managed());
You are not generating a Cryptographic Message Syntax (CMS) message format which is defined in PKCS#7. You generate just the signature, which can be placed in the container format.
To create a CMS formatted message yourself, please take a look at the Microsoft documentation or use the C# version of Bouncy Castle.
Related
I have no expertise with cryptography, i'm trying to decrypt a JWE payload in ASP.net core C#, the information that i have is the encryption was performed with RSA-OAEP-256 and A256GCM, so i'm using Jose libraries do deal with cryptography, the code is like:
eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.rb3as5DV3PjfYM9cmxO1uE_OaLBt_gFMG9oe1iW_8999KNXEcxAuENaAJgD0fIWdrYD0UwDfkPxzG2cKy3SkvhQE5af7HNDuJBK7p_jjWZMNxtLO3IWCVbcYmH8r-TJEf4MPrDQi_0wP0QLIqH9aR3EVzRdkZ0tn1f8uSsaRlv7rXX_09mPME8V3y7dIDVAKJ0upvJvuyjnsNuAxXVAKvXjNdesKE_GMc3P5ZH6tOBb78a3uLyTOVf-itdR0f2Y7932QPnWbOM1d45mYARUK8Q28IHlKnyhntkA9YP8HQfvFdyMnAKhzPiybSU3Hg1U6wOh6qeYOqN4IIUedzZz__HFZZLpfPJHUacEXfgOWlPO3ZryMxN9v13pDG223oHl-9zbCOdtNsU3igOWlDM4094MECfpYWWem9cuEnbADjsyqVaq0l3CoL8MLUvDKpEjgI7ezopX0UFOlTWXjDxK-EmWeHOJlUAOjRJKUtmJBhiqtjY4quWsTO5xRzX-_fPyFw2Cql2T2_03FDNgZY6u8GpvmBR3f9E1jXqzNI36vbIdtBa6l0tksOPBnLeG070boMdViKMdUxAjzCW1EcUvaXo_vgOZ-ZU8_loOvGBOYmzE6myesQCMDaHXrSJROoR-G5lk5OO-hED6KWUptkqKI5vAuAHGuojq0_1d2YT4X4e8._jpZ8zc1XWIEFVmu.TKbdl02R_2q6-QwtW4cnUiNDoXhFX_fkTDxrhxofM8BhLTMhMk1cx3jvSPJADftBd5NgHghOouZePw_NwapFpNUwgFq__QvPVKcw6QQwU1IKcuh-ShfSJRtr9oVC93zQprZSvgLJsf5K-46sbjnEBc6dzCsL07r3M9fbg4XwaJyRW7iriLTXFbFEd-CbsqlGgZupHGUbn0W_h5PVYTuwAp4I7wyp_k2xF0i9MQRcLk04fm--zdwYo7-FfM3yfsz129OXzpH7tp6c_dl-5D53_cleLFLAIn1BNnDwVFfKIPkjbjz8_NzGoXWWESW8DP00Z2Of4qVgdhtBWunduriM7NyDWaiDWgePt3qX0A3nvSp6bIp9sXdZYiuGVM3z7-iMb-oJPsj1Abx5MuRHpbvovNLHY89QnV8Qf43TCUOGxpgiNcULd4QxeLn2NmXcmbxlFVxhGHxq44XHF0A14dEiWSYp4001T7lun-yv3DPZuiGiO-L4iKHZT-gnHAzjaDIyXVo5JsL1qWGVi59DJneQrnyjodZs7ESCUIbOASJ5SJ9QtSOu-uyvKVdyK6Tfw9-cGNXAzDBAOBmHcnxMOtWcZ6AscDJhpI_2quoktpTD9GkEM0gItKZ5W3r99i8t_RoZCakBdBY6D5gwVg4yFsJyb1YvqsYsH1X8MQBPdrVBTc4DUT0M0ucpfl5bV3nlMxxEffCyk-jbNNXid9_kOjq4Xv3-pHO4qJUQpJvRYIvGqyC0Ep1swo3-gbsUIjtEfyLlf2JkcDIM5WkV_iSvEbjch9lceTMKzjQVZgMnDWPvTtEvAZCXUxbRu9wE9fuX9F2W-yJ_DyB0o871IOhdDi0VyQcipQ2wkvuZecu9uqLFGtVk5NaPxYq0uOyaDQ3QzDwucAMwalaXPua9qjhLjM6TCePgn_ncVdN5jckMXo--RRAX3o4G1Hm8_xcJ6Amcvl8vsb7hUTdXY6um6CT-WDHbi-FQgMyyn-vlC64NJdngvT3uWvcKETS8UoKhp78nFDy20qWXIqSzxwi7rf60OL7vPZ_6McVfXORTbMjxvGRTT5skgkY58B5VPvB1c6vN12tKN3E3lqbJCpzass0rSzbfBxdRDg-PIV-Nuv0S-ch9aUxA5h6cMrYBZMQuiV-RO3EoqfQSU0JNGJuGir8mQAKuI5pJwROKrn1cCAaTSrcueobXz_ppJgZdxzjh_dUzZhfUrrE7DqJgPqHbuEPju7ViB39iPLsiniDz3W1iOhQKSbFDNzLmG_yzjKv1jF90onqIyo_mLN3kVlxHyvgP4MA8405OJCR_Cqmob0djhkiRsJCfNWUuVmmq0q0YPTfFIAn_R9A9Zdlwd8Ybg88_RKegLMwySgvfWT27w2OwGMQX6kCrPxV5pWS57lgmPiflq-R1H1uHXvBDoXySx3Uzv1J2ElzvtQGVufZFBznnirsQI87cwxSz76gWiVelf4GNJzRme3O1XRPhmlMlTBWCHOASRxTo9mM964oHc5g3cIRWrzNFppTV_FkJQ6cwPFYYjFdSA3Hh1w8_RxCxyXncsunAZoniCgV6KEBN7A5KybKMu424JQqWqdlKQqHBW7XLdqMnMH-ryzie22fGmIn4RrT5ha6ZI43rvLREt_4dYJJpmh4yw1f7Bh-8mIuKd1ha3lERWP0qZhSR6sSsCHob_UTe4JW_KwVT0om4FAgMzbLoKoZf1v01QHHn0ISSH9cvtgwv8TObcleMkEYrDJ_MxsSxOKm-B7VoKFDEhtns0ybZA_QYEK40voAzhrGO4CPjsOR7tWKIUFk3veNJRxmixBeGVP7Up7KAvXk7wAhRg060MzZ0Gf4kaWi6IS-H_hWSPYbb0NO0IQRcGYFXALt58p0hO61HpUqG5gnQGiceiMnj1DVKIVAbtnUhB_rGcrePPCKT_TQIeCyO4FRjtHw73iYePZgacVEJDGOqthPlVWJpKF9IWeUu5Ngqc3j6L75bQ4uuvUGVHAORbH3bzXoxxqx4hjU2kI0KvQwGs0VC6rCCgC2GCqJmn3-W0jxir9Mw3VBMaBOOpslv-FSMLriL4UX1solBR3pZ7bCm1vGCUooaj9tG0Pp4n6dwqGz54hkJ5vgYX5xEKZMYYJxhhKomRFNzvhJtli9qe4lNLUsMHEnwcs-BX1tMi7JSOxmPm5BNT_A7qYeRj4dJh4cR926geYdQpcXHhYC9qyNXuqsLG5Qf88rPqMeQerwBmxcwGbTUh2eUpSu4dZZzWuCUiG92Fb55UBtElxZ0mDsQ6SPso6g44oaBNaBbOJ1DnigSE6n1X-yz2HyRjYKHLCpbSHz2xDpQaHSUMVuHphOlS69Wn0Mwb_HljnQU0S34HJya1-zivBIDepkmt3_9EhLy3La872n3H1IEzkaNX7cjCr77imU2lQ32G1iwbFAo4FvJfkJhYwP2xLh1Q38GeE_2vsiQlu1iFr3Fs_Wxv-hYW6rnAz1B_1MSOI0slWMQywIhqZ7dbyyWv_S-oxecVneZ4LlSW-hxCYJGtrsGJtnEaRHVYZJ-N-MjwBm9nJU4P8mY9Nz9MPbWbovb8gJ5DLXFppZjReRk2A2zHTGKzav6Q0DYKI0NGmSDHJW6UbSjVzBBJe2r85NS4u5HGS_wyEhXXnMtJZdn6VBQj9AEY4Jrt2xZzCRoqWlUI46uMObvWq5qvkKCPcSLKyrHEIigbR3JmW3zzDNvc39RmiC6cbJ0Ypb-G0D4CNwdV2bemLzs29NIWms75cqMHxlkyKOqEX5UsYlGBhra_kM.vykYzq6TQ8ApQdyREGo6-g
var jwtSettings = new JwtSettings();
jwtSettings.RegisterMapper(new JwtPayloadConverter.JsonMapperJwt());
var decodedJwt = Jose.JWT.Decode(paylaodRetornoStone2, rsa, Jose.JweAlgorithm.RSA_OAEP_256, Jose.JweEncryption.A256GCM, jwtSettings);
when i try do decrypt the payload, i'm getting this error: specified padding mode is not valid for this algorithm.
the specific part of code that is throwing this exception is the:
byte[] cek = keyManagement.Unwrap(encryptedCek, key, jweAlgorithm.KeySize, header);
the implementation of RsaOaep256KeyManagement is doing this:
return Ensure.Type<RSA>(key, "RsaKeyManagement algorithm expects key to be of RSA type.").Decrypt(encryptedCek, RSAEncryptionPadding.OaepSHA256);
it seens that paddind mode is right, anyone have an idea to how fix this error?
I am trying to sign a PDF with BouncyCastle CMS. Signing works, but Adobe Reader tells me it is not LTV-ready.
As far as I can see, the CRLs are embedded in the CMS SignedData. The certficates are embedded too. A timestamp also is embedded.
The signature is a detached signature and put in the "reserved space".
Why is the signature still not LTV-ready? Am I doing something obvious wrong?
Signed Test-PDF: http://www.filedropper.com/outputx
Code:
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
// CertificateChain
List<Certificate> certList = Arrays.asList(certChain);
try {
Hashtable signedAttrs = new Hashtable();
X509Certificate signingCert = (X509Certificate) certList.get(0);
gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC")
.setSignedAttributeGenerator(new AttributeTable(signedAttrs))
.build("SHA256withRSA", privKey, signingCert));
gen.addCertificates(new JcaCertStore(certList));
boolean embedCrls = true;
if (embedCrls) {
X509CRL[] crls = fetchCRLs(signingCert);
for (X509CRL crl : crls) {
gen.addCRL(new JcaX509CRLHolder(crl));
}
}
// gen.addOtherRevocationInfo(arg0, arg1);
CMSProcessableByteArray processable = new CMSProcessableByteArray(IOUtils.toByteArray(content));
CMSSignedData signedData = gen.generate(processable, false);
if (tsaClient != null) {
signedData = signTimeStamps(signedData);
}
return signedData.getEncoded();
} catch (Exception e) {
throw new RuntimeException(e);
}
In interoperable PDF signatures there are two ways to add validation related information, and neither of them uses the default CMS way of adding CRLs that your code uses.
Adding Pre-Fetched Data In Signed Attributes
The old, ISO 32000-1 style "PKCS#7 Signatures as used in ISO 32000" (later based on CMS instead of PKCS#7) are specified to include revocation information in a dedicated signed attribute for an OID registered by Adobe:
12.8.3.3.2 Revocation Information
The adbe Revocation Information attribute:
adbe-revocationInfoArchival OBJECT IDENTIFIER ::=
{ adbe(1.2.840.113583) acrobat(1) security(1) 8 }
The value of the revocation information attribute can include any of the following data types:
Certificate Revocation Lists (CRLs), described in RFC 3280 (see the Bibliography): CRLs are generally large and therefore should not be embedded in the PKCS#7 object.
Online Certificate Status Protocol (OCSP) Responses, described in RFC 2560, X.509 Internet Public Key Infrastructure Online Certificate Status Protocol—OCSP (see the Bibliography): These are generally small and constant in size and should be the data type included in the PKCS#7 object.
Custom revocation information: The format is not prescribed by this specification, other than that it be encoded as an OCTET STRING. The application should be able to determine the type of data contained within the OCTET STRING by looking at the associated OBJECT IDENTIFIER.
adbe's Revocation Information attribute value has ASN.1 type RevocationInfoArchival:
RevocationInfoArchival ::= SEQUENCE {
crl [0] EXPLICIT SEQUENCE of CRLs, OPTIONAL
ocsp [1] EXPLICIT SEQUENCE of OCSP Responses, OPTIONAL
otherRevInfo [2] EXPLICIT SEQUENCE of OtherRevInfo, OPTIONAL
}
OtherRevInfo ::= SEQUENCE {
Type OBJECT IDENTIFIER
Value OCTET STRING
}
(Obviously this is merely Pseudo-ASN.1...)
As this structure is the value of a signed attribute, revocation information must be fetched before signing to be added like this.
Adding Data In Document Security Stores (DSS)
For their PAdES signatures ETSI specified extra PDF structures to be added to signed PDF documents which can carry extra validation related information, see ETSI EN 319 142. These structures later were integrated in ISO 32000-2:
12.8.4.3 Document Security Store (DSS)
The document security store (DSS), when present, shall be a dictionary that shall be the value of a DSS key in the document catalog dictionary (see 7.7.2, "Document catalog dictionary"). This dictionary may contain:
an array of all certificates used for the signatures, including timestamp signatures, that occur in the document. It shall also hold all the auxiliary certificates required to validate the certificates participating in certificate chain validations.
an array of all Certificate Revocation Lists (CRL) (see Internet RFC 5280) used for some of the signatures, and
an array of all Certificate Status Protocol (OCSP) responses (see Internet RFC 6960) used for some of the signatures.
a VRI key whose value shall be a dictionary containing one VRI dictionary (validation-related information) for each signature represented in CMS format.
Any VRI dictionaries, if present, shall be located in document incremental update sections. If the signature dictionary to which a VRI dictionary applies is itself in an incremental update section, the DSS/VRI update shall be done later than the signature update. The inclusion of VRI dictionary entries is optional. All validation material referenced in VRI entries is included in DSS entries too.
...
As you can read already here, this structure is designed for adding information after signing. This goes along with the ETSI favoring revocation information generated after the signature for validation.
And In PDFBox
You mention PDFBox in your tags, so you appear to use PDFBox for signing.
To add pre-fetched validation data to the signed adbe-revocationInfoArchival attribute, you merely have to add an attribute as defines above to the signedAttrs of your code.
To add data in document security stores (DSS) you can use the code of the PDFBox example AddValidationInformation as mentioned by #Tilman in a comment.
I have a signed pdf with Adobe signature well done. My problem starts when I want to download this document.
Via webmethod I get the bytes of the signed file. Until here there is no problems.
If I try to save the file in my server, when I open the file everything is correct. But if I try to download it when I open it the signature is wrong.
This is the error in adobe reader:
"The scope of the signed data is defined by a range of unexpected bytes.
Details: The range of bytes of the signature is invalid"
This is the way I download the file:
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename= Factura.pdf");
HttpContext.Current.Response.AddHeader("Content-Length", newStream.Length.ToString());
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.BufferOutput = true;
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.OutputStream.Write(newStream.GetBuffer(), 0, newStream.GetBuffer().Length);
HttpContext.Current.Response.OutputStream.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
Can anyone help me with this problem?
You are sending more bytes than thos advertised in the header. Do newStream.ToArray() and only use the byte array. Other thing to check is if you really have all the bytes in newStream, save it to a file to check (from the ToArray().
I have a string encrypted in PHP using following code
function encrypt($string, $publicKey)
{
openssl_public_encrypt($string, $cryptedText, $publicKey);
return base64_encode($cryptedText);
}
$publicKey = file_get_contents('public.crt');
$encryptedText = encrypt('Test', $publicKey);
This works fine in PHP, i am able to encrypt/decrypt using public/private key pair.
The encryptedText is sent to iOS application where i want to decrypt the same string, i tried with multiple approaches and nothing seems to be working, any pointer to do the following is appreciated.
Decrypt OpenSSL encrypted string received from PHP in Objective-C
Encrypt and send data to PHP for Decrypting (should support openssl_private_decrypt)
I used this library for iOS which worked perfectly.
https://github.com/jslim89/RSA-Example
I've just sign document. and Add LTV too (with Document Secure Story and TSA); but adobe reader tells me that LTV is not enabled.
I found the problem. Adobe reader tells me that OCSP is not embedded in the document.
After adding time stamp I just create DSS dictionary and add certificates and ocsp responses.
PDDocumentCatalog catalog = template.getDocumentCatalog();
COSDictionary catalogDictionary = catalog.getCOSDictionary();
COSDictionary dssDictionary = new COSDictionary();
COSArray cosOcsps = CertUtils.getOcspResponseCosArray(ocspResp);
COSArray cosCerts = CertUtils.getCertificateCosArray(certs);
dssDictionary.setItem(COSName.getPDFName("Certs"), cosCerts);
dssDictionary.setItem(COSName.getPDFName("OCSPs"), cosOcsps);
catalogDictionary.setItem(COSName.getPDFName("DSS"), dssDictionary);
is not that enough to add OCSPs?
I sign document like Pades-BES. does it needs VRI? I know that id does not need.
that's sample
PDF Document
The specification ETSI TS 102 778-4 (aka PAdES part 4) in Annex A.1 Document Security Store requires the value of the OCSPs entry in a DSS dictionary to be
An array of (indirect references to) streams, each containing a BER-encoded Online Certificate Status Protocol (OCSP) response (see RFC 2560 [8]). This array contains OCSPs that may be used in the validation of any signatures in the document.
You, on the other hand, only used an array of the BasicOCSPResponse objects which were contained in the original OCSPResponse objects you received.
OCSPResponse ::= SEQUENCE {
responseStatus OCSPResponseStatus,
responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
ResponseBytes ::= SEQUENCE {
responseType OBJECT IDENTIFIER,
response OCTET STRING }
For a basic OCSP responder, responseType will be id-pkix-ocsp-basic.
The value for response SHALL be the DER encoding of BasicOCSPResponse.
BasicOCSPResponse ::= SEQUENCE {
tbsResponseData ResponseData,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING,
certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
(from section 4.2.1 ASN.1 Specification of the OCSP Response of RFC 2560)
Probably you were not aware that you only used this inner object because many security libraries after requesting an OCSP response unwrap the original OCSPResponse, check the contained OCSPResponseStatus, and (if it indicates success) only return the contained BasicOCSPResponse or (otherwise) throw some exception.
If that's the case, you can simply wrap your BasicOCSPResponse in an OCSPResponse using the OCSPResponseStatus value successful (0) before putting it into the document.