// Encrypts the given element with the key name specified. A corresponding key name mapping // has to be defined before calling this method. The key name is added as // a KeyNameInfo KeyInfo to an EncryptedKey (AES session key) generated randomly. public EncryptedData Encrypt(XmlElement inputElement, string keyName) { if (inputElement == null) { throw new ArgumentNullException("inputElement"); } if (keyName == null) { throw new ArgumentNullException("keyName"); } Object encryptionKey = null; if (m_keyNameMapping != null) { encryptionKey = m_keyNameMapping[keyName]; } if (encryptionKey == null) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingEncryptionKey")); } // kek is either a SymmetricAlgorithm or an RSA key, otherwise, we wouldn't be able to insert it in the hash table SymmetricAlgorithm symKey = encryptionKey as SymmetricAlgorithm; RSA rsa = encryptionKey as RSA; // Create the EncryptedData object, using an AES-256 session key by default. EncryptedData ed = new EncryptedData(); ed.Type = EncryptedXml.XmlEncElementUrl; ed.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url); // Include the key name in the EncryptedKey KeyInfo. string encryptionMethod = null; if (symKey == null) { encryptionMethod = EncryptedXml.XmlEncRSA15Url; } else if (symKey is TripleDES) { // CMS Triple DES Key Wrap encryptionMethod = EncryptedXml.XmlEncTripleDESKeyWrapUrl; } else if (symKey is Rijndael || symKey is Aes) { // FIPS AES Key Wrap switch (symKey.KeySize) { case 128: encryptionMethod = EncryptedXml.XmlEncAES128KeyWrapUrl; break; case 192: encryptionMethod = EncryptedXml.XmlEncAES192KeyWrapUrl; break; case 256: encryptionMethod = EncryptedXml.XmlEncAES256KeyWrapUrl; break; } } else { // throw an exception if the transform is not in the previous categories throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_NotSupportedCryptographicTransform")); } EncryptedKey ek = new EncryptedKey(); ek.EncryptionMethod = new EncryptionMethod(encryptionMethod); ek.KeyInfo.AddClause(new KeyInfoName(keyName)); // Create a random AES session key and encrypt it with the public key associated with the certificate. RijndaelManaged rijn = new RijndaelManaged(); ek.CipherData.CipherValue = (symKey == null ? EncryptedXml.EncryptKey(rijn.Key, rsa, false) : EncryptedXml.EncryptKey(rijn.Key, symKey)); // Encrypt the input element with the random session key that we've created above. KeyInfoEncryptedKey kek = new KeyInfoEncryptedKey(ek); ed.KeyInfo.AddClause(kek); ed.CipherData.CipherValue = EncryptData(inputElement, rijn, false); return(ed); }
// 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)m_keyNameMapping[keyName] != null) { return((SymmetricAlgorithm)m_keyNameMapping[keyName]); } // try to get it from a CarriedKeyName XmlNamespaceManager nsm = new XmlNamespaceManager(m_document.NameTable); nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl); XmlNodeList encryptedKeyList = m_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 == this.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(m_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(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm")); } symmetricAlgorithmUri = encryptedData.EncryptionMethod.KeyAlgorithm; } byte[] key = DecryptEncryptedKey(ek); if (key == null) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingDecryptionKey")); } SymmetricAlgorithm symAlg = (SymmetricAlgorithm)GostCryptoConfig.CreateFromName(symmetricAlgorithmUri); symAlg.Key = key; return(symAlg); } return(null); }
// 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) { // 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) { X509CertificateCollection collection = Utils.BuildBagOfCerts(kiX509Data, CertUsageType.Decryption); foreach (X509Certificate certificate in collection) { RSA privateKey = certificate.PrivateKey as RSA; if (privateKey != null) { 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)); return(DecryptEncryptedKey(ek)); } 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 = (SymmetricAlgorithm)GostCryptoConfig.CreateFromName(encryptedKey.EncryptionMethod.KeyAlgorithm); symAlg.Key = encryptionKey; return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, symAlg)); } } } return(null); }
public override void LoadXml(XmlElement value) { m_encryptedKey = new EncryptedKey(); m_encryptedKey.LoadXml(value); }
public KeyInfoEncryptedKey(EncryptedKey encryptedKey) { m_encryptedKey = encryptedKey; }
private SymmetricAlgorithm DecryptEncryptedKeyClass(EncryptedKey encryptedKey, string symmetricAlgorithmUri) { if (encryptedKey == null) { throw ExceptionUtility.ArgumentNull("encryptedKey"); } SymmetricAlgorithm decryptionKey = null; if (encryptedKey.KeyInfo != null) { foreach (var keyInfo in encryptedKey.KeyInfo) { // Извлечение ключа по имени if (keyInfo is KeyInfoName) { var keyName = ((KeyInfoName)keyInfo).Value; var keyAlgorithm = KeyNameMapping[keyName]; if (keyAlgorithm != null) { if (keyAlgorithm is SymmetricAlgorithm) { decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (SymmetricAlgorithm)keyAlgorithm, symmetricAlgorithmUri, encryptedKey.EncryptionMethod.KeyAlgorithm); } else if (keyAlgorithm is RSA) { var useOaep = (encryptedKey.EncryptionMethod != null) && (encryptedKey.EncryptionMethod.KeyAlgorithm == XmlEncRSAOAEPUrl); decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (RSA)keyAlgorithm, useOaep, symmetricAlgorithmUri); } else if (keyAlgorithm is Gost3410AsymmetricAlgorithmBase) { decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (Gost3410AsymmetricAlgorithmBase)keyAlgorithm); } } break; } // Извлечение ключа из сертификата if (keyInfo is KeyInfoX509Data) { var certificates = GostXmlUtils.BuildBagOfCertsDecryption((KeyInfoX509Data)keyInfo); foreach (var certificate in certificates) { var privateKey = certificate.GetPrivateKeyAlgorithm(); if (privateKey is RSA) { var useOaep = (encryptedKey.EncryptionMethod != null) && (encryptedKey.EncryptionMethod.KeyAlgorithm == XmlEncRSAOAEPUrl); decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (RSA)privateKey, useOaep, symmetricAlgorithmUri); } else if (privateKey is Gost3410AsymmetricAlgorithmBase) { decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, (Gost3410AsymmetricAlgorithmBase)privateKey); } } break; } // Извлечение ключа по ссылке if (keyInfo is KeyInfoRetrievalMethod) { var idValue = GostXmlUtils.ExtractIdFromLocalUri(((KeyInfoRetrievalMethod)keyInfo).Uri); var idElement = GetIdElement(Document, idValue); if (idElement != null) { var secondEncryptedKey = new EncryptedKey(); secondEncryptedKey.LoadXml(idElement); decryptionKey = DecryptEncryptedKeyClass(secondEncryptedKey, symmetricAlgorithmUri); } break; } // Ключ в готовом виде if (keyInfo is KeyInfoEncryptedKey) { var secondEncryptedKey = ((KeyInfoEncryptedKey)keyInfo).EncryptedKey; var symmetricAlgorithm = DecryptEncryptedKeyClass(secondEncryptedKey, symmetricAlgorithmUri); if (symmetricAlgorithm != null) { decryptionKey = DecryptKeyClass(encryptedKey.CipherData.CipherValue, symmetricAlgorithm, symmetricAlgorithmUri, encryptedKey.EncryptionMethod.KeyAlgorithm); } break; } } } return(decryptionKey); }
public override SymmetricAlgorithm GetDecryptionKey(EncryptedData encryptedData, string symmetricAlgorithmUri) { if (encryptedData == null) { throw ExceptionUtility.ArgumentNull("encryptedData"); } SymmetricAlgorithm decryptionKey = null; if (encryptedData.KeyInfo != null) { EncryptedKey encryptedKey = null; foreach (var keyInfo in encryptedData.KeyInfo) { // Извлечение ключа по имени if (keyInfo is KeyInfoName) { var keyName = ((KeyInfoName)keyInfo).Value; var keyAlgorithm = KeyNameMapping[keyName]; if (keyAlgorithm == null) { var nsManager = new XmlNamespaceManager(Document.NameTable); nsManager.AddNamespace("enc", XmlEncNamespaceUrl); var encryptedKeyNodes = Document.SelectNodes("//enc:EncryptedKey", nsManager); if (encryptedKeyNodes != null) { foreach (XmlElement encryptedKeyNode in encryptedKeyNodes) { var currentEncryptedKey = new EncryptedKey(); currentEncryptedKey.LoadXml(encryptedKeyNode); if ((currentEncryptedKey.CarriedKeyName == keyName) && (currentEncryptedKey.Recipient == Recipient)) { encryptedKey = currentEncryptedKey; break; } } } } else { decryptionKey = (SymmetricAlgorithm)keyAlgorithm; } break; } // Извлечение ключа по ссылке if (keyInfo is KeyInfoRetrievalMethod) { var idValue = GostXmlUtils.ExtractIdFromLocalUri(((KeyInfoRetrievalMethod)keyInfo).Uri); var idElement = GetIdElement(Document, idValue); if (idElement != null) { encryptedKey = new EncryptedKey(); encryptedKey.LoadXml(idElement); } break; } // Ключ в готовом виде if (keyInfo is KeyInfoEncryptedKey) { encryptedKey = ((KeyInfoEncryptedKey)keyInfo).EncryptedKey; break; } } if (decryptionKey == null && encryptedKey != null) { if (symmetricAlgorithmUri == null) { if (encryptedData.EncryptionMethod == null) { throw ExceptionUtility.CryptographicException(Resources.XmlMissingAlgorithm); } symmetricAlgorithmUri = encryptedData.EncryptionMethod.KeyAlgorithm; } decryptionKey = DecryptEncryptedKeyClass(encryptedKey, symmetricAlgorithmUri); } } return(decryptionKey); }
/// <summary> /// Извлекает ключ из элемента <EncryptedKey>. /// </summary> /// <param name="encryptedKey">Элемент <EncryptedKey> с информацией о ключе шифрования.</param> /// <returns>Массив байт, содержащий ключ для расшифровки.</returns> public byte[] DecryptEncryptedKey(EncryptedKey encryptedKey) { return(_encryptedXml.DecryptEncryptedKey(encryptedKey)); }