Created
June 11, 2019 15:49
-
-
Save ukcoderj/39d8bd0e74bbe30d2f250853b7300239 to your computer and use it in GitHub Desktop.
DPAPI - ProtectedData.Protect - Example for hiding sensitive information in Windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Security.Cryptography; | |
using System.Text; | |
namespace TestConsole | |
{ | |
/// <summary> | |
/// Uses DPAPI for hiding sensitive information | |
/// Adapted from MSDN: https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata?redirectedfrom=MSDN&view=netframework-4.8 | |
/// | |
/// NOTE: You will need to add a reference to | |
/// System.Security for this class. | |
/// </summary> | |
public class StringProtectionHelper | |
{ | |
// Create byte array for additional entropy when using Protect method. | |
byte[] _additionalEntropy = { 5, 6, 7, 8, 0 }; | |
public void TestDataProtection() | |
{ | |
// This is our key that must not appear anywhere in source code! | |
var key = "qwertyuiopasdfghjklzxcvbnm=="; | |
var protectionScope = DataProtectionScope.CurrentUser; | |
var base64ToStore = GetProtectedString(key, protectionScope); | |
Console.WriteLine($"Safe to store this: {base64ToStore}"); | |
var unProtectedString = GetUnProtectString(base64ToStore, protectionScope); | |
Debug.Equals(key, unProtectedString); | |
} | |
/// <summary> | |
/// Encrypts a string in the scope provided and returns the base64 output | |
/// </summary> | |
/// <param name="stringToHide">The key or data to encrypt</param> | |
/// <param name="dataProtectionScope">The scope of encryption e.g. DataProtectionScope.CurrentUser, or DataProtectionScope.LocalMachine.</param> | |
/// <returns>A base64 string of the key that can only be decrypted by the scope provided.</returns> | |
public string GetProtectedString(string stringToHide, DataProtectionScope dataProtectionScope) | |
{ | |
byte[] stringAsBytes = Encoding.Unicode.GetBytes(stringToHide); | |
byte[] protectedData = Protect(stringAsBytes, dataProtectionScope); | |
string protectedDataAsBase64String = Convert.ToBase64String(protectedData); | |
return protectedDataAsBase64String; | |
} | |
/// <summary> | |
/// Converts base64 output from ProtectString and converts it to original value. | |
/// </summary> | |
/// <param name="base64StringToUnprotect">The base64 string output of protecting the key/data.</param> | |
/// <param name="dataProtectionScope">The scope of encryption e.g. DataProtectionScope.CurrentUser, or DataProtectionScope.LocalMachine.</param> | |
/// <returns>The original key/ unencrypted data for use</returns> | |
public string GetUnProtectString(string base64StringToUnprotect, DataProtectionScope dataProtectionScope) | |
{ | |
byte[] base64StringBytes = Convert.FromBase64String(base64StringToUnprotect); | |
var unProtectedDetails = Unprotect(base64StringBytes, dataProtectionScope); | |
var unprotectString = Encoding.Unicode.GetString(unProtectedDetails); | |
return unprotectString; | |
} | |
/// <summary> | |
/// Takes a resource and protects it within the scope provided. | |
/// </summary> | |
/// <param name="data">the data you would like to convert (e.g. a key or data)</param> | |
/// <param name="dataProtectionScope">The scope of encryption e.g. DataProtectionScope.CurrentUser, or DataProtectionScope.LocalMachine.</param> | |
/// <returns>The encrypted data as a byte array (needs converting to a base64 string to be storable in text.</returns> | |
private byte[] Protect(byte[] data, DataProtectionScope dataProtectionScope) | |
{ | |
try | |
{ | |
return ProtectedData.Protect(data, _additionalEntropy, dataProtectionScope); | |
} | |
catch (CryptographicException e) | |
{ | |
Console.WriteLine("Data was not encrypted. An error occurred."); | |
Console.WriteLine(e.ToString()); | |
return null; | |
} | |
} | |
/// <summary> | |
/// Unprotects a protected byte array | |
/// </summary> | |
/// <param name="data">byte array created by the protect method</param> | |
/// <param name="dataProtectionScope">The scope of encryption e.g. DataProtectionScope.CurrentUser, or DataProtectionScope.LocalMachine.</param> | |
/// <returns>The original key/data passed to the protect method.</returns> | |
private byte[] Unprotect(byte[] data, DataProtectionScope dataProtectionScope) | |
{ | |
try | |
{ | |
return ProtectedData.Unprotect(data, _additionalEntropy, dataProtectionScope); | |
} | |
catch (CryptographicException e) | |
{ | |
Console.WriteLine("Data was not decrypted. An error occurred."); | |
Console.WriteLine(e.ToString()); | |
return null; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment