I’m trying to digitally sign a MultiMIME message using the following code. I wonder if it is correct as I’m experiencing issues if the mails go through a Cisco IronPort email scanner. IronPort tries to remove the signature to append some additional info to the mail but it does not detect that my mails are signed. Therefore it just appends and the signature becomes invalid.
What makes me suspicious about my code is that the envelope for the signed message is set to “SevenBit” but the signature is attached Base64 encoded. But as it works (except the IronPort) issue I assume it is correct.
I can also see thet GetAlternateView() will return the trasfer encoding as “sevenbit” instead of “7bit”. This is obviously wrong and was a known bug in .NET back in 2005 but shouldn’t it be fixed by now?
So the question is: this piece of code below, is it really doing what it is supposed to do?
It gets called wiht the email oMessage being completely prepared and unsigned. Then
oMessage = this.Sign(oMessage);
MailMessage oMail.AlternateViews.Add(oMessage.GetAlternateView());
and the mail gets sent.
/// <summary>
/// Signs the contents of the specified envelope.
/// </summary>
/// <param name="oMessage">The mail content to sign. Can be null.</param>
/// <returns>An envelope which contains a signed mail.</returns>
private Envelope Sign( Envelope oMessage )
{
Envelope oSignedMessage = new Envelope( "multipart/signed; boundary=\"" + this.sBoundary + "\"; protocol=\"application/x-pkcs7-signature\"", TransferEncoding.SevenBit );
//oSignedMessage.Append( "\r\n" );
// Open a new envelope which will contain the original mail content and the signature
oSignedMessage.Append( "--" ).Append( this.sBoundary ).Append( "\r\n" );
// Append the content to the new envelope
// Can be null if no plain text or html content and no attachments.
if ( oMessage != null )
{
oSignedMessage.Append( oMessage );
// Don't need this anymore
oMessage.Dispose();
}
oSignedMessage.Append( "\r\n" );
// Create a second part in the same envelope for the signature
oSignedMessage.Append( "--" ).Append( this.sBoundary ).Append( "\r\n" );
oSignedMessage.Append( "Content-Type: application/x-pkcs7-signature; name=\"smime.p7s\"\r\n" );
oSignedMessage.Append( "Content-Transfer-Encoding: base64\r\n" );
oSignedMessage.Append( "Content-Disposition: attachment; filename=\"smime.p7s\"\r\n" );
oSignedMessage.Append( "\r\n" );
// Create the signature..
byte[] aSignature = this.GetSignature( oMessage );
// ..and append it
oSignedMessage.Append( Convert.ToBase64String( aSignature, Base64FormattingOptions.InsertLineBreaks ) );
oSignedMessage.Append( "\r\n\r\n" );
// Close the whole envelope
oSignedMessage.Append( "--" ).Append( this.sBoundary ).Append( "--\r\n" );
return oSignedMessage;
}
The issue has been found. It was an additonal linebreak in the MIME content. MIME formats are very picky about linebreaks and newlines. One too much or one too less and you’re screwed.
The other problem regarding “7bit” vs. “sevenbit” was that Microsoft’s enumerator for the transfer encoding is called “SevenBit”. At one place in the code “SevenBit.ToString()” was used which resulted in the string “sevenbit” instead of the enumerator value “7bit”.