dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.98k stars 4.66k forks source link

Make SignedCms interoperate with openssl cms -verify #24525

Closed dawud-tan closed 4 years ago

dawud-tan commented 6 years ago

https://github.com/dotnet/corefx/commit/075cec7a82fe2cdec403315c3350b88973119abe I have difficulty in making Detached System.Security.Cryptography.Pkcs.SignedCms.cs interoperate with openssl cms, the openssl command that I execute is openssl cms -verify -in signedCusdec.p7s -certfile kepabeanan.crt -noverify -nointern -no_alt_chains -out verifiedCusdec.txt, it throws following error

Error reading S/MIME message
140484988696384:error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag:crypto/asn1/tasn_dec.c:1112:
140484988696384:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:crypto/asn1/tasn_dec.c:274:Type=CMS_ContentInfo
140484988696384:error:0D0D106E:asn1 encoding routines:b64_read_asn1:decode error:crypto/asn1/asn_mime.c:143:
140484988696384:error:0D0D40CC:asn1 encoding routines:SMIME_read_ASN1:asn1 sig parse error:crypto/asn1/asn_mime.c:442:

Following is my code snippet extracted from AS2MIMEUtilities.cs

ContentInfo contentInfo = new ContentInfo(arMessage);
SignedCms signedCms = new SignedCms(contentInfo, true); // <- true detaches the signature
CmsSigner cmsSigner = new CmsSigner(cert);
signedCms.ComputeSignature(cmsSigner);
byte[] signature = signedCms.Encode();
return signature;

Following is the signedCusdec.p7s file, generated from the above code

Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha1"; boundary="_3ace996b6559464b90b8b436572c6bae_"

--_3ace996b6559464b90b8b436572c6bae_
Content-Type: multipart/report; report-type=disposition-notification; 
    boundary="_94805c60317b4d5baf012c913b6412fc_"

--_94805c60317b4d5baf012c913b6412fc_
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

The AS2 message has been received.
--_94805c60317b4d5baf012c913b6412fc_
Content-Type: message/disposition-notification
Content-Transfer-Encoding: 7bit

Reporting-UA: ASP.NET Core 2.0 Web API
Original-Recipient: rfc822; mendelsontestAS2
Final-Recipient: rfc822; mendelsontestAS2
Original-Message-ID: <github-dawud-tan-RetrofitSmime-26122017175311+0700--4062199134817124179@mycompanyAS2_mendelsontestAS2>
Disposition: automatic-action/MDN-sent-automatically; processed
Received-Content-MIC: e+hBgnF68v4onExp21tBAg==, md5

--_94805c60317b4d5baf012c913b6412fc_--
--_3ace996b6559464b90b8b436572c6bae_
Content-Type: application/pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=smime.p7s

MIIEcgYJKoZIhvcNAQcCoIIEYzCCBF8CAQExDzANBglghkgBZQMEAgEFADALBgkqhkiG9w0BBwGgggLUMIIC0DCCAjkCBEOO/fMwDQYJKoZIhvcNAQEFBQAwga4xJjAkBgkqhkiG9w0BCQEWF3Jvc2V0dGFuZXRAbWVuZGVsc29uLmRlMQswCQYDVQQGEwJERTEPMA0GA1UECBMGQmVybGluMQ8wDQYDVQQHEwZCZXJsaW4xIjAgBgNVBAoTGW1lbmRlbHNvbi1lLWNvbW1lcmNlIEdtYkgxIjAgBgNVBAsTGW1lbmRlbHNvbi1lLWNvbW1lcmNlIEdtYkgxDTALBgNVBAMTBG1lbmQwHhcNMDUxMjAxMTM0MzE1WhcNMTkwODEwMTM0MzE1WjCBrjEmMCQGCSqGSIb3DQEJARYXcm9zZXR0YW5ldEBtZW5kZWxzb24uZGUxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZCZXJsaW4xDzANBgNVBAcTBkJlcmxpbjEiMCAGA1UEChMZbWVuZGVsc29uLWUtY29tbWVyY2UgR21iSDEiMCAGA1UECxMZbWVuZGVsc29uLWUtY29tbWVyY2UgR21iSDENMAsGA1UEAxMEbWVuZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1QYrk0Zb4MsdAbkzFfLp2mZOg6H1ZpWRpyeMm+1ozNiqA/zeDPnzgoAEjmDYhpR3BID1XsvOA+pzixH5YbOQFZ0Z+SNVTMxQ0tDLQYsylKBneynDr11iOCBxu2wdkFhEZ0NJJRdY3sS95iHOKFqvdlPeyblrMnrBYZW9vcN8fUECAwEAATANBgkqhkiG9w0BAQUFAAOBgQCucT5rhqerUTOPyUHf1ia8gCknTM1QyKUAReS3nmIiYuTsBqxvLQ72jEFCgOTGPyUq/IlnB91mrNcXuo11V6eMFNQ5+RDyz600XM8R4MXhnp4jtDQeMrQFk/bbbrt/lUeG/rA/eUgn82iATpALtcwzb1EQNxf++hbo6AqCZrXBVjGCAWIwggFeAgEBMIG3MIGuMSYwJAYJKoZIhvcNAQkBFhdyb3NldHRhbmV0QG1lbmRlbHNvbi5kZTELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJlcmxpbjEPMA0GA1UEBxMGQmVybGluMSIwIAYDVQQKExltZW5kZWxzb24tZS1jb21tZXJjZSBHbWJIMSIwIAYDVQQLExltZW5kZWxzb24tZS1jb21tZXJjZSBHbWJIMQ0wCwYDVQQDEwRtZW5kAgRDjv3zMA0GCWCGSAFlAwQCAQUAMA0GCSqGSIb3DQEBAQUABIGAznTWUclwMZW6PxrRqQd0JSBOv5Ge66Ip46RpYDQpQV/4Jo61+cB16ytqn07YXoz3DWr3MhcbiYz+3rjO3DPrBcLpg546gKgjnezQfDX5TJtSpUdVqjztFNiYwwUT/iDog606AUB8Evfcrnw88aOnNK/So3zNnGjrDUeUZFP1WAk=

--_3ace996b6559464b90b8b436572c6bae_--
bartonjs commented 6 years ago

@dawud-tan Does your snippet work from .NET Framework, but not .NET Core; or does it fail from both?

dawud-tan commented 6 years ago

@bartonjs It fail from both, what I do is just put the base64 encoded of signedCms.Encode() into the body of application/pkcs7-signature, then concatenate all of the required string to form standard S/MIME (RFC 3851), following is the snippet of my .csproj file. mm, could you point me to an example of SignedCms that could be verified with openssl cms -verify please?

<TargetFramework>net471</TargetFramework>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
bartonjs commented 6 years ago

I'm pretty sure OpenSSL is upset with you for violating the base64 encoding rule that says no more than 76 characters per line.

https://tools.ietf.org/html/rfc2045#section-6.8

The encoded output stream must be represented in lines of no more than 76 characters each. All line breaks or other characters not found in Table 1 must be ignored by decoding software. In base64 data, characters other than those in Table 1, line breaks, and other white space probably indicate a transmission error, about which a warning message or even a message rejection might be appropriate under some circumstances.

Adding a bunch of line breaks in your message to limit the base64 to 76 characters per line I then get

$ openssl cms -in smime.msg -verify
Verification failure
139997058221720:error:2E099064:CMS routines:CMS_SIGNERINFO_VERIFY_CERT:certificate verify error:cms_smime.c:287:Verify error:self signed certificate

Which means it has now processed the message.

dawud-tan commented 6 years ago

@bortonjs ah, I'm sorry for being naive, thanks for the url spec :smile:, it's my fault. This issue could be closed.

string sig = Convert.ToBase64String(signedCms.Encode());

I didn't break the output of the above call into 76 chars. So, the problem it's not related with SignedCms class, but, does .NET Framework or .NET Core do have S/MIME support out of the box?

self-signed cert error is supposed to be happen. What I do in my environment is just openssl smime -verify -in signedCusdec.txt -noverify -nointern -nochain -certfile kepabeanan.crt -out verify.txt.

bartonjs commented 6 years ago

does .NET Framework or .NET Core do have S/MIME support out of the box?

Not that I'm aware of. @davidsh is there S/MIME anywhere in System.Net.Mail?

davidsh commented 6 years ago

Not that I'm aware of. @davidsh is there S/MIME anywhere in System.Net.Mail?

There is no S/MIME support in System.Net.* APIs in neither .NET Framework or .NET Core.

jnm2 commented 6 years ago

I like https://github.com/jstedfast/MimeKit.