public override void LoadInnerXml(XmlNodeList nodeList) { if (nodeList == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_UnknownTransform); } ExceptUris.Clear(); foreach (XmlNode node in nodeList) { XmlElement elem = node as XmlElement; if (elem != null) { if (elem.LocalName == "Except" && elem.NamespaceURI == XmlDecryptionTransformNamespaceUrl) { // the Uri is required string uri = Utils.GetAttribute(elem, "URI", XmlDecryptionTransformNamespaceUrl); if (uri == null || uri.Length == 0 || uri[0] != '#') { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_UriRequired); } if (!Utils.VerifyAttributes(elem, "URI")) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_UnknownTransform); } string idref = Utils.ExtractIdFromLocalUri(uri); ExceptUris.Add(idref); } else { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_UnknownTransform); } } } }
private int GetReferenceLevel(int index, ArrayList references) { if (_refProcessed[index]) { return(_refLevelCache[index]); } _refProcessed[index] = true; Reference reference = (Reference)references[index]; if (reference.Uri == null || reference.Uri.Length == 0 || (reference.Uri.Length > 0 && reference.Uri[0] != '#')) { _refLevelCache[index] = 0; return(0); } if (reference.Uri.Length > 0 && reference.Uri[0] == '#') { string idref = Utils.ExtractIdFromLocalUri(reference.Uri); if (idref == "xpointer(/)") { _refLevelCache[index] = 0; return(0); } // If this is pointing to another reference for (int j = 0; j < references.Count; ++j) { if (((Reference)references[j]).Id == idref) { _refLevelCache[index] = GetReferenceLevel(j, references) + 1; return(_refLevelCache[index]); } } // Then the reference points to an object tag _refLevelCache[index] = 0; return(0); } // Malformed reference throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_InvalidReference); }
// Try to decrypt the EncryptedKey given the key mapping public virtual byte[] DecryptEncryptedKey(EncryptedKey encryptedKey, RsaKeyParameters privateKey = null) { if (encryptedKey == null) { throw new ArgumentNullException(nameof(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 = _keyNameMapping[keyName]; if (kek != null) { if (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null) { throw new System.Security.Cryptography.CryptographicException(SR.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 KeyParameter kp) { return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, kp)); } else if (kek is ParametersWithIV piv) { return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, piv.Parameters as KeyParameter)); } // 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, (RsaKeyParameters)kek, fOAEP)); } break; } kiX509Data = keyInfoEnum.Current as KeyInfoX509Data; if (kiX509Data != null) { IList <X509Certificate> collection = Utils.BuildBagOfCerts(kiX509Data, CertUsageType.Decryption); foreach (X509Certificate certificate in collection) { if (privateKey != null) { if (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null) { throw new System.Security.Cryptography.CryptographicException(SR.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(_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. _xmlDsigSearchDepthCounter++; if (IsOverXmlDsigRecursionLimit()) { //Throw exception once recursion limit is hit. throw new CryptoSignedXmlRecursionException(); } else { return(DecryptEncryptedKey(ek, privateKey)); } } finally { _xmlDsigSearchDepthCounter--; } } kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey; if (kiEncKey != null) { ek = kiEncKey.EncryptedKey; // recursively process EncryptedKey elements byte[] encryptionKey = DecryptEncryptedKey(ek, privateKey); if (encryptionKey != null) { // this is a symmetric algorithm for sure IBlockCipher blockSymAlg = CryptoHelpers.CreateFromName <IBlockCipher>(encryptedKey.EncryptionMethod.KeyAlgorithm); if (blockSymAlg == null) { IBufferedCipher bufferedSymAlg = CryptoHelpers.CreateFromName <IBufferedCipher>(encryptedKey.EncryptionMethod.KeyAlgorithm); if (bufferedSymAlg == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); } } if (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); } return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, new KeyParameter(encryptionKey))); } } } return(null); }
// default behaviour is to look for keys defined by an EncryptedKey clause // either directly or through a KeyInfoRetrievalMethod, and key names in the key mapping public virtual ICipherParameters GetDecryptionKey(EncryptedData encryptedData, string symmetricAlgorithmUri) { if (encryptedData == null) { throw new ArgumentNullException(nameof(encryptedData)); } if (encryptedData.KeyInfo == null) { return(null); } IEnumerator keyInfoEnum = encryptedData.KeyInfo.GetEnumerator(); KeyInfoRetrievalMethod kiRetrievalMethod; KeyInfoName kiName; KeyInfoEncryptedKey kiEncKey; EncryptedKey ek = null; while (keyInfoEnum.MoveNext()) { kiName = keyInfoEnum.Current as KeyInfoName; if (kiName != null) { // Get the decryption key from the key mapping string keyName = kiName.Value; if (_keyNameMapping[keyName] as ICipherParameters != null) { return((ICipherParameters)_keyNameMapping[keyName]); } // try to get it from a CarriedKeyName XmlNamespaceManager nsm = new XmlNamespaceManager(_document.NameTable); nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl); XmlNodeList encryptedKeyList = _document.SelectNodes("//enc:EncryptedKey", nsm); if (encryptedKeyList != null) { foreach (XmlNode encryptedKeyNode in encryptedKeyList) { XmlElement encryptedKeyElement = encryptedKeyNode as XmlElement; EncryptedKey ek1 = new EncryptedKey(); ek1.LoadXml(encryptedKeyElement); if (ek1.CarriedKeyName == keyName && ek1.Recipient == Recipient) { ek = ek1; break; } } } break; } kiRetrievalMethod = keyInfoEnum.Current as KeyInfoRetrievalMethod; if (kiRetrievalMethod != null) { string idref = Utils.ExtractIdFromLocalUri(kiRetrievalMethod.Uri); ek = new EncryptedKey(); ek.LoadXml(GetIdElement(_document, idref)); break; } kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey; if (kiEncKey != null) { ek = kiEncKey.EncryptedKey; break; } } // if we have an EncryptedKey, decrypt to get the symmetric key if (ek != null) { // now process the EncryptedKey, loop recursively // If the Uri is not provided by the application, try to get it from the EncryptionMethod if (symmetricAlgorithmUri == null) { if (encryptedData.EncryptionMethod == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); } symmetricAlgorithmUri = encryptedData.EncryptionMethod.KeyAlgorithm; } byte[] key = DecryptEncryptedKey(ek); if (key == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingDecryptionKey); } IBufferedCipher symAlg = CryptoHelpers.CreateFromName <IBufferedCipher>(symmetricAlgorithmUri); if (symAlg == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); } KeyParameter keyParam; if (symAlg.AlgorithmName.IndexOf("DESede", StringComparison.OrdinalIgnoreCase) >= 0) { keyParam = new DesEdeParameters(key); } else if (symAlg.AlgorithmName.IndexOf("DES", StringComparison.OrdinalIgnoreCase) >= 0) { keyParam = new DesParameters(key); } else { keyParam = new KeyParameter(key); } return(keyParam); } return(null); }
// // private methods // private byte[] GetCipherValue(CipherData cipherData) { if (cipherData == null) { throw new ArgumentNullException(nameof(cipherData)); } 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; if (cipherData.CipherReference.Uri == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_UriNotSupported); } // See if the CipherReference is a local URI if (cipherData.CipherReference.Uri.Length == 0) { // self referenced Uri string baseUri = (_document == null ? null : _document.BaseURI); TransformChain tc = cipherData.CipherReference.TransformChain; if (tc == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_UriNotSupported); } decInputStream = tc.TransformToOctetStream(_document, _xmlResolver, baseUri); } else if (cipherData.CipherReference.Uri[0] == '#') { string idref = Utils.ExtractIdFromLocalUri(cipherData.CipherReference.Uri); // Serialize XmlElement idElem = GetIdElement(_document, idref); if (idElem == null || idElem.OuterXml == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_UriNotSupported); } inputStream = new MemoryStream(_encoding.GetBytes(idElem.OuterXml)); string baseUri = (_document == null ? null : _document.BaseURI); TransformChain tc = cipherData.CipherReference.TransformChain; if (tc == null) { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_UriNotSupported); } decInputStream = tc.TransformToOctetStream(inputStream, _xmlResolver, baseUri); } else { throw new System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_UriNotResolved, cipherData.CipherReference.Uri); } // 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 (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 System.Security.Cryptography.CryptographicException(SR.Cryptography_Xml_MissingCipherData); }
// default behaviour is to look for keys defined by an EncryptedKey clause // either directly or through a KeyInfoRetrievalMethod, and key names in the key mapping public virtual SymmetricAlgorithm GetDecryptionKey(EncryptedData encryptedData, string symmetricAlgorithmUri) { if (encryptedData == null) { throw new ArgumentNullException("encryptedData"); } if (encryptedData.KeyInfo == null) { return(null); } IEnumerator keyInfoEnum = encryptedData.KeyInfo.GetEnumerator(); KeyInfoRetrievalMethod kiRetrievalMethod; KeyInfoName kiName; KeyInfoEncryptedKey kiEncKey; EncryptedKey ek = null; while (keyInfoEnum.MoveNext()) { kiName = keyInfoEnum.Current as KeyInfoName; if (kiName != null) { // Get the decryption key from the key mapping string keyName = kiName.Value; if ((SymmetricAlgorithm)_keyNameMapping[keyName] != null) { return((SymmetricAlgorithm)_keyNameMapping[keyName]); } // try to get it from a CarriedKeyName XmlNamespaceManager nsm = new XmlNamespaceManager(_document.NameTable); nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl); XmlNodeList encryptedKeyList = _document.SelectNodes("//enc:EncryptedKey", nsm); if (encryptedKeyList != null) { foreach (XmlNode encryptedKeyNode in encryptedKeyList) { XmlElement encryptedKeyElement = encryptedKeyNode as XmlElement; EncryptedKey ek1 = new EncryptedKey(); ek1.LoadXml(encryptedKeyElement); if (ek1.CarriedKeyName == keyName && ek1.Recipient == Recipient) { ek = ek1; break; } } } break; } kiRetrievalMethod = keyInfoEnum.Current as KeyInfoRetrievalMethod; if (kiRetrievalMethod != null) { string idref = Utils.ExtractIdFromLocalUri(kiRetrievalMethod.Uri); ek = new EncryptedKey(); ek.LoadXml(GetIdElement(_document, idref)); break; } kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey; if (kiEncKey != null) { ek = kiEncKey.EncryptedKey; break; } } // if we have an EncryptedKey, decrypt to get the symmetric key if (ek != null) { // now process the EncryptedKey, loop recursively // If the Uri is not provided by the application, try to get it from the EncryptionMethod if (symmetricAlgorithmUri == null) { if (encryptedData.EncryptionMethod == null) { throw new CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); } symmetricAlgorithmUri = encryptedData.EncryptionMethod.KeyAlgorithm; } byte[] key = DecryptEncryptedKey(ek); if (key == null) { throw new CryptographicException(SR.Cryptography_Xml_MissingDecryptionKey); } SymmetricAlgorithm symAlg = (SymmetricAlgorithm)CryptoHelpers.CreateFromName(symmetricAlgorithmUri); symAlg.Key = key; return(symAlg); } return(null); }