Example #1
0
        /// <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));
                }
            }
        }