public SMimeReader(MimeMessage mimeMessage) { this.mimeMultipart = mimeMessage.Body as MultipartSigned; if (this.mimeMultipart == null) { throw new InvalidOperationException("Mime multipart is not a MultipartSigned"); } MimeEntity mime = this.mimeMultipart[1]; // Extracting signature using (var m = new MemoryStream()) { mime.WriteTo(m, true); m.Seek(0, SeekOrigin.Begin); this.signature = m.ToBuffer(); } var contentType = new ContentType(mimeMessage.Headers[HeaderId.ContentType]); String algorithm = contentType.Parameters?["micalg"]; if (algorithm == null) { throw new InvalidOperationException( "micalg parameter not found in Content-Type header: " + contentType); } this.sMimeDigestMethod = SMimeDigestMethod.FindByIdentifier(algorithm); }
/// <summary> /// Creates a new S/MIME message having the supplied MimeType as the "content-type" /// </summary> /// <param name="inputStream"></param> /// <param name="mimeType"></param> /// <param name="digestMethod"></param> /// <returns></returns> public MimeMessage CreateSignedMimeMessage( Stream inputStream, string mimeType, SMimeDigestMethod digestMethod) { MimeEntity mimeBodyPart = MimeMessageHelper.CreateMimeBodyPart(inputStream, mimeType); return(this.CreateSignedMimeMessage(mimeBodyPart, digestMethod)); }
/// <summary> /// Creates an S/MIME message from the supplied String, having the supplied MimeType as the "content-type". /// </summary> /// <param name="msg"></param> /// <param name="mimeType"></param> /// <param name="digestMethod"></param> /// <returns></returns> public MimeMessage CreateSignedMimeMessage( string msg, string mimeType, SMimeDigestMethod digestMethod) { var msgData = Encoding.Default.GetBytes(msg); return(this.CreateSignedMimeMessage(msgData.ToStream(), mimeType, digestMethod)); }
/// <summary> /// Creates an S/MIME message using the supplied MimeBodyPart. The signature is generated using the private key /// as supplied in the constructor. Our certificate, which is required to verify the signature is enclosed. /// </summary> /// <param name="mimeBodyPart"></param> /// <param name="digestMethod"></param> /// <returns></returns> public MimeMessage CreateSignedMimeMessage(MimeMessage mimeBodyPart, SMimeDigestMethod digestMethod) { MimeMessage message = new MimeMessage(); using (var ctx = this.secContentFactory()) { // Algorithm lookup DigestAlgorithm algorithm; if (digestMethod.Equals(SMimeDigestMethod.Sha1)) { algorithm = DigestAlgorithm.Sha1; } else if (digestMethod.Equals(SMimeDigestMethod.Sha512)) { algorithm = DigestAlgorithm.Sha512; } else { throw new NotSupportedException($"Algorithm {digestMethod.GetAlgorithm()} not supported"); } // Signer identification var cmsSigner = new CmsSigner(this.ourCertificate, this.privateKey) { DigestAlgorithm = algorithm }; // Create and sign message message.Body = MultipartSigned.Create(ctx, cmsSigner, mimeBodyPart.Body); // Force signed content to be transferred in binary format MimePart xml = (MimePart)message.BodyParts.First(); xml.ContentTransferEncoding = ContentEncoding.Binary; } // Remove unused headers foreach (var header in message.Headers.Select(x => x.Id).ToList()) { if (header != HeaderId.MessageId && header != HeaderId.MimeVersion && header != HeaderId.ContentType) { message.Headers.Remove(header); } } return(message); }
/// <summary> /// Calculates sha1 mic based on the MIME body part. /// </summary> /// <param name="bodyPart"></param> /// <param name="digestMethod"></param> /// <returns></returns> public static Digest CalculateMic(MimeEntity bodyPart, SMimeDigestMethod digestMethod) { try { byte[] digest; using (var m = new MemoryStream()) { bodyPart.WriteTo(m); m.Seek(0, SeekOrigin.Begin); digest = BcHelper.Hash(m.ToArray(), digestMethod.GetAlgorithm()); } return(Digest.Of(digestMethod.GetDigestMethod(), digest)); } catch (IOException e) { throw new InvalidOperationException("Unable to read data from digest input. " + e.Message, e); } catch (Exception e) { throw new InvalidOperationException("Unable to handle mime body part. " + e.Message, e); } }
public MimeMessage CreateSignedMimeMessage(MimeEntity mimeBodyPart, SMimeDigestMethod digestMethod) { if (mimeBodyPart is MimePart) { ((MimePart)mimeBodyPart).ContentTransferEncoding = ContentEncoding.Binary; } MultipartSigned multipart; using (var ctx = this.secContentFactory()) { // Algorithm lookup DigestAlgorithm algorithm; if (digestMethod.Equals(SMimeDigestMethod.Sha1)) { algorithm = DigestAlgorithm.Sha1; } else if (digestMethod.Equals(SMimeDigestMethod.Sha512)) { algorithm = DigestAlgorithm.Sha512; } else { throw new NotSupportedException($"Algorithm {digestMethod.GetAlgorithm()} not supported"); } var micalg = ctx.GetDigestAlgorithmName(algorithm); var signed = new MultipartSigned(); // set the protocol and micalg Content-Type parameters signed.ContentType.Parameters["protocol"] = ctx.SignatureProtocol; signed.ContentType.Parameters["micalg"] = micalg; // add the modified/parsed entity as our first part signed.Add(mimeBodyPart); var cmsSigner = new CmsSigner(this.ourCertificate, this.privateKey) { DigestAlgorithm = algorithm }; ApplicationPkcs7Signature signature; using (var memory = new MemoryBlockStream()) { // var prepared = Prepare(entity, memory); mimeBodyPart.WriteTo(memory); memory.Position = 0; // sign the cleartext content signature = ctx.Sign(cmsSigner, memory); } // add the detached signature as the second part signed.Add(signature); // Create and sign message multipart = signed; } var message = new MimeMessage(); message.Body = multipart; return(message); }