/// <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)); } } }