Well, not exactly….. SMIME is a very nice spec, it’s widely supported, and there are SMIME libraries for most development environments. The problem is that the RFC822 SMTP-vs-local line- endings nastyness combines with MIME canonicalization and libraries/mail UAs idiosyncracies to make SMIME messages very fragile. In the rest of this entry, I briefly describe a couple of SMIME pitfalls I spent quite a few hours debugging recently.
Using OpenSSL (via M2Crypto) to cleartext sign a SMIME message, you get back a valid multipart/signed message that has one problem: the cleartext part of the message has CR+LF line endings, while the rest of the message (pkcs7 signature, SMIME headers) has LF line endings (cf this thread on mailing.openssl.dev). OpenSSL performs MIME canonicalization (ie it converts line endings to CR+LF — SMIME_crlf_copy() in crypto/pkcs7/pk7_smime.c/PKCS7_sign()) on the message before signing it, as per the SMIME spec. The problem is that a message with a mix of CR+LF and bare LF is almost never what you need. If you send the message by SMTP directly after signing it, it should have CR+LF line endings as per RFC822. If you hand off the message to a program like qmail-inject, your message should respect local conventions, ie on Unix have bare LF line endings. This problem becomes apparent when you open a signed message in Outlook or Outlook Express, since the message appears tampered and cannot be verified. If you sign with the “binary” flag, you get no CR+LF line endings but the resulting message cannot be verified unless you perform the MIME canonicalization yourself before signing, getting the same output as in the above situation. A sample of the resulting message, with line endings prefixed to the actual lines (and long lines snipped):
'n' MIME-Version: 1.0 'n' Content-Type: multipart/signed; protocol="application/x-pkcs7-sig 'n' 'n' This is an S/MIME signed message 'n' 'n' ------526F05E052FA5F1DF695C4ABA3E3EF81 'rn' prova prova prova 'rn' prova 123 'rn' 'rn' prova 'n' 'n' ------526F05E052FA5F1DF695C4ABA3E3EF81 'n' Content-Type: application/x-pkcs7-signature; name="smime.p7s" 'n' Content-Transfer-Encoding: base64 'n' Content-Disposition: attachment; filename="smime.p7s" 'n' 'n' MIIGDAYJKoZIhvcNAQcCoIIF/TCCBfkCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3 'n' DQEHAaCCA9gwggPUMIIDPaADAgECAgECMA0GCSqGSIb3DQEBBAUAMIGbMQswCQYD
If you sign SMIME messages with OpenSSL on Unix, you may discover that your messages are valid in Mozilla, but they appear as tampered in Outlook, Outlook Express, and programs using MS libraries to validate them. A search on Google Groups turns up quite a few threads on this topic, none of which unfortunately offer any practical help, apart from generic suggestions regarding line-ending conversions, which do not work. After quite a few hours spent debugging this problem, I could only come up with a practical solution with no theorical explanation: append a single linefeed (a bare LF) to the end of the payload before signing it. Mozilla and OpenSSL keep verifying the resulting SMIME messages, and Outlook stops complaining that the message has been tampered with. I still have to verify the implications of this workaround when you sign a message that includes a SMIME message as a MIME message/rfc822 attachment, since I’ve noticed that signing such a message often breaks the attachment validity.