// Try to decrypt the EncryptedKey given the key mapping public virtual byte[] DecryptEncryptedKey(EncryptedKey encryptedKey) { if (encryptedKey == null) { throw new ArgumentNullException("encryptedKey"); } if (encryptedKey.KeyInfo == null) { return(null); } IEnumerator keyInfoEnum = encryptedKey.KeyInfo.GetEnumerator(); KeyInfoName kiName; KeyInfoX509Data kiX509Data; KeyInfoRetrievalMethod kiRetrievalMethod; KeyInfoEncryptedKey kiEncKey; EncryptedKey ek = null; bool fOAEP = false; while (keyInfoEnum.MoveNext()) { kiName = keyInfoEnum.Current as KeyInfoName; if (kiName != null) { // Get the decryption key from the key mapping string keyName = kiName.Value; Object kek = m_keyNameMapping[keyName]; if (kek != null) { if (!Utils.GetLeaveCipherValueUnchecked() && (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null)) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm")); } // kek is either a SymmetricAlgorithm or an RSA key, otherwise, we wouldn't be able to insert it in the hash table if (kek is SymmetricAlgorithm) { return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (SymmetricAlgorithm)kek)); } // kek is an RSA key: get fOAEP from the algorithm, default to false fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl); return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (RSA)kek, fOAEP)); } break; } kiX509Data = keyInfoEnum.Current as KeyInfoX509Data; if (kiX509Data != null) { X509Certificate2Collection collection = Utils.BuildBagOfCerts(kiX509Data, CertUsageType.Decryption); foreach (X509Certificate2 certificate in collection) { using (RSA privateKey = certificate.GetRSAPrivateKey()) { if (privateKey != null) { if (!Utils.GetLeaveCipherValueUnchecked() && (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null)) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm")); } fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl); return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, privateKey, fOAEP)); } } } break; } kiRetrievalMethod = keyInfoEnum.Current as KeyInfoRetrievalMethod; if (kiRetrievalMethod != null) { string idref = Utils.ExtractIdFromLocalUri(kiRetrievalMethod.Uri); ek = new EncryptedKey(); ek.LoadXml(GetIdElement(m_document, idref)); try { //Following checks if XML dsig processing is in loop and within the limit defined by machine // admin or developer. Once the recursion depth crosses the defined limit it will throw exception. m_xmlDsigSearchDepthCounter++; if (IsOverXmlDsigRecursionLimit()) { //Throw exception once recursion limit is hit. throw new CryptoSignedXmlRecursionException(); } else { return(DecryptEncryptedKey(ek)); } } finally { m_xmlDsigSearchDepthCounter--; } } kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey; if (kiEncKey != null) { ek = kiEncKey.EncryptedKey; // recursively process EncryptedKey elements byte[] encryptionKey = DecryptEncryptedKey(ek); if (encryptionKey != null) { // this is a symmetric algorithm for sure SymmetricAlgorithm symAlg = Utils.CreateFromName <SymmetricAlgorithm>(encryptedKey.EncryptionMethod.KeyAlgorithm); if (symAlg == null) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm")); } symAlg.Key = encryptionKey; if (!Utils.GetLeaveCipherValueUnchecked() && (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null)) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm")); } return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, symAlg)); } } } return(null); }
// // private methods // private byte[] GetCipherValue(CipherData cipherData) { if (cipherData == null) { throw new ArgumentNullException("cipherData"); } WebResponse response = null; Stream inputStream = null; if (cipherData.CipherValue != null) { return(cipherData.CipherValue); } else if (cipherData.CipherReference != null) { if (cipherData.CipherReference.CipherValue != null) { return(cipherData.CipherReference.CipherValue); } Stream decInputStream = null; // See if the CipherReference is a local URI if (!Utils.GetLeaveCipherValueUnchecked() && cipherData.CipherReference.Uri == null) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotSupported")); } if (cipherData.CipherReference.Uri.Length == 0) { // self referenced Uri string baseUri = (m_document == null ? null : m_document.BaseURI); TransformChain tc = cipherData.CipherReference.TransformChain; if (!Utils.GetLeaveCipherValueUnchecked() && tc == null) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotSupported")); } decInputStream = tc.TransformToOctetStream(m_document, m_xmlResolver, baseUri); } else if (cipherData.CipherReference.Uri[0] == '#') { string idref = Utils.ExtractIdFromLocalUri(cipherData.CipherReference.Uri); // Serialize if (Utils.GetLeaveCipherValueUnchecked()) { inputStream = new MemoryStream(m_encoding.GetBytes(GetIdElement(m_document, idref).OuterXml)); } else { XmlElement idElem = GetIdElement(m_document, idref); if (idElem == null || idElem.OuterXml == null) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotSupported")); } inputStream = new MemoryStream(m_encoding.GetBytes(idElem.OuterXml)); } string baseUri = (m_document == null ? null : m_document.BaseURI); TransformChain tc = cipherData.CipherReference.TransformChain; if (!Utils.GetLeaveCipherValueUnchecked() && tc == null) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotSupported")); } decInputStream = tc.TransformToOctetStream(inputStream, m_xmlResolver, baseUri); } else { DownloadCipherValue(cipherData, out inputStream, out decInputStream, out response); } // read the output stream into a memory stream byte[] cipherValue = null; using (MemoryStream ms = new MemoryStream()) { Utils.Pump(decInputStream, ms); cipherValue = ms.ToArray(); // Close the stream and return if (response != null) { response.Close(); } if (inputStream != null) { inputStream.Close(); } decInputStream.Close(); } // cache the cipher value for Perf reasons in case we call this routine twice cipherData.CipherReference.CipherValue = cipherValue; return(cipherValue); } // Throw a CryptographicException if we were unable to retrieve the cipher data. throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingCipherData")); }