/// <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 <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); }
/// <summary> /// Writes the contents of a <see cref="KeyInfo"/> as XML conforming to https://www.w3.org/TR/2001/PR-xmldsig-core-20010820/#sec-KeyInfo. /// </summary> /// <param name="writer">the <see cref="XmlWriter"/> to use.</param> /// <param name="keyInfo">the <see cref="KeyInfo"/>to write.</param> /// <exception cref="ArgumentNullException">if <paramref name="writer"/> is null.</exception> /// <exception cref="ArgumentNullException">if <paramref name="keyInfo"/> is null.</exception> /// <exception cref="XmlWriteException">if there is a problem writing the XML.</exception> public virtual void WriteKeyInfo(XmlWriter writer, KeyInfo keyInfo) { if (writer == null) { throw LogArgumentNullException(nameof(writer)); } if (keyInfo == null) { throw LogArgumentNullException(nameof(keyInfo)); } // <KeyInfo> writer.WriteStartElement(XmlSignatureConstants.Elements.KeyInfo, XmlSignatureConstants.Namespace); if (keyInfo.KeyName != null) { writer.WriteElementString(Prefix, XmlSignatureConstants.Elements.KeyName, XmlSignatureConstants.Namespace, keyInfo.KeyName); } if (keyInfo.RSAKeyValue != null) { // <KeyValue> writer.WriteStartElement(Prefix, XmlSignatureConstants.Elements.KeyValue, XmlSignatureConstants.Namespace); // <RSAKeyValue> writer.WriteStartElement(Prefix, XmlSignatureConstants.Elements.RSAKeyValue, XmlSignatureConstants.Namespace); // <Modulus>...</Modulus> writer.WriteElementString(Prefix, XmlSignatureConstants.Elements.Modulus, XmlSignatureConstants.Namespace, keyInfo.RSAKeyValue.Modulus); // <Exponent>...</Exponent> writer.WriteElementString(Prefix, XmlSignatureConstants.Elements.Exponent, XmlSignatureConstants.Namespace, keyInfo.RSAKeyValue.Exponent); // </RSAKeyValue> writer.WriteEndElement(); // </KeyValue> writer.WriteEndElement(); } if (keyInfo.RetrievalMethodUri != null) { writer.WriteStartElement(keyInfo.Prefix, XmlSignatureConstants.Elements.RetrievalMethod, XmlSignatureConstants.Namespace); writer.WriteAttributeString(XmlSignatureConstants.Attributes.URI, null, keyInfo.RetrievalMethodUri); writer.WriteEndElement(); } foreach (var data in keyInfo.X509Data) { // <X509Data> writer.WriteStartElement(keyInfo.Prefix, XmlSignatureConstants.Elements.X509Data, XmlSignatureConstants.Namespace); if (data.IssuerSerial != null) { writer.WriteStartElement(keyInfo.Prefix, XmlSignatureConstants.Elements.X509IssuerSerial, XmlSignatureConstants.Namespace); writer.WriteElementString(keyInfo.Prefix, XmlSignatureConstants.Elements.X509IssuerName, XmlSignatureConstants.Namespace, data.IssuerSerial.IssuerName); writer.WriteElementString(keyInfo.Prefix, XmlSignatureConstants.Elements.X509SerialNumber, XmlSignatureConstants.Namespace, data.IssuerSerial.SerialNumber); writer.WriteEndElement(); } if (data.SKI != null) { writer.WriteElementString(keyInfo.Prefix, XmlSignatureConstants.Elements.X509SKI, XmlSignatureConstants.Namespace, data.SKI); } if (data.SubjectName != null) { writer.WriteElementString(keyInfo.Prefix, XmlSignatureConstants.Elements.X509SubjectName, XmlSignatureConstants.Namespace, data.SubjectName); } foreach (var certificate in data.Certificates) { // <X509Certificate>...</X509Certificate> writer.WriteElementString(keyInfo.Prefix, XmlSignatureConstants.Elements.X509Certificate, XmlSignatureConstants.Namespace, certificate); } if (data.CRL != null) { writer.WriteElementString(keyInfo.Prefix, XmlSignatureConstants.Elements.X509CRL, XmlSignatureConstants.Namespace, data.CRL); } // </X509Data> writer.WriteEndElement(); } // </KeyInfo> writer.WriteEndElement(); }