Пример #1
0
        /// <summary>
        /// Reads XML conforming to https://www.w3.org/TR/2001/PR-xmldsig-core-20010820/#sec-SignatureMethod
        /// </summary>
        /// <param name="reader">a <see cref="XmlReader"/>positioned on a &lt;SignatureMethod> 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>A string with the signature method.</returns>
        public virtual string ReadSignatureMethod(XmlReader reader)
        {
            XmlUtil.CheckReaderOnEntry(reader, XmlSignatureConstants.Elements.SignatureMethod, XmlSignatureConstants.Namespace);

            try
            {
                bool isEmptyElement  = reader.IsEmptyElement;
                var  signatureMethod = reader.GetAttribute(XmlSignatureConstants.Attributes.Algorithm, null);
                if (signatureMethod == null)
                {
                    throw XmlUtil.OnRequiredAttributeMissing(XmlSignatureConstants.Elements.SignatureMethod, XmlSignatureConstants.Attributes.Algorithm);
                }

                reader.Read();
                reader.MoveToContent();
                if (!isEmptyElement)
                {
                    reader.MoveToContent();
                    reader.ReadEndElement();
                }

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

                throw XmlUtil.LogReadException(LogMessages.IDX30016, ex, XmlSignatureConstants.Elements.Transform);
            }
        }
Пример #2
0
        /// <summary>
        /// Reads XML conforming to https://www.w3.org/TR/2001/PR-xmldsig-core-20010820/#sec-Signature
        /// </summary>
        /// <param name="reader">a <see cref="XmlReader"/>positioned on a &lt;Signature> 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="Signature"/></returns>
        public virtual Signature ReadSignature(XmlReader reader)
        {
            try
            {
                // <Signature>
                XmlUtil.CheckReaderOnEntry(reader, XmlSignatureConstants.Elements.Signature, XmlSignatureConstants.Namespace);

                var prefix = reader.Prefix;
                var id     = reader.GetAttribute(XmlSignatureConstants.Attributes.Id, null);
                reader.Read();

                var signedInfo = ReadSignedInfo(reader);
                reader.MoveToContent();
                var     signatureValue = reader.ReadElementContentAsString().Trim();
                KeyInfo keyInfo        = null;
                if (reader.IsStartElement(XmlSignatureConstants.Elements.KeyInfo, XmlSignatureConstants.Namespace))
                {
                    keyInfo = ReadKeyInfo(reader);
                }

                // </Signature>
                reader.MoveToContent();

                // throw if we are not on EndElement, something unexpected
                if (reader.NodeType != XmlNodeType.EndElement)
                {
                    throw XmlUtil.LogReadException(LogMessages.IDX30025, XmlSignatureConstants.Elements.Signature, reader.NodeType, reader.LocalName);
                }

                reader.ReadEndElement();
                return(new Signature
                {
                    Id = id,
                    KeyInfo = keyInfo,
                    Prefix = prefix,
                    SignedInfo = signedInfo,
                    SignatureValue = signatureValue
                });
            }
            catch (Exception ex)
            {
                if (ex is XmlReadException)
                {
                    throw;
                }

                throw XmlUtil.LogReadException(LogMessages.IDX30016, ex, XmlSignatureConstants.Elements.Signature);
            }
        }
Пример #3
0
        /// <summary>
        /// Reads XML conforming to https://www.w3.org/TR/2001/PR-xmldsig-core-20010820/#sec-CanonicalizationMethod
        /// </summary>
        /// <param name="reader">a <see cref="XmlReader"/>positioned on a &lt;CanonicalizationMethod> 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>A string with the canonicalization method.</returns>
        public virtual string ReadCanonicalizationMethod(XmlReader reader)
        {
            // <CanonicalizationMethod>
            XmlUtil.CheckReaderOnEntry(reader, XmlSignatureConstants.Elements.CanonicalizationMethod, XmlSignatureConstants.Namespace);

            try
            {
                bool isEmptyElement = reader.IsEmptyElement;
                var  algorithm      = reader.GetAttribute(XmlSignatureConstants.Attributes.Algorithm, null);
                if (string.IsNullOrEmpty(algorithm))
                {
                    throw XmlUtil.LogReadException(LogMessages.IDX30013, XmlSignatureConstants.Elements.Signature, XmlSignatureConstants.Attributes.Algorithm);
                }

                if (algorithm != SecurityAlgorithms.ExclusiveC14nWithComments && algorithm != SecurityAlgorithms.ExclusiveC14n)
                {
                    throw XmlUtil.LogReadException(LogMessages.IDX30100, XmlSignatureConstants.Elements.Transform, algorithm, SecurityAlgorithms.ExclusiveC14n, SecurityAlgorithms.ExclusiveC14nWithComments);
                }

                reader.Read();
                reader.MoveToContent();
                if (!isEmptyElement)
                {
                    if (reader.IsStartElement(XmlSignatureConstants.ExclusiveC14nInclusiveNamespaces))
                    {
                        throw XmlUtil.LogReadException(LogMessages.IDX30107);
                    }

                    reader.MoveToContent();
                    reader.ReadEndElement();
                }

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

                throw XmlUtil.LogReadException(LogMessages.IDX30016, ex, XmlSignatureConstants.Elements.Transform);
            }
        }
Пример #4
0
        /// <summary>
        /// Reads XML conforming to https://www.w3.org/TR/2001/PR-xmldsig-core-20010820/#sec-KeyInfo
        /// </summary>
        /// <param name="reader"><see cref="XmlReader"/> pointing positioned on a &lt;KeyInfo> element.</param>
        /// <exception cref="ArgumentNullException">if <paramref name="reader"/> is null.</exception>
        /// <exception cref="XmlReadException">if there is a problem reading the XML.</exception>
        /// <remarks>Only handles IssuerSerial, Ski, SubjectName, Certificate. Unsupported types are skipped. Only a X509 data element is supported.</remarks>
        public virtual KeyInfo ReadKeyInfo(XmlReader reader)
        {
            XmlUtil.CheckReaderOnEntry(reader, XmlSignatureConstants.Elements.KeyInfo, XmlSignatureConstants.Namespace);

            var keyInfo = new KeyInfo
            {
                Prefix = reader.Prefix
            };

            try
            {
                bool isEmptyElement = reader.IsEmptyElement;

                // <KeyInfo>
                reader.ReadStartElement();
                while (reader.IsStartElement())
                {
                    // <X509Data>
                    if (reader.IsStartElement(XmlSignatureConstants.Elements.X509Data, XmlSignatureConstants.Namespace))
                    {
                        keyInfo.X509Data.Add(ReadX509Data(reader));
                    }
                    // <RetrievalMethod>
                    else if (reader.IsStartElement(XmlSignatureConstants.Elements.RetrievalMethod, XmlSignatureConstants.Namespace))
                    {
                        keyInfo.RetrievalMethodUri = reader.GetAttribute(XmlSignatureConstants.Attributes.URI);
                        reader.ReadOuterXml();
                    }
                    // <KeyName>
                    else if (reader.IsStartElement(XmlSignatureConstants.Elements.KeyName, XmlSignatureConstants.Namespace))
                    {
                        keyInfo.KeyName = reader.ReadElementContentAsString(XmlSignatureConstants.Elements.KeyName, XmlSignatureConstants.Namespace);
                    }
                    // <KeyValue>
                    else if (reader.IsStartElement(XmlSignatureConstants.Elements.KeyValue, XmlSignatureConstants.Namespace))
                    {
                        reader.ReadStartElement(XmlSignatureConstants.Elements.KeyValue, XmlSignatureConstants.Namespace);
                        if (reader.IsStartElement(XmlSignatureConstants.Elements.RSAKeyValue, XmlSignatureConstants.Namespace))
                        {
                            // Multiple RSAKeyValues were found
                            if (keyInfo.RSAKeyValue != null)
                            {
                                throw XmlUtil.LogReadException(LogMessages.IDX30015, XmlSignatureConstants.Elements.RSAKeyValue);
                            }

                            keyInfo.RSAKeyValue = ReadRSAKeyValue(reader);
                        }
                        else
                        {
                            // Skip the element since it is not an <RSAKeyValue>
                            LogHelper.LogWarning(LogMessages.IDX30300, reader.ReadOuterXml());
                        }

                        // </KeyValue>
                        reader.ReadEndElement();
                    }
                    else
                    {
                        // Skip the element since it is not one of  <RetrievalMethod>, <X509Data>, <KeyValue>
                        LogHelper.LogWarning(LogMessages.IDX30300, reader.ReadOuterXml());
                    }
                }

                // </KeyInfo>
                if (!isEmptyElement)
                {
                    reader.ReadEndElement();
                }
            }
            catch (Exception ex)
            {
                if (ex is XmlReadException)
                {
                    throw;
                }

                throw XmlUtil.LogReadException(LogMessages.IDX30017, ex, XmlSignatureConstants.Elements.KeyInfo, ex);
            }

            return(keyInfo);
        }
Пример #5
0
        /// <summary>
        /// Reads XML conforming to https://www.w3.org/TR/2001/PR-xmldsig-core-20010820/#sec-Reference
        /// </summary>
        /// <param name="reader">a <see cref="XmlReader"/>positioned on a &lt;Reference> 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="Reference"/></returns>
        public virtual Reference ReadReference(XmlReader reader)
        {
            XmlUtil.CheckReaderOnEntry(reader, XmlSignatureConstants.Elements.Reference, XmlSignatureConstants.Namespace);

            try
            {
                var reference = new Reference
                {
                    Prefix = reader.Prefix,
                    Id     = reader.GetAttribute(XmlSignatureConstants.Attributes.Id, null),
                    Type   = reader.GetAttribute(XmlSignatureConstants.Attributes.Type, null),
                    Uri    = reader.GetAttribute(XmlSignatureConstants.Attributes.URI, null)
                };

                reader.Read();
                ReadTransforms(reader, reference);

                // <DigestMethod> - required
                XmlUtil.CheckReaderOnEntry(reader, XmlSignatureConstants.Elements.DigestMethod, XmlSignatureConstants.Namespace);
                bool isEmptyElement = reader.IsEmptyElement;
                var  digestMethod   = reader.GetAttribute(XmlSignatureConstants.Attributes.Algorithm, null);
                if (string.IsNullOrEmpty(digestMethod))
                {
                    throw XmlUtil.OnRequiredAttributeMissing(XmlSignatureConstants.Elements.DigestMethod, XmlSignatureConstants.Attributes.Algorithm);
                }

                reference.DigestMethod = digestMethod;

                reader.Read();
                reader.MoveToContent();
                if (!isEmptyElement)
                {
                    reader.ReadEndElement();
                }

                // <DigestValue>
                XmlUtil.CheckReaderOnEntry(reader, XmlSignatureConstants.Elements.DigestValue, XmlSignatureConstants.Namespace);
                var digestValue = reader.ReadElementContentAsString().Trim();
                if (string.IsNullOrEmpty(digestValue))
                {
                    throw XmlUtil.LogReadException(LogMessages.IDX30206, reference.Uri ?? reference.Id);
                }

                reference.DigestValue = digestValue;

                // </Reference>
                reader.MoveToContent();
                reader.ReadEndElement();

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

                throw XmlUtil.LogReadException(LogMessages.IDX30016, ex, XmlSignatureConstants.Elements.Reference);
            }
        }
Пример #6
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);
            }
        }