/// <summary> /// Initializes a new instance of the <see cref="SendOperation"/> class. /// </summary> /// <param name="stage">The pipeline stage.</param> public SendOperation(ElasticsearchPipelineStage stage) { mStage = stage; mContentStream = new MemoryBlockStream(ArrayPool <byte> .Shared); mRequestContentWriter = new Utf8JsonWriter(mContentStream, mJsonWriterOptions); IsFull = false; }
/// <summary> /// Resets the content stream and the <see cref="IsFull"/> property. /// </summary> private void ResetContentStream() { mContentStream?.Dispose(); // returns buffers back to the pool mContentStream = new MemoryBlockStream(ArrayPool <byte> .Shared); mRequestContentWriter = new Utf8JsonWriter(mContentStream, mJsonWriterOptions); IsFull = false; }
static void LoadContent(MimePart attachment, Stream stream) { var content = new MemoryBlockStream(); if (attachment.ContentType.IsMimeType("text", "*")) { var filter = new BestEncodingFilter(); var buf = new byte[4096]; int index, length; int nread; while ((nread = stream.Read(buf, 0, buf.Length)) > 0) { filter.Filter(buf, 0, nread, out index, out length); content.Write(buf, 0, nread); } filter.Flush(buf, 0, 0, out index, out length); attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit); } else { attachment.ContentTransferEncoding = ContentEncoding.Base64; stream.CopyTo(content, 4096); } content.Position = 0; attachment.Content = new MimeContent(content); }
void LoadContent(MimePart attachment, string fileName) { var content = new MemoryBlockStream(); var filter = new BestEncodingFilter(); using (var stream = File.OpenRead(fileName)) { var buf = new byte[4096]; int index, length; int nread; while ((nread = stream.Read(buf, 0, buf.Length)) > 0) { filter.Filter(buf, 0, nread, out index, out length); content.Write(buf, 0, nread); } filter.Flush(buf, 0, 0, out index, out length); } content.Position = 0; if (linked) { attachment.ContentLocation = new Uri(Path.GetFileName(fileName), UriKind.Relative); } attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit); attachment.ContentObject = new ContentObject(content, ContentEncoding.Default); }
/// <summary> /// Cryptographically signs the specified entity. /// </summary> /// <remarks> /// <para>Signs the entity using the supplied signer and <see cref="SecureMimeContext"/>.</para> /// <para>For better interoperability with other mail clients, you should use /// <see cref="MultipartSigned.Create(SecureMimeContext, CmsSigner, MimeEntity)"/> /// instead as the multipart/signed format is supported among a much larger /// subset of mail client software.</para> /// </remarks> /// <returns>The signed entity.</returns> /// <param name="ctx">The S/MIME context to use for signing.</param> /// <param name="signer">The signer.</param> /// <param name="entity">The entity.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="signer"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static ApplicationPkcs7Mime Sign(SecureMimeContext ctx, CmsSigner signer, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException(nameof(ctx)); } if (signer == null) { throw new ArgumentNullException(nameof(signer)); } if (entity == null) { throw new ArgumentNullException(nameof(entity)); } using (var memory = new MemoryBlockStream()) { var options = FormatOptions.CloneDefault(); options.NewLineFormat = NewLineFormat.Dos; entity.WriteTo(options, memory); memory.Position = 0; return(ctx.EncapsulatedSign(signer, memory)); } }
async Task ConstructMimePartAsync(MimePart part, CancellationToken cancellationToken) { Stream content; bool isEmpty; if (persistent) { long begin = GetOffset(inputIndex); long end; using (var measured = new MeasuringStream()) { isEmpty = await ScanContentAsync(measured, true, cancellationToken).ConfigureAwait(false); end = begin + measured.Length; } content = new BoundStream(stream, begin, end, true); } else { content = new MemoryBlockStream(); isEmpty = await ScanContentAsync(content, true, cancellationToken).ConfigureAwait(false); content.Seek(0, SeekOrigin.Begin); } if (!isEmpty) { part.Content = new MimeContent(content, part.ContentTransferEncoding); } else { content.Dispose(); } }
public ImapReplayCommand(string tag, string command, string resource, bool compressed = false) { CommandBuffer = Latin1.GetBytes(command); Compressed = compressed; Command = command; using (var stream = GetType().Assembly.GetManifestResourceStream("UnitTests.Net.Imap.Resources." + resource)) { using (var memory = new MemoryBlockStream()) { using (Stream compress = new CompressedStream(memory)) { using (var filtered = new FilteredStream(compressed ? compress : memory)) { filtered.Add(new ImapReplayFilter("A########", tag)); filtered.Add(new Unix2DosFilter()); stream.CopyTo(filtered, 4096); filtered.Flush(); } Response = memory.ToArray(); } } } if (compressed) { using (var memory = new MemoryStream()) { using (var compress = new CompressedStream(memory)) { compress.Write(CommandBuffer, 0, CommandBuffer.Length); compress.Flush(); CommandBuffer = memory.ToArray(); } } } }
private static void ParseImplementation(Node node, MimeEntity entity) { var tmp = new Node("entity", entity.ContentType.MimeType); ProcessHeaders(tmp, entity); if (entity is MultipartSigned signed) { // Multipart content. var signatures = new Node("signatures"); foreach (var idx in signed.Verify()) { if (!idx.Verify()) { throw new SecurityException("Signature of MIME message was not valid"); } signatures.Add(new Node("fingerprint", idx.SignerCertificate.Fingerprint.ToLower())); } tmp.Add(signatures); // Then traversing content of multipart/signed message. foreach (var idx in signed) { ParseImplementation(tmp, idx); } } else if (entity is MultipartEncrypted) { throw new ArgumentException("Magic currently does not support decrypting MIME messages"); } else if (entity is Multipart multi) { // Multipart content. foreach (var idx in multi) { ParseImplementation(tmp, idx); } } else if (entity is TextPart text) { // Singular content type. // Notice! We don't really care about the encoding the text was encoded with. tmp.Add(new Node("content", text.GetText(out var encoding))); } else if (entity is MimePart part) { using (var stream = new MemoryBlockStream()) { // Decoding content to memory. part.Content.DecodeTo(stream); // Resetting position and setting up a buffer object to hold content. stream.Position = 0; // Putting content into return node for MimeEntity. tmp.Add(new Node("content", stream.ToArray())); } } node.Add(tmp); }
/// <summary> /// Encrypts the specified entity. /// </summary> /// <remarks> /// Encrypts the entity to the specified recipients using the supplied <see cref="SecureMimeContext"/>. /// </remarks> /// <returns>The encrypted entity.</returns> /// <param name="ctx">The S/MIME context to use for encrypting.</param> /// <param name="recipients">The recipients.</param> /// <param name="entity">The entity.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="recipients"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static ApplicationPkcs7Mime Encrypt(SecureMimeContext ctx, CmsRecipientCollection recipients, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException(nameof(ctx)); } if (recipients == null) { throw new ArgumentNullException(nameof(recipients)); } if (entity == null) { throw new ArgumentNullException(nameof(entity)); } using (var memory = new MemoryBlockStream()) { var options = FormatOptions.CloneDefault(); options.NewLineFormat = NewLineFormat.Dos; entity.WriteTo(options, memory); memory.Position = 0; return(ctx.Encrypt(recipients, memory)); } }
/// <summary> /// Creates a new <see cref="MultipartSigned"/>. /// </summary> /// <remarks> /// Cryptographically signs the entity using the supplied signer in order /// to generate a detached signature and then adds the entity along with /// the detached signature data to a new multipart/signed part. /// </remarks> /// <returns>A new <see cref="MultipartSigned"/> instance.</returns> /// <param name="ctx">The S/MIME context to use for signing.</param> /// <param name="signer">The signer.</param> /// <param name="entity">The entity to sign.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="signer"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static MultipartSigned Create(SecureMimeContext ctx, CmsSigner signer, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException(nameof(ctx)); } if (signer == null) { throw new ArgumentNullException(nameof(signer)); } if (entity == null) { throw new ArgumentNullException(nameof(entity)); } using (var memory = new MemoryBlockStream()) { var prepared = Prepare(entity, memory); memory.Position = 0; // sign the cleartext content var signature = ctx.Sign(signer, memory); return(Create(ctx, signer.DigestAlgorithm, prepared, signature)); } }
/// <summary> /// Cryptographically signs the specified entity. /// </summary> /// <remarks> /// <para>Signs the entity using the supplied signer, digest algorithm and <see cref="SecureMimeContext"/>.</para> /// <para>For better interoperability with other mail clients, you should use /// <see cref="MultipartSigned.Create(SecureMimeContext, CmsSigner, MimeEntity)"/> /// instead as the multipart/signed format is supported among a much larger /// subset of mail client software.</para> /// </remarks> /// <returns>The signed entity.</returns> /// <param name="ctx">The S/MIME context to use for signing.</param> /// <param name="signer">The signer.</param> /// <param name="digestAlgo">The digest algorithm to use for signing.</param> /// <param name="entity">The entity.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="signer"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="CertificateNotFoundException"> /// A signing certificate could not be found for <paramref name="signer"/>. /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static ApplicationPkcs7Mime Sign(SecureMimeContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException("ctx"); } if (signer == null) { throw new ArgumentNullException("signer"); } if (entity == null) { throw new ArgumentNullException("entity"); } using (var memory = new MemoryBlockStream()) { var options = FormatOptions.CloneDefault(); options.NewLineFormat = NewLineFormat.Dos; entity.WriteTo(options, memory); memory.Position = 0; return(ctx.EncapsulatedSign(signer, digestAlgo, memory)); } }
/// <summary> /// Encrypts the specified entity. /// </summary> /// <remarks> /// Encrypts the entity to the specified recipients using the supplied <see cref="SecureMimeContext"/>. /// </remarks> /// <returns>The encrypted entity.</returns> /// <param name="ctx">The S/MIME context to use for encrypting.</param> /// <param name="recipients">The recipients.</param> /// <param name="entity">The entity.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="recipients"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.ArgumentException"> /// Valid certificates could not be found for one or more of the <paramref name="recipients"/>. /// </exception> /// <exception cref="CertificateNotFoundException"> /// A certificate could not be found for one or more of the <paramref name="recipients"/>. /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static ApplicationPkcs7Mime Encrypt(SecureMimeContext ctx, IEnumerable <MailboxAddress> recipients, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException("ctx"); } if (recipients == null) { throw new ArgumentNullException("recipients"); } if (entity == null) { throw new ArgumentNullException("entity"); } using (var memory = new MemoryBlockStream()) { var options = FormatOptions.CloneDefault(); options.NewLineFormat = NewLineFormat.Dos; entity.WriteTo(options, memory); memory.Position = 0; return((ApplicationPkcs7Mime)ctx.Encrypt(recipients, memory)); } }
public void Setup() { var bytes = new byte[9 * 1024]; int position = 0; random = new Random(); random.NextBytes(bytes); // this is our master stream, all operations on the chained stream // should match the results on this stream master = new MemoryStream(bytes); mbuf = new byte[4096]; buf = new byte[4096]; // write the content into the memory block stream in random chunks blocks = new MemoryBlockStream(); Assert.IsTrue(blocks.CanRead, "Expected to be able to read from the memory block stream."); Assert.IsTrue(blocks.CanWrite, "Expected to be able to write to the memory block stream."); Assert.IsTrue(blocks.CanSeek, "Expected to be able to seek in the memory block stream."); Assert.IsFalse(blocks.CanTimeout, "Did not expect to be able to set timeouts in the memory block stream."); while (position < bytes.Length) { int n = Math.Min(bytes.Length - position, random.Next() % 4096); blocks.Write(bytes, position, n); position += n; } blocks.Seek(0, SeekOrigin.Begin); }
public void TestStreamArguments() { using (var stream = new MeasuringStream()) AssertStreamArguments(stream); using (var stream = new MemoryBlockStream()) AssertStreamArguments(stream); using (var memory = new MemoryStream()) { Assert.Throws <ArgumentNullException> (() => new FilteredStream(null)); using (var stream = new FilteredStream(memory)) AssertStreamArguments(stream); } using (var memory = new MemoryStream()) { Assert.Throws <ArgumentNullException> (() => new BoundStream(null, 0, 10, true)); Assert.Throws <ArgumentOutOfRangeException> (() => new BoundStream(memory, -1, 10, true)); Assert.Throws <ArgumentOutOfRangeException> (() => new BoundStream(memory, 5, 1, true)); using (var stream = new BoundStream(memory, 0, -1, true)) AssertStreamArguments(stream); } using (var memory = new MemoryStream()) { using (var stream = new ChainedStream()) { stream.Add(memory); Assert.Throws <ArgumentNullException> (() => stream.Add(null)); AssertStreamArguments(stream); } } }
public ImapReplayCommand(string command, string resource) { string tag = null; Command = command; if (command.StartsWith("A00000", StringComparison.Ordinal)) { tag = command.Substring(0, 9); } using (var stream = GetType().Assembly.GetManifestResourceStream("UnitTests.Net.Imap.Resources." + resource)) { using (var memory = new MemoryBlockStream()) { using (var filtered = new FilteredStream(memory)) { if (tag != null) { filtered.Add(new ImapReplayFilter("A########", tag)); } filtered.Add(new Unix2DosFilter()); stream.CopyTo(filtered, 4096); filtered.Flush(); } Response = memory.ToArray(); } } }
/// <summary> /// Parses a MimeEntity and returns as lambda to caller. /// </summary> /// <param name="node">Node containing the MIME message as value, /// and also where the lambda structure representing the parsed message will be placed.</param> /// <param name="entity">MimeEntity to parse.</param> public static void Parse(Node node, MimeEntity entity) { node.Value = entity.ContentType.MimeType; ProcessHeaders(node, entity); if (entity is Multipart multi) { // Multipart content. foreach (var idx in multi) { var idxNode = new Node("entity"); Parse(idxNode, idx); node.Add(idxNode); } } else if (entity is TextPart text) { // Test type of entity. node.Add(new Node("content", text.GetText(out var _))); } else if (entity is MimePart part) { using (var stream = new MemoryBlockStream()) { // Decoding content to memory. part.Content.DecodeTo(stream); // Resetting position and setting up a buffer object to hold content. stream.Position = 0; // Putting content into return node for MimeEntity. node.Add(new Node("content", stream.ToArray())); } } }
public void TestStreamArguments() { using (var stream = new MeasuringStream()) AssertStreamArguments(stream); using (var stream = new MemoryBlockStream()) AssertStreamArguments(stream); using (var memory = new MemoryStream()) { using (var stream = new FilteredStream(memory)) AssertStreamArguments(stream); } using (var memory = new MemoryStream()) { using (var stream = new BoundStream(memory, 0, -1, true)) AssertStreamArguments(stream); } using (var memory = new MemoryStream()) { using (var stream = new ChainedStream()) { stream.Add(memory); AssertStreamArguments(stream); } } }
/// <summary> /// Creates a new <see cref="MultipartSigned"/>. /// </summary> /// <remarks> /// Cryptographically signs the entity using the supplied signer and digest algorithm in /// order to generate a detached signature and then adds the entity along with the /// detached signature data to a new multipart/signed part. /// </remarks> /// <returns>A new <see cref="MultipartSigned"/> instance.</returns> /// <param name="ctx">The cryptography context to use for signing.</param> /// <param name="signer">The signer.</param> /// <param name="digestAlgo">The digest algorithm to use for signing.</param> /// <param name="entity">The entity to sign.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="signer"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// The <paramref name="digestAlgo"/> was out of range. /// </exception> /// <exception cref="System.NotSupportedException"> /// The <paramref name="digestAlgo"/> is not supported. /// </exception> /// <exception cref="CertificateNotFoundException"> /// A signing certificate could not be found for <paramref name="signer"/>. /// </exception> /// <exception cref="PrivateKeyNotFoundException"> /// The private key could not be found for <paramref name="signer"/>. /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static MultipartSigned Create(CryptographyContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException(nameof(ctx)); } if (signer == null) { throw new ArgumentNullException(nameof(signer)); } if (entity == null) { throw new ArgumentNullException(nameof(entity)); } using (var memory = new MemoryBlockStream()) { var prepared = Prepare(entity, memory); memory.Position = 0; // sign the cleartext content var signature = ctx.Sign(signer, digestAlgo, memory); return(Create(ctx, digestAlgo, prepared, signature)); } }
async Task <BoundaryType> ConstructMimePartAsync(MimePart part, CancellationToken cancellationToken) { ScanContentResults results; Stream content; if (persistent) { long begin = GetOffset(inputIndex); long end; using (var measured = new MeasuringStream()) { results = await ScanContentAsync(measured, true, cancellationToken).ConfigureAwait(false); end = begin + measured.Length; } content = new BoundStream(stream, begin, end, true); } else { content = new MemoryBlockStream(); results = await ScanContentAsync(content, true, cancellationToken).ConfigureAwait(false); content.Seek(0, SeekOrigin.Begin); } if (!results.IsEmpty) { part.ContentObject = new ContentObject(content, part.ContentTransferEncoding); } return(results.Boundary); }
private static MimePart GetMimePart(AttachmentBase item) { var mimeType = item.ContentType.ToString(); var contentType = ContentType.Parse(mimeType); var attachment = item as Attachment; MimePart part; if (contentType.MediaType.Equals("text", StringComparison.OrdinalIgnoreCase)) { // Original: part = new TextPart(contentType); // Due to constructor of TextPart(ContentType contentType) being internal, // mimic the instantiation by using MimePart(ContentType contentType) part = new MimePart(contentType); } else { part = new MimePart(contentType); } if (attachment != null) { var disposition = attachment.ContentDisposition.ToString(); part.ContentDisposition = ContentDisposition.Parse(disposition); } switch (item.TransferEncoding) { case System.Net.Mime.TransferEncoding.QuotedPrintable: part.ContentTransferEncoding = ContentEncoding.QuotedPrintable; break; case System.Net.Mime.TransferEncoding.Base64: part.ContentTransferEncoding = ContentEncoding.Base64; break; case System.Net.Mime.TransferEncoding.SevenBit: part.ContentTransferEncoding = ContentEncoding.SevenBit; break; case System.Net.Mime.TransferEncoding.EightBit: part.ContentTransferEncoding = ContentEncoding.EightBit; break; } if (item.ContentId != null) { part.ContentId = item.ContentId; } var stream = new MemoryBlockStream(); item.ContentStream.CopyTo(stream); stream.Position = 0; #pragma warning disable CS0618 // Type or member is obsolete, this line will be removed once the ContentObject property is fully removed part.ContentObject = new ContentObject(stream); #pragma warning restore CS0618 // Type or member is obsolete, this line will be removed once the ContentObject property is fully removed return(part); }
public MemoryBlockStreamTests() { var bytes = new byte[9 * 1024]; int position = 0; random = new Random(); random.NextBytes(bytes); // this is our master stream, all operations on the chained stream // should match the results on this stream master = new MemoryStream(bytes); mbuf = new byte[4096]; buf = new byte[4096]; // write the content into the memory block stream in random chunks blocks = new MemoryBlockStream(); while (position < bytes.Length) { int n = Math.Min(bytes.Length - position, random.Next() % 4096); blocks.Write(bytes, position, n); position += n; } blocks.Seek(0, SeekOrigin.Begin); }
/// <summary> /// Creates a new <see cref="MultipartSigned"/>. /// </summary> /// <remarks> /// Cryptographically signs the entity using the supplied signer in order /// to generate a detached signature and then adds the entity along with /// the detached signature data to a new multipart/signed part. /// </remarks> /// <returns>A new <see cref="MultipartSigned"/> instance.</returns> /// <param name="ctx">The S/MIME context to use for signing.</param> /// <param name="signer">The signer.</param> /// <param name="entity">The entity to sign.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="ctx"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="signer"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="entity"/> is <c>null</c>.</para> /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public static MultipartSigned Create(SecureMimeContext ctx, CmsSigner signer, MimeEntity entity) { if (ctx == null) { throw new ArgumentNullException("ctx"); } if (signer == null) { throw new ArgumentNullException("signer"); } if (entity == null) { throw new ArgumentNullException("entity"); } entity.Prepare(EncodingConstraint.SevenBit, 78); using (var memory = new MemoryBlockStream()) { using (var filtered = new FilteredStream(memory)) { // Note: see rfc3156, section 3 - second note filtered.Add(new ArmoredFromFilter()); // Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156) filtered.Add(new TrailingWhitespaceFilter()); // Note: see rfc2015 or rfc3156, section 5.1 filtered.Add(new Unix2DosFilter()); entity.WriteTo(filtered); filtered.Flush(); } memory.Position = 0; // Note: we need to parse the modified entity structure to preserve any modifications var parser = new MimeParser(memory, MimeFormat.Entity); var parsed = parser.ParseEntity(); memory.Position = 0; // sign the cleartext content var micalg = ctx.GetDigestAlgorithmName(signer.DigestAlgorithm); var signature = ctx.Sign(signer, memory); 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(parsed); // add the detached signature as the second part signed.Add(signature); return(signed); } }
/// <summary> /// Decrypts the <see cref="MultipartEncrypted"/> part. /// </summary> /// <remarks> /// Decrypts the <see cref="MultipartEncrypted"/> and extracts any digital signatures in cases /// where the content was also signed. /// </remarks> /// <returns>The decrypted entity.</returns> /// <param name="ctx">The OpenPGP cryptography context to use for decrypting.</param> /// <param name="signatures">A list of digital signatures if the data was both signed and encrypted.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="ctx"/> is <c>null</c>. /// </exception> /// <exception cref="System.FormatException"> /// <para>The <c>protocol</c> parameter was not specified.</para> /// <para>-or-</para> /// <para>The multipart is malformed in some way.</para> /// </exception> /// <exception cref="System.NotSupportedException"> /// The provided <see cref="OpenPgpContext"/> does not support the protocol parameter. /// </exception> /// <exception cref="PrivateKeyNotFoundException"> /// The private key could not be found to decrypt the encrypted data. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The user chose to cancel the password prompt. /// </exception> /// <exception cref="System.UnauthorizedAccessException"> /// 3 bad attempts were made to unlock the secret key. /// </exception> public MimeEntity Decrypt(OpenPgpContext ctx, out DigitalSignatureCollection signatures) { if (ctx == null) { throw new ArgumentNullException("ctx"); } var protocol = ContentType.Parameters["protocol"]; if (string.IsNullOrEmpty(protocol)) { throw new FormatException(); } protocol = protocol.Trim().ToLowerInvariant(); if (!ctx.Supports(protocol)) { throw new NotSupportedException(); } if (Count < 2) { throw new FormatException(); } var version = this[0] as MimePart; if (version == null) { throw new FormatException(); } var ctype = version.ContentType; var value = string.Format("{0}/{1}", ctype.MediaType, ctype.MediaSubtype); if (value.ToLowerInvariant() != protocol) { throw new FormatException(); } var encrypted = this[1] as MimePart; if (encrypted == null || encrypted.ContentObject == null) { throw new FormatException(); } if (!encrypted.ContentType.Matches("application", "octet-stream")) { throw new FormatException(); } using (var memory = new MemoryBlockStream()) { encrypted.ContentObject.DecodeTo(memory); memory.Position = 0; return(ctx.Decrypt(memory, out signatures)); } }
static void AssertJwzMboxResults(string actual, Stream output) { var summary = File.ReadAllText(Path.Combine(MboxDataDir, "jwz-summary.txt")).Replace("\r\n", "\n"); var original = new MemoryBlockStream(); var expected = new byte[4096]; var buffer = new byte[4096]; int nx, n; // WORKAROUND: Mono's iso-2022-jp decoder breaks on this input in versions <= 3.2.3 but is fixed in 3.2.4+ string iso2022jp = Encoding.GetEncoding("iso-2022-jp").GetString(Convert.FromBase64String("GyRAOjRGI0stGyhK")); if (iso2022jp != "佐藤豊") { actual = actual.Replace(iso2022jp, "佐藤豊"); } Assert.AreEqual(summary, actual, "Summaries do not match for jwz.mbox"); using (var stream = File.OpenRead(Path.Combine(MboxDataDir, "jwz.mbox.txt"))) { using (var filtered = new FilteredStream(original)) { filtered.Add(new Dos2UnixFilter()); stream.CopyTo(filtered); filtered.Flush(); } } original.Position = 0; output.Position = 0; Assert.AreEqual(original.Length, output.Length, "The length of the mbox did not match."); do { var position = original.Position; nx = original.Read(expected, 0, expected.Length); n = output.Read(buffer, 0, buffer.Length); if (nx == 0) { break; } for (int i = 0; i < nx; i++) { if (buffer[i] == expected[i]) { continue; } var strExpected = CharsetUtils.Latin1.GetString(expected, 0, nx); var strActual = CharsetUtils.Latin1.GetString(buffer, 0, n); Assert.AreEqual(strExpected, strActual, "The mbox differs at position {0}", position + i); } } while (true); }
private static MimePart GetMimePart(AttachmentBase item) { var mimeType = item.ContentType.ToString(); var contentType = ContentType.Parse(mimeType); var attachment = item as Attachment; var part = new MimePart(contentType); // if (attachment != null) { var disposition = attachment.ContentDisposition.ToString(); part.ContentDisposition = ContentDisposition.Parse(disposition); } // Adjust the transfer encoding switch (item.TransferEncoding) { case TransferEncoding.QuotedPrintable: part.ContentTransferEncoding = ContentEncoding.QuotedPrintable; break; case TransferEncoding.Base64: part.ContentTransferEncoding = ContentEncoding.Base64; break; case TransferEncoding.SevenBit: part.ContentTransferEncoding = ContentEncoding.SevenBit; break; case TransferEncoding.EightBit: part.ContentTransferEncoding = ContentEncoding.EightBit; break; case TransferEncoding.Unknown: break; default: throw new ArgumentOutOfRangeException(); } // Adjust the attachment content identifier if (item.ContentId != null) { part.ContentId = item.ContentId; } // Copy the content of the attachment var stream = new MemoryBlockStream(); item.ContentStream.CopyTo(stream); stream.Position = 0; part.Content = new MimeContent(stream); // Done return(part); }
/// <summary> /// Verify the multipart/signed part. /// </summary> /// <remarks> /// Verifies the multipart/signed part using the supplied cryptography context. /// </remarks> /// <returns>A signer info collection.</returns> /// <param name="ctx">The cryptography context to use for verifying the signature.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="ctx"/> is <c>null</c>. /// </exception> /// <exception cref="System.FormatException"> /// The multipart is malformed in some way. /// </exception> /// <exception cref="System.NotSupportedException"> /// <paramref name="ctx"/> does not support verifying the signature part. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was cancelled via the cancellation token. /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public async Task <DigitalSignatureCollection> VerifyAsync(CryptographyContext ctx, CancellationToken cancellationToken = default(CancellationToken)) { if (ctx == null) { throw new ArgumentNullException(nameof(ctx)); } var protocol = ContentType.Parameters["protocol"]?.Trim(); if (string.IsNullOrEmpty(protocol)) { throw new FormatException("The multipart/signed part did not specify a protocol."); } if (!ctx.Supports(protocol)) { throw new NotSupportedException("The specified cryptography context does not support the signature protocol."); } if (Count < 2) { throw new FormatException("The multipart/signed part did not contain the expected children."); } var signature = this[1] as MimePart; if (signature == null || signature.Content == null) { throw new FormatException("The signature part could not be found."); } var ctype = signature.ContentType; var value = string.Format("{0}/{1}", ctype.MediaType, ctype.MediaSubtype); if (!ctx.Supports(value)) { throw new NotSupportedException(string.Format("The specified cryptography context does not support '{0}'.", value)); } using (var signatureData = new MemoryBlockStream()) { await signature.Content.DecodeToAsync(signatureData, cancellationToken).ConfigureAwait(false); signatureData.Position = 0; using (var cleartext = new MemoryBlockStream()) { // Note: see rfc2015 or rfc3156, section 5.1 var options = FormatOptions.CloneDefault(); options.NewLineFormat = NewLineFormat.Dos; options.VerifyingSignature = true; await this[0].WriteToAsync(options, cleartext, cancellationToken); cleartext.Position = 0; return(await ctx.VerifyAsync(cleartext, signatureData, cancellationToken).ConfigureAwait(false)); } } }
private void CompareState(MemoryStream ms, MemoryBlockStream ms2) { // Compare byte content. byte[] buff1 = ms.ToArray(); byte[] buff2 = ms2.ToArray(); // Compare read/write position. Assert.Equal(buff1, buff2); Assert.Equal(ms.Position, ms2.Position); }
void OnFieldsChanged(object sender, HeaderListChangedEventArgs e) { var stream = new MemoryBlockStream(); var options = FormatOptions.Default; fields.WriteTo(options, stream); stream.Position = 0; ContentObject = new ContentObject(stream); }
public void TestGetSetTimeouts() { using (var block = new MemoryBlockStream()) { Assert.Throws <InvalidOperationException> (() => { int x = block.ReadTimeout; }); Assert.Throws <InvalidOperationException> (() => { int x = block.WriteTimeout; }); Assert.Throws <InvalidOperationException> (() => block.ReadTimeout = 5); Assert.Throws <InvalidOperationException> (() => block.WriteTimeout = 5); } }
/// <summary> /// Verifies the multipart/signed part. /// </summary> /// <remarks> /// Verifies the multipart/signed part using the supplied cryptography context. /// </remarks> /// <returns>A signer info collection.</returns> /// <param name="ctx">The cryptography context to use for verifying the signature.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="ctx"/> is <c>null</c>. /// </exception> /// <exception cref="System.FormatException"> /// The multipart is malformed in some way. /// </exception> /// <exception cref="System.NotSupportedException"> /// <paramref name="ctx"/> does not support verifying the signature part. /// </exception> /// <exception cref="Org.BouncyCastle.Cms.CmsException"> /// An error occurred in the cryptographic message syntax subsystem. /// </exception> public DigitalSignatureCollection Verify(CryptographyContext ctx) { if (ctx == null) { throw new ArgumentNullException("ctx"); } var protocol = ContentType.Parameters["protocol"]; if (string.IsNullOrEmpty(protocol)) { throw new FormatException("The multipart/signed part did not specify a protocol."); } if (!ctx.Supports(protocol.Trim())) { throw new NotSupportedException("The specified cryptography context does not support the signature protocol."); } if (Count < 2) { throw new FormatException("The multipart/signed part did not contain the expected children."); } var signature = this[1] as MimePart; if (signature == null || signature.ContentObject == null) { throw new FormatException("The signature part could not be found."); } var ctype = signature.ContentType; var value = string.Format("{0}/{1}", ctype.MediaType, ctype.MediaSubtype); if (!ctx.Supports(value)) { throw new NotSupportedException(string.Format("The specified cryptography context does not support '{0}'.", value)); } using (var signatureData = new MemoryBlockStream()) { signature.ContentObject.DecodeTo(signatureData); signatureData.Position = 0; using (var cleartext = new MemoryBlockStream()) { // Note: see rfc2015 or rfc3156, section 5.1 var options = FormatOptions.CloneDefault(); options.NewLineFormat = NewLineFormat.Dos; this[0].WriteTo(options, cleartext); cleartext.Position = 0; return(ctx.Verify(cleartext, signatureData)); } } }