Note that there are some explanatory texts on larger screens.

plurals
  1. POAPI secured by PKCS#7 cryptographic message
    primarykey
    data
    text
    <p>I am currently trying to call an API that requires me to put XML data in a PKCS#7 format.<br> This data is posted to the API end point.<br> The response also comes in a form of a PKCS#7 cryptographic messages (MIME-type is application/pkcs7-mime).<br> Some Notes they provide: A cryptographic message doesn't contain any certification chains. Data compression is not used. Data encryption is not used. A cryptographic message is in the OpenSSL PEM format. </p> <p>I have been supplied two certificates. One I created the request for and have the private key, the other supplied to me by the service provider.<br> I have managed to successfully install these certificates, and can communicate with the service.</p> <p>I am seemingly sending data to this API service successfully.<br> Now I'm trying to make sense of the response I'm receiving from this API.<br> This response looks like this</p> <pre><code>-----BEGIN PKCS7----- WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd -----END PKCS7----- </code></pre> <p>(I jumbled up the contents on the off chance there's anything sensitive in there)</p> <p>With this response i need to</p> <ol> <li>Verify the digital signature to ensure that response was sent by the provider</li> <li>Get an Xml formatted message from this response</li> </ol> <p>I have been primarily using the <a href="http://www.bouncycastle.org/csharp/" rel="nofollow">Bouncy Castle</a> library and the MS <a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.pkcs.signedcms%28v=vs.85%29.aspx" rel="nofollow">SignedCms Class</a><br> In summary, I am getting absolutely nowhere.</p> <p>Please can someone guide me on what to do here as I've been at this for about 5 days and am going nowhere fast. </p> <p>Here is some of what I'm doing so far:</p> <p><strong>Make the request</strong></p> <p>Using the HttpWebRequest and HttpWebResponse i am posting data to the service using my supplied certificate</p> <pre><code>var store = new X509Store(StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2 cert = store.Certificates.Find(X509FindType.FindByThumbprint, "ACLKJCLKJCLKJCLKJCLKJCLKJCLKJCLKJCLKJCLK", false)[0]; HttpWebRequest request = null; var uri = new Uri(endPointUri); request = (HttpWebRequest) WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/pkcs7-mime"; request.ContentLength = requestString.Length; request.ClientCertificates.Add(cert); using (Stream writeStream = request.GetRequestStream()) { var encoding = new UTF8Encoding(); byte[] bytes = encoding.GetBytes(requestString); writeStream.Write(bytes, 0, bytes.Length); } string result = null; using (var response = (HttpWebResponse) request.GetResponse()) { using (Stream responseStream = response.GetResponseStream()) { if (responseStream != null) { using (var readStream = new StreamReader(responseStream, Encoding.UTF8)) { result = readStream.ReadToEnd(); } } } } return result; </code></pre> <p>Here I get back the "BEGIN PKCS7" message from above.<br> Now I'm trying to figure out what to do with this</p> <p><strong>MS Signed CMS Class Approach</strong></p> <pre><code>SignedCms signedCms = new SignedCms(); signedCms.Decode(Encoding.Default.GetBytes(resultString)); try { signedCms.CheckSignature(new X509Certificate2Collection(cert1), true); } catch (System.Security.Cryptography.CryptographicException e) { _Log.Error(e.Message) } </code></pre> <p>This throws the exception on "signedCms.Decode" of "ASN1 bad tag value met."</p> <p><strong>BouncyCastle ISigner</strong></p> <p>Here the documentation is non-existent.<br> So first I save my response to a file and use the TextReader object to try test with BouncyCastle</p> <pre><code>using (TextReader reader = File.OpenText(@"c:\temp\resultString.txt")) { PemReader pemRd = new PemReader(reader); ContentInfo d = (ContentInfo)pemRd.ReadObject(); Console.WriteLine(d.ContentType.ToString()); } </code></pre> <p>This returns the result: "1.2.840.113549.1.7.2"<br> From what i can tell, this means its "Pkcs7 Signed Data"<br> Woohoo, something looks like its working.<br> But from here, how do I verify, and how do I extract any information from this</p> <p>My Verify attempt</p> <pre><code>using (TextReader reader = File.OpenText(@"c:\temp\resultString.txt")) { PemReader pemRd = new PemReader(reader); var signature = new CmsSignedData(pemRd.ReadObject()); } </code></pre> <p>Fail - signature is null</p> <pre><code>var store = new X509Store(StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2 cert = store.Certificates.Find(X509FindType.FindByThumbprint, "ACLKJCLKJCLKJCLKJCLKJCLKJCLKJCLKJCLKJCLK", false)[0]; //tried with both certs ISigner signer = SignerUtilities.GetSigner("RSA"); var bouncyx509 = DotNetUtilities.FromX509Certificate(cert1); signer.Init(true, DotNetUtilities.FromX509Certificate(cert1).GetPublicKey()); </code></pre> <p>Fail - need private key to create signer</p> <p><strong>In Closing</strong></p> <p>I hope I have provided enough information to get some help here.<br> Maybe I'm heading in completely the wrong direction. </p> <p>My Questions are:</p> <ol> <li>How do I Verify the digital signature?</li> <li>How do I get an Xml formatted message from this response?</li> </ol> <p><strong>THE SOLUTION</strong></p> <p>Thanks to gtrig, i finally have a solution.<br> Using the MS SignedCms object I had to first remove the Header and Footer form the message, then Convert.FromBase64String</p> <p>Working Solution</p> <pre><code>SignedCms signedCms = new SignedCms(); resultString = resultString.Replace("\n", "").Replace("-----BEGIN PKCS7-----", "").Replace("-----END PKCS7-----", ""); signedCms.Decode(Convert.FromBase64String(resultString)); </code></pre> <p>Now signedCms.ContentInfo.Content contains the reponse Xml message I expect</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload