public override XmlNode Encrypt(XmlNode node) { RSACryptoServiceProvider cryptoServiceProvider = this.GetCryptoServiceProvider(false, false); XmlDocument document = new XmlDocument { PreserveWhitespace = true }; document.LoadXml("<foo>" + node.OuterXml + "</foo>"); EncryptedXml xml = new EncryptedXml(document); XmlElement documentElement = document.DocumentElement; SymmetricAlgorithm symmetricAlgorithm = new TripleDESCryptoServiceProvider(); byte[] randomKey = this.GetRandomKey(); symmetricAlgorithm.Key = randomKey; symmetricAlgorithm.Mode = CipherMode.ECB; symmetricAlgorithm.Padding = PaddingMode.PKCS7; byte[] buffer = xml.EncryptData(documentElement, symmetricAlgorithm, true); EncryptedData encryptedData = new EncryptedData { Type = "http://www.w3.org/2001/04/xmlenc#Element", EncryptionMethod = new EncryptionMethod("http://www.w3.org/2001/04/xmlenc#tripledes-cbc"), KeyInfo = new KeyInfo() }; EncryptedKey encryptedKey = new EncryptedKey { EncryptionMethod = new EncryptionMethod("http://www.w3.org/2001/04/xmlenc#rsa-1_5"), KeyInfo = new KeyInfo(), CipherData = new CipherData() }; encryptedKey.CipherData.CipherValue = EncryptedXml.EncryptKey(symmetricAlgorithm.Key, cryptoServiceProvider, this.UseOAEP); KeyInfoName clause = new KeyInfoName { Value = this._KeyName }; encryptedKey.KeyInfo.AddClause(clause); KeyInfoEncryptedKey key2 = new KeyInfoEncryptedKey(encryptedKey); encryptedData.KeyInfo.AddClause(key2); encryptedData.CipherData = new CipherData(); encryptedData.CipherData.CipherValue = buffer; EncryptedXml.ReplaceElement(documentElement, encryptedData, true); foreach (XmlNode node2 in document.ChildNodes) { if (node2.NodeType == XmlNodeType.Element) { foreach (XmlNode node3 in node2.ChildNodes) { if (node3.NodeType == XmlNodeType.Element) { return(node3); } } } } return(null); }
private void CheckEncryptionMethod(object algorithm, string uri) { XmlDocument doc = new XmlDocument(); doc.LoadXml("<root />"); EncryptedXml exml = new EncryptedXml(); exml.AddKeyNameMapping("key", algorithm); EncryptedData edata = exml.Encrypt(doc.DocumentElement, "key"); IEnumerator keyInfoEnum = edata.KeyInfo.GetEnumerator(); keyInfoEnum.MoveNext(); KeyInfoEncryptedKey kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey; Assert.NotNull(edata); Assert.Equal(uri, kiEncKey.EncryptedKey.EncryptionMethod.KeyAlgorithm); Assert.NotNull(edata.CipherData.CipherValue); }
/// <summary> /// Получает ключ для расшифровки на основе зашифрованных данных (из примеров криптопро) /// </summary> /// <param name="exml"></param> /// <param name="encryptedData"></param> /// <returns>Алгоритм для расшифровки</returns> private SymmetricAlgorithm GetDecryptionKey(EncryptedXml exml, EncryptedData encryptedData) { IEnumerator encryptedKeyEnumerator = encryptedData.KeyInfo.GetEnumerator(); // Проходим по всем KeyInfo while (encryptedKeyEnumerator.MoveNext()) { // Пропускам все что неизвестно. KeyInfoEncryptedKey current = encryptedKeyEnumerator.Current as KeyInfoEncryptedKey; if (current == null) { continue; } // До первого EncryptedKey EncryptedKey encryptedKey = current.EncryptedKey; if (encryptedKey == null) { continue; } KeyInfo keyinfo = encryptedKey.KeyInfo; // Проходим по всем KeyInfo зашифрования ключа. IEnumerator srcKeyEnumerator = keyinfo.GetEnumerator(); while (srcKeyEnumerator.MoveNext()) { // Пропускам все что неизвестно. KeyInfoX509Data keyInfoCert = srcKeyEnumerator.Current as KeyInfoX509Data; if (keyInfoCert == null) { continue; } AsymmetricAlgorithm alg = certOur.PrivateKey; // Приватный ключ, открытый ключ которого мы отправляли при шифровании запроса Gost3410 myKey = alg as Gost3410; // Преобразования if (myKey == null) { continue; } // Получаем и возвращаем ключ для расшифровки return(CPEncryptedXml.DecryptKeyClass(encryptedKey.CipherData.CipherValue, myKey, encryptedData.EncryptionMethod.KeyAlgorithm)); } } return(null); }
// Override EncryptedXml.GetDecryptionKey to avoid calling into CryptoConfig.CreateFromName // When detect AES, we need to return AesCryptoServiceProvider (FIPS certified) instead of AesManaged (FIPS obsolated) public override SymmetricAlgorithm GetDecryptionKey(EncryptedData encryptedData, string symmetricAlgorithmUri) { // If AES is used then assume FIPS is required bool fipsRequired = IsAesDetected(encryptedData, symmetricAlgorithmUri); if (fipsRequired) { // Obtain the EncryptedKey EncryptedKey ek = null; foreach (var ki in encryptedData.KeyInfo) { KeyInfoEncryptedKey kiEncKey = ki as KeyInfoEncryptedKey; if (kiEncKey != null) { ek = kiEncKey.EncryptedKey; break; } } // Got an EncryptedKey, decrypt it to get the AES key if (ek != null) { byte[] key = DecryptEncryptedKey(ek); // Construct FIPS-certified AES provider if (key != null) { AesCryptoServiceProvider aes = new AesCryptoServiceProvider(); aes.Key = key; return(aes); } } } // Fallback to the base implementation return(base.GetDecryptionKey(encryptedData, symmetricAlgorithmUri)); }
public Stream Decrypt(EncryptionMethod encryptionMethod, KeyInfo keyInfo, Stream toDecrypt) { Assert.NotNull(encryptionMethod); Assert.NotNull(keyInfo); Assert.NotNull(toDecrypt); Assert.True(encryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncAES128Url || encryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncAES192Url || encryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncAES256Url); Assert.Equal(keyInfo.Count, 1); byte[] decryptedKey = null; foreach (KeyInfoClause clause in keyInfo) { if (clause is KeyInfoEncryptedKey) { KeyInfoEncryptedKey encryptedKeyInfo = clause as KeyInfoEncryptedKey; EncryptedKey encryptedKey = encryptedKeyInfo.EncryptedKey; Assert.Equal(encryptedKey.EncryptionMethod.KeyAlgorithm, EncryptedXml.XmlEncRSAOAEPUrl); Assert.Equal(encryptedKey.KeyInfo.Count, 1); Assert.NotEqual(_asymmetricKeys.Count, 0); RSAParameters rsaParams = new RSAParameters(); RSAParameters rsaInputParams = new RSAParameters(); foreach (KeyInfoClause rsa in encryptedKey.KeyInfo) { if (rsa is RSAKeyValue) { rsaParams = (rsa as RSAKeyValue).Key.ExportParameters(false); break; } else { Assert.True(false, "Invalid License - MalformedKeyInfoClause"); } } bool keyMismatch = true; foreach (AsymmetricAlgorithm key in _asymmetricKeys) { RSA rsaKey = key as RSA; Assert.NotNull(rsaKey); rsaInputParams = rsaKey.ExportParameters(false); if (!PublicKeysEqual(rsaParams, rsaInputParams)) { continue; } keyMismatch = false; // Decrypt session key byte[] encryptedKeyValue = encryptedKey.CipherData.CipherValue; if (encryptedKeyValue == null) { throw new CryptographicException("MissingKeyCipher"); } decryptedKey = EncryptedXml.DecryptKey(encryptedKeyValue, rsaKey, true); break; } if (keyMismatch) { throw new Exception("Invalid License - AsymmetricKeyMismatch"); } } else if (clause is KeyInfoName) { Assert.True(false, "This test should not have KeyInfoName clauses"); } else { throw new CryptographicException("MalformedKeyInfoClause"); } break; } if (decryptedKey == null) { throw new CryptographicException("KeyDecryptionFailure"); } using (Aes aes = Aes.Create()) { aes.Key = decryptedKey; aes.Padding = PaddingMode.PKCS7; aes.Mode = CipherMode.CBC; return(DecryptStream(toDecrypt, aes)); } }
/// <summary> /// Encrypts the XML node passed to it. /// </summary> /// <param name="node">The XmlNode to encrypt.</param> /// <returns></returns> public override XmlNode Encrypt(XmlNode node) { // Get the RSA public key to encrypt the node. This key will encrypt // a symmetric key, which will then be encryped in the XML document. RSACryptoServiceProvider cryptoServiceProvider = this.GetCryptoServiceProvider(true); // Create an XML document and load the node to be encrypted in it. XmlDocument document = new XmlDocument(); document.PreserveWhitespace = true; document.LoadXml("<Data>" + node.OuterXml + "</Data>"); // Create a new instance of the EncryptedXml class // and use it to encrypt the XmlElement with the // a new random symmetric key. EncryptedXml xml = new EncryptedXml(document); XmlElement documentElement = document.DocumentElement; SymmetricAlgorithm symmetricAlgorithm = new RijndaelManaged(); // Create a 192 bit random key. symmetricAlgorithm.Key = this.GetRandomKey(); symmetricAlgorithm.GenerateIV(); symmetricAlgorithm.Padding = PaddingMode.PKCS7; byte[] buffer = xml.EncryptData(documentElement, symmetricAlgorithm, true); // Construct an EncryptedData object and populate // it with the encryption information. EncryptedData encryptedData = new EncryptedData(); encryptedData.Type = EncryptedXml.XmlEncElementUrl; // Create an EncryptionMethod element so that the // receiver knows which algorithm to use for decryption. encryptedData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES192Url); encryptedData.KeyInfo = new KeyInfo(); // Encrypt the session key and add it to an EncryptedKey element. EncryptedKey encryptedKey = new EncryptedKey(); encryptedKey.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url); encryptedKey.KeyInfo = new KeyInfo(); encryptedKey.CipherData = new CipherData(); encryptedKey.CipherData.CipherValue = EncryptedXml.EncryptKey(symmetricAlgorithm.Key, cryptoServiceProvider, false); KeyInfoName clause = new KeyInfoName(); clause.Value = "rsaKey"; // Add the encrypted key to the EncryptedData object. encryptedKey.KeyInfo.AddClause(clause); KeyInfoEncryptedKey key2 = new KeyInfoEncryptedKey(encryptedKey); encryptedData.KeyInfo.AddClause(key2); encryptedData.CipherData = new CipherData(); encryptedData.CipherData.CipherValue = buffer; // Replace the element from the original XmlDocument // object with the EncryptedData element. EncryptedXml.ReplaceElement(documentElement, encryptedData, true); foreach (XmlNode node2 in document.ChildNodes) { if (node2.NodeType == XmlNodeType.Element) { foreach (XmlNode node3 in node2.ChildNodes) { if (node3.NodeType == XmlNodeType.Element) { return(node3); } } } } return(null); }
public Stream Decrypt(EncryptionMethod encryptionMethod, KeyInfo keyInfo, Stream toDecrypt) { Assert.NotNull(encryptionMethod); Assert.NotNull(keyInfo); Assert.NotNull(toDecrypt); Assert.True(encryptionMethod.KeyAlgorithm == NS.XmlEncAES128Url || encryptionMethod.KeyAlgorithm == NS.XmlEncAES192Url || encryptionMethod.KeyAlgorithm == NS.XmlEncAES256Url); Assert.Equal(keyInfo.Count, 1); byte[] decryptedKey = null; foreach (KeyInfoClause clause in keyInfo) { if (clause is KeyInfoEncryptedKey) { KeyInfoEncryptedKey encryptedKeyInfo = clause as KeyInfoEncryptedKey; EncryptedKey encryptedKey = encryptedKeyInfo.GetEncryptedKey(); Assert.Equal(encryptedKey.EncryptionMethod.KeyAlgorithm, NS.XmlEncRSAOAEPUrl); Assert.Equal(encryptedKey.KeyInfo.Count, 1); Assert.NotEqual(_asymmetricKeys.Count, 0); RsaKeyParameters rsaParams = null; RsaKeyParameters rsaInputParams = null; foreach (KeyInfoClause rsa in encryptedKey.KeyInfo) { if (rsa is RsaKeyValue) { rsaParams = (rsa as RsaKeyValue).GetKey(); break; } else { Assert.True(false, "Invalid License - MalformedKeyInfoClause"); } } bool keyMismatch = true; foreach (AsymmetricCipherKeyPair key in _asymmetricKeys) { RsaKeyParameters rsaKey = key.Private as RsaKeyParameters; Assert.NotNull(rsaKey); rsaInputParams = key.Public as RsaKeyParameters; Assert.NotNull(rsaInputParams); if (!PublicKeysEqual(rsaParams, rsaInputParams)) { continue; } keyMismatch = false; byte[] encryptedKeyValue = encryptedKey.CipherData.CipherValue; if (encryptedKeyValue == null) { throw new System.Security.Cryptography.CryptographicException("MissingKeyCipher"); } decryptedKey = XmlDecryption.DecryptKey(encryptedKeyValue, rsaKey, true); break; } if (keyMismatch) { throw new Exception("Invalid License - AsymmetricKeyMismatch"); } } else if (clause is KeyInfoName) { Assert.True(false, "This test should not have KeyInfoName clauses"); } else { throw new System.Security.Cryptography.CryptographicException("MalformedKeyInfoClause"); } break; } if (decryptedKey == null) { throw new System.Security.Cryptography.CryptographicException("KeyDecryptionFailure"); } return(DecryptStream(toDecrypt, new KeyParameter(decryptedKey), "AES/CBC/PKCS7")); }
public override XmlNode Encrypt(XmlNode node) { XmlDocument xmlDocument; EncryptedXml exml; byte[] rgbOutput; EncryptedData ed; KeyInfoName kin; EncryptedKey ek; KeyInfoEncryptedKey kek; XmlElement inputElement; RSACryptoServiceProvider rsa = GetCryptoServiceProvider(false, false); // Encrypt the node with the new key xmlDocument = new XmlDocument(); xmlDocument.PreserveWhitespace = true; xmlDocument.LoadXml("<foo>" + node.OuterXml + "</foo>"); exml = new EncryptedXml(xmlDocument); inputElement = xmlDocument.DocumentElement; using (SymmetricAlgorithm symAlg = GetSymAlgorithmProvider()) { rgbOutput = exml.EncryptData(inputElement, symAlg, true); ed = new EncryptedData(); ed.Type = EncryptedXml.XmlEncElementUrl; ed.EncryptionMethod = GetSymEncryptionMethod(); ed.KeyInfo = new KeyInfo(); ek = new EncryptedKey(); ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url); ek.KeyInfo = new KeyInfo(); ek.CipherData = new CipherData(); ek.CipherData.CipherValue = EncryptedXml.EncryptKey(symAlg.Key, rsa, UseOAEP); } kin = new KeyInfoName(); kin.Value = _KeyName; ek.KeyInfo.AddClause(kin); kek = new KeyInfoEncryptedKey(ek); ed.KeyInfo.AddClause(kek); ed.CipherData = new CipherData(); ed.CipherData.CipherValue = rgbOutput; EncryptedXml.ReplaceElement(inputElement, ed, true); rsa.Clear(); // Get node from the document foreach (XmlNode node2 in xmlDocument.ChildNodes) { if (node2.NodeType == XmlNodeType.Element) { foreach (XmlNode node3 in node2.ChildNodes) // node2 is the "foo" node { if (node3.NodeType == XmlNodeType.Element) { return(node3); // node3 is the "EncryptedData" node } } } } return(null); }
/// <summary> /// An example on how to decrypt an encrypted assertion. /// </summary> private static void DecryptAssertion(string file) { XmlDocument doc = new XmlDocument(); doc.Load(file); XmlElement encryptedDataElement = GetElement(dk.nita.saml20.Schema.XEnc.EncryptedData.ELEMENT_NAME, Saml20Constants.XENC, doc); EncryptedData encryptedData = new EncryptedData(); encryptedData.LoadXml(encryptedDataElement); XmlNodeList nodelist = doc.GetElementsByTagName(dk.nita.saml20.Schema.XmlDSig.KeyInfo.ELEMENT_NAME, Saml20Constants.XMLDSIG); Assert.That(nodelist.Count > 0); KeyInfo key = new KeyInfo(); key.LoadXml((XmlElement)nodelist[0]); // Review: Is it possible to figure out which certificate to load based on the Token? /* * Comment: * It would be possible to provide a key/certificate identifier in the EncryptedKey element, which contains the "recipient" attribute. * The implementation (Safewhere.Tokens.Saml20.Saml20EncryptedAssertion) currently just expects an appropriate asymmetric key to be provided, * and is not not concerned about its origin. * If the need arises, we can easily extend the Saml20EncryptedAssertion class with a property that allows extraction key info, eg. the "recipient" * attribute. */ X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\sts_dev_certificate.pfx", "test1234"); // ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.NETDEVFX.v20.en/CPref18/html/T_System_Security_Cryptography_Xml_KeyInfoClause_DerivedTypes.htm // Look through the list of KeyInfo elements to find the encrypted key. SymmetricAlgorithm symmetricKey = null; foreach (KeyInfoClause keyInfoClause in key) { if (keyInfoClause is KeyInfoEncryptedKey) { KeyInfoEncryptedKey keyInfoEncryptedKey = (KeyInfoEncryptedKey)keyInfoClause; EncryptedKey encryptedKey = keyInfoEncryptedKey.EncryptedKey; symmetricKey = new RijndaelManaged(); symmetricKey.Key = EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (RSA)cert.PrivateKey, false); continue; } } // Explode if we didn't manage to find a viable key. Assert.IsNotNull(symmetricKey); EncryptedXml encryptedXml = new EncryptedXml(); byte[] plaintext = encryptedXml.DecryptData(encryptedData, symmetricKey); XmlDocument assertion = new XmlDocument(); assertion.Load(new StringReader(System.Text.Encoding.UTF8.GetString(plaintext))); // A very simple test to ensure that there is indeed an assertion in the plaintext. Assert.AreEqual(Assertion.ELEMENT_NAME, assertion.DocumentElement.LocalName); Assert.AreEqual(Saml20Constants.ASSERTION, assertion.DocumentElement.NamespaceURI); }