/// <summary> /// Checks the container is valid. /// </summary> /// <param name="containerDoc">Signed container.</param> /// <exception cref="ArgumentException">Thrown when the container is not valid. /// </exception> private void CheckSignedContainer(XmlDocument containerDoc) { // Check the document is a signed container if (!XmlUtils.CheckElement(containerDoc.DocumentElement, SignedPayloadElement, this.signedPayloadXmlNs)) { throw new ArgumentException("Document is not a signed container"); } XmlNamespaceManager namespaceManager = CreateXmlNamespaceManager(containerDoc); // Check the container has signatures IList <XmlElement> signatureElems = XPathUtils.GetElements(containerDoc, "/sp:signedPayload/sp:signatures/ds:Signature", namespaceManager); if (signatureElems.Count == 0) { throw new XspException("No signatures were found in the signed container"); } // Check the container contains data if (XPathUtils.GetElement(containerDoc, "/sp:signedPayload/sp:signedPayloadData", namespaceManager) == null) { throw new XspException("No data section within the container"); } }
/// <summary> /// Gets a list of digest values. /// </summary> /// <param name="containerDoc">Signed container.</param> /// <returns>List of digest values.</returns> public IList <byte[]> GetDigestValues(XmlDocument containerDoc) { ArgumentUtils.CheckNotNull(containerDoc, "containerDoc"); // Check the document is a signed container if (!XmlUtils.CheckElement(containerDoc.DocumentElement, SignedPayloadElement, this.signedPayloadXmlNs)) { throw new ArgumentException("Document is not a signed container"); } // Create the namespace manager for executing XPath statements XmlNamespaceManager namespaceManager = CreateXmlNamespaceManager( containerDoc); // Get the list of signature elements IList <XmlElement> signatureElems = XPathUtils.GetElements(containerDoc, "/sp:signedPayload/sp:signatures/ds:Signature", namespaceManager); if (signatureElems.Count == 0) { throw new XspException("No 'ds:Signature' elements were found within the " + "'sp:signatures' element"); } // Iterate through each signature to get the digest IList <byte[]> digestList = new List <byte[]>(); foreach (XmlElement signatureElem in signatureElems) { // Extract the digest from the signature IDictionary <string, byte[]> digestValues = this.signedProfileService.GetDigestValues(signatureElem); if (digestValues.Keys.Count == 0) { throw new XspException("Signature contains no refences"); } if (digestValues.Keys.Count > 1) { throw new XspException("Signature contains more than one reference"); } // Get the first value from the values list as there is only one IEnumerator <byte[]> digestEnumerator = digestValues.Values.GetEnumerator(); digestEnumerator.MoveNext(); digestList.Add(digestEnumerator.Current); } return(digestList); }
/// <summary> /// Decrypts an encrypted container Xml element, returning the payload. /// </summary> /// <param name="encryptedPayloadElem">Encrypted container to decrypt.</param> /// <param name="certificate">Certificate to decrypt with.</param> /// <returns>Decrypted payload.</returns> /// <exception cref="XspException">Thrown on error.</exception> public XmlDocument GetData(XmlElement encryptedPayloadElem, X509Certificate2 certificate) { ArgumentUtils.CheckNotNull(encryptedPayloadElem, "encryptedPayloadElem"); ArgumentUtils.CheckNotNull(certificate, "certificate"); // Check the root element belongs to the right namespace if (!XmlUtils.CheckElement(encryptedPayloadElem, EncryptedPayloadElement, this.encryptedPayloadXmlNs)) { throw new ArgumentException("Document is not an encrypted container"); } // Clone the source element so it is not modified XmlElement clonePayloadElem = XmlUtils.Clone(encryptedPayloadElem); // Create a namespace manager for XPath XmlNamespaceManager namespaceManager = CreateXmlNamespaceManager( clonePayloadElem.OwnerDocument); // Get the 'xenc:EncryptedData' element XmlElement encryptedDataElem = XPathUtils.GetElement(clonePayloadElem, "/ep:encryptedPayload/ep:encryptedPayloadData/xenc:EncryptedData", namespaceManager); if (encryptedDataElem == null) { throw new XspException("Encrypted data was not found within the container"); } // Get the 'xenc:EncryptedKey' element list IList <XmlElement> keyElems = XPathUtils.GetElements(clonePayloadElem, "/ep:encryptedPayload/ep:keys/xenc:EncryptedKey", namespaceManager); if (keyElems.Count == 0) { throw new XspException("No encrypted keys found within the container"); } // Decrypt the data this.encryptedProfileService.Decrypt(keyElems, encryptedDataElem, certificate); // Get the payload element XmlElement payloadElem = XPathUtils.GetElement(clonePayloadElem, "/ep:encryptedPayload/ep:encryptedPayloadData/*[1]", namespaceManager); // Return the payload element within a new Xml document return(XmlUtils.CreateXmlDocument(payloadElem)); }
/// <summary> /// Checks the signatures in a signed payload container and also verifies the /// certificates with the certificate verifier callback. /// </summary> /// <param name="containerDoc">Signed payload container.</param> /// <param name="certificateVerifier">Certificate verifier.</param> /// <exception cref="XspException">Thrown on error.</exception> public void Check(XmlDocument containerDoc, ICertificateVerifier certificateVerifier) { ArgumentUtils.CheckNotNull(containerDoc, "containerDoc"); ArgumentUtils.CheckNotNull(certificateVerifier, "certificateVerifier"); // Check the container is valid CheckSignedContainer(containerDoc); // Get all the signatures in the container IList <XmlElement> signatureElems = XPathUtils.GetElements(containerDoc, "/sp:signedPayload/sp:signatures/ds:Signature", CreateXmlNamespaceManager(containerDoc)); // Check all the signatures verify this.signedProfileService.Check(signatureElems, certificateVerifier); }
/// <summary> /// Returns a list of certificates from the signed container. /// </summary> /// <param name="containerDoc">Signed container.</param> /// <returns>List of certificates.</returns> public IList <X509Certificate2> GetSigningCertificates(XmlDocument containerDoc) { ArgumentUtils.CheckNotNull(containerDoc, "containerDoc"); // Check the document is a signed container if (!XmlUtils.CheckElement(containerDoc.DocumentElement, SignedPayloadElement, this.signedPayloadXmlNs)) { throw new ArgumentException("Document is not a signed container"); } // Create the namespace manager for executing XPath statements XmlNamespaceManager namespaceManager = CreateXmlNamespaceManager( containerDoc); // Get the list of signature elements IList <XmlElement> signatureElems = XPathUtils.GetElements(containerDoc, "/sp:signedPayload/sp:signatures/ds:Signature", namespaceManager); if (signatureElems.Count == 0) { throw new XspException("No 'ds:Signature' elements were found " + "within the 'sp:signatures' element"); } IList <X509Certificate2> certs = new List <X509Certificate2>(); foreach (XmlElement signatureElem in signatureElems) { // Add each certificate X509Certificate2 cert = this.signedProfileService.GetSigningCertificate(signatureElem); certs.Add(cert); } return(certs); }