Beispiel #1
0
        /// <summary>
        /// Reads XML conforming to https://www.w3.org/TR/2001/PR-xmldsig-core-20010820/#sec-SignedInfo
        /// </summary>
        /// <param name="reader">a <see cref="XmlReader"/>positioned on a &lt;SignedInfo> element.</param>
        /// <exception cref="ArgumentNullException">if <paramref name="reader"/> is null.</exception>
        /// <exception cref="XmlReadException">if there is a problem reading the XML.</exception>
        /// <returns><see cref="SignedInfo"/></returns>
        public virtual SignedInfo ReadSignedInfo(XmlReader reader)
        {
            XmlUtil.CheckReaderOnEntry(reader, XmlSignatureConstants.Elements.SignedInfo, XmlSignatureConstants.Namespace);

            try
            {
                var defaultNamespace = reader.LookupNamespace(string.Empty);
                var bufferedStream   = new MemoryStream();
                var settings         = new XmlWriterSettings
                {
                    Encoding        = Encoding.UTF8,
                    NewLineHandling = NewLineHandling.None
                };

                // need to read into buffer since the canonicalization reader needs a stream.
                using (XmlWriter bufferWriter = XmlDictionaryWriter.Create(bufferedStream, settings))
                {
                    bufferWriter.WriteNode(reader, true);
                    bufferWriter.Flush();
                }

                bufferedStream.Position = 0;

                //
                // We are creating a XmlDictionaryReader with a hard-coded Max XmlDictionaryReaderQuotas. This is a reader that we
                // are creating over an already buffered content. The content was initially read off user provided XmlDictionaryReader
                // with the correct quotas and hence we know the data is valid.
                //
                using (var canonicalizingReader = XmlDictionaryReader.CreateTextReader(bufferedStream, XmlDictionaryReaderQuotas.Max))
                {
                    var signedInfo = new SignedInfo();
                    signedInfo.CanonicalStream = new MemoryStream();

                    // TODO - should not always use 'false'
                    canonicalizingReader.StartCanonicalization(signedInfo.CanonicalStream, false, null);
                    canonicalizingReader.MoveToStartElement(XmlSignatureConstants.Elements.SignedInfo, XmlSignatureConstants.Namespace);
                    signedInfo.Prefix = canonicalizingReader.Prefix;
                    signedInfo.Id     = canonicalizingReader.GetAttribute(XmlSignatureConstants.Attributes.Id, null);
                    // read <SignedInfo ...> start element
                    canonicalizingReader.Read();
                    // TODO - if comments are not false, then we need to reset.
                    // this should be very rare.
                    signedInfo.CanonicalizationMethod = ReadCanonicalizationMethod(canonicalizingReader);
                    signedInfo.SignatureMethod        = ReadSignatureMethod(canonicalizingReader);
                    signedInfo.References.Add(ReadReference(canonicalizingReader));

                    if (canonicalizingReader.IsStartElement(XmlSignatureConstants.Elements.Reference, XmlSignatureConstants.Namespace))
                    {
                        throw XmlUtil.LogReadException(LogMessages.IDX30020);
                    }

                    canonicalizingReader.ReadEndElement();
                    canonicalizingReader.EndCanonicalization();
                    signedInfo.CanonicalStream.Flush();

                    return(signedInfo);
                }
            }
            catch (Exception ex)
            {
                if (ex is XmlReadException)
                {
                    throw;
                }

                throw XmlUtil.LogReadException(LogMessages.IDX30016, ex, XmlSignatureConstants.Elements.SignedInfo);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Writes the contents of a <see cref="SignedInfo"/> as XML conforming to https://www.w3.org/TR/2001/PR-xmldsig-core-20010820/#sec-SignedInfo.
        /// </summary>
        /// <param name="writer">the <see cref="XmlWriter"/> to use.</param>
        /// <param name="signedInfo">the <see cref="SignedInfo"/>to write.</param>
        /// <remarks>Assumes the &lt;Reference> digest has been calculated, no canonicalization or digest calculation is performed.</remarks>
        /// <exception cref="ArgumentNullException">if <paramref name="writer"/> is null.</exception>
        /// <exception cref="ArgumentNullException">if <paramref name="signedInfo"/> is null.</exception>
        /// <exception cref="XmlWriteException">if <see cref="SignedInfo.CanonicalizationMethod"/> is null or empty.</exception>
        /// <exception cref="XmlWriteException">if <see cref="SignedInfo.References"/> is null.</exception>
        /// <exception cref="NotSupportedException">if <see cref="SignedInfo.References" />.Count > 1.</exception>
        /// <exception cref="XmlWriteException">if <see cref="SignedInfo.SignatureMethod"/> is null or empty.</exception>
        public virtual void WriteSignedInfo(XmlWriter writer, SignedInfo signedInfo)
        {
            if (writer == null)
            {
                throw LogArgumentNullException(nameof(writer));
            }

            if (signedInfo == null)
            {
                throw LogArgumentNullException(nameof(signedInfo));
            }

            if (string.IsNullOrEmpty(signedInfo.CanonicalizationMethod))
            {
                throw XmlUtil.LogWriteException(LogMessages.IDX30401, XmlSignatureConstants.Elements.SignedInfo, XmlSignatureConstants.Elements.CanonicalizationMethod);
            }

            if (string.IsNullOrEmpty(signedInfo.SignatureMethod))
            {
                throw XmlUtil.LogWriteException(LogMessages.IDX30401, XmlSignatureConstants.Elements.SignedInfo, XmlSignatureConstants.Elements.SignatureMethod);
            }

            if (signedInfo.References == null)
            {
                throw XmlUtil.LogWriteException(LogMessages.IDX30405);
            }

            // <SignedInfo>
            writer.WriteStartElement(Prefix, XmlSignatureConstants.Elements.SignedInfo, XmlSignatureConstants.Namespace);

            // @Id
            if (signedInfo.Id != null)
            {
                writer.WriteAttributeString(XmlSignatureConstants.Attributes.Id, null, signedInfo.Id);
            }

            // <CanonicalizationMethod>
            writer.WriteStartElement(Prefix, XmlSignatureConstants.Elements.CanonicalizationMethod, XmlSignatureConstants.Namespace);

            //@Algorithm
            writer.WriteAttributeString(XmlSignatureConstants.Attributes.Algorithm, null, signedInfo.CanonicalizationMethod);
            writer.WriteEndElement();

            // <SignatureMethod>
            writer.WriteStartElement(Prefix, XmlSignatureConstants.Elements.SignatureMethod, XmlSignatureConstants.Namespace);

            // @Algorithm
            writer.WriteAttributeString(XmlSignatureConstants.Attributes.Algorithm, null, signedInfo.SignatureMethod);

            // </SignatureMethod>
            writer.WriteEndElement();

            // <Reference>
            foreach (var reference in signedInfo.References)
            {
                WriteReference(writer, reference);
            }

            // </SignedInfo>
            writer.WriteEndElement();
        }
Beispiel #3
0
 /// <summary>
 /// Initializes a <see cref="Signature"/> instance.
 /// </summary>
 /// <param name="signedInfo">associated with this Signature.</param>
 /// <exception cref="ArgumentNullException">if <paramref name="signedInfo"/> if null.</exception>
 public Signature(SignedInfo signedInfo)
 {
     SignedInfo = signedInfo;
 }