| File: System\Configuration\DpapiProtectedConfigurationProvider.cs | Web Access |
| Project: src\runtime\src\libraries\System.Configuration.ConfigurationManager\src\System.Configuration.ConfigurationManager.csproj (System.Configuration.ConfigurationManager) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Specialized; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Xml; namespace System.Configuration { [SupportedOSPlatform("windows")] public sealed class DpapiProtectedConfigurationProvider : ProtectedConfigurationProvider { private bool _useMachineProtection = true; private string _keyEntropy; public override XmlNode Decrypt(XmlNode encryptedNode) { if (encryptedNode.NodeType != XmlNodeType.Element || encryptedNode.Name != "EncryptedData") { throw new ConfigurationErrorsException(SR.DPAPI_bad_data); } XmlNode cipherNode = TraverseToChild(encryptedNode, "CipherData", false); if (cipherNode == null) throw new ConfigurationErrorsException(SR.DPAPI_bad_data); XmlNode cipherValue = TraverseToChild(cipherNode, "CipherValue", true); if (cipherValue == null) throw new ConfigurationErrorsException(SR.DPAPI_bad_data); string encText = cipherValue.InnerText; if (encText == null) throw new ConfigurationErrorsException(SR.DPAPI_bad_data); string decText = DecryptText(encText); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.PreserveWhitespace = true; xmlDocument.LoadXml(decText); return xmlDocument.DocumentElement; } public override XmlNode Encrypt(XmlNode node) { string text = node.OuterXml; string encText = EncryptText(text); string pre = @"<EncryptedData><CipherData><CipherValue>"; string post = @"</CipherValue></CipherData></EncryptedData>"; string xmlText = pre + encText + post; XmlDocument xmlDocument = new XmlDocument(); xmlDocument.PreserveWhitespace = true; xmlDocument.LoadXml(xmlText); return xmlDocument.DocumentElement; } private string EncryptText(string clearText) { if (clearText == null || clearText.Length < 1) return clearText; byte[] inputData = PrepareDataBlob(clearText); byte[] entropyData = PrepareDataBlob(_keyEntropy); byte[] encryptedData = ProtectedData.Protect( userData: inputData, optionalEntropy: entropyData, scope: UseMachineProtection ? DataProtectionScope.LocalMachine : DataProtectionScope.CurrentUser); return Convert.ToBase64String(encryptedData); } private string DecryptText(string encText) { if (encText == null || encText.Length < 1) return encText; byte[] inputData = Convert.FromBase64String(encText); byte[] entropyData = PrepareDataBlob(_keyEntropy); byte[] decryptedData = ProtectedData.Unprotect( encryptedData: inputData, optionalEntropy: entropyData, scope: UseMachineProtection ? DataProtectionScope.LocalMachine : DataProtectionScope.CurrentUser); return Encoding.Unicode.GetString(decryptedData); } public bool UseMachineProtection { get { return _useMachineProtection; } } public override void Initialize(string name, NameValueCollection configurationValues) { base.Initialize(name, configurationValues); _useMachineProtection = GetBooleanValue(configurationValues, "useMachineProtection", true); _keyEntropy = configurationValues["keyEntropy"]; configurationValues.Remove("keyEntropy"); if (configurationValues.Count > 0) throw new ConfigurationErrorsException(SR.Format(SR.Unrecognized_initialization_value, configurationValues.GetKey(0))); } private static XmlNode TraverseToChild(XmlNode node, string name, bool onlyChild) { foreach (XmlNode child in node.ChildNodes) { if (child.NodeType != XmlNodeType.Element) continue; if (child.Name == name) return child; // found it! if (onlyChild) return null; } return null; } private static byte[] PrepareDataBlob(string s) { return (s != null) ? Encoding.Unicode.GetBytes(s) : Array.Empty<byte>(); } private static bool GetBooleanValue(NameValueCollection configurationValues, string valueName, bool defaultValue) { string s = configurationValues[valueName]; if (s == null) return defaultValue; configurationValues.Remove(valueName); if (s == "true") return true; if (s == "false") return false; throw new ConfigurationErrorsException(SR.Format(SR.Config_invalid_boolean_attribute, valueName)); } } }