Skip to content

Instantly share code, notes, and snippets.

@ukcoderj
Created June 11, 2019 15:49
Show Gist options
  • Save ukcoderj/39d8bd0e74bbe30d2f250853b7300239 to your computer and use it in GitHub Desktop.
Save ukcoderj/39d8bd0e74bbe30d2f250853b7300239 to your computer and use it in GitHub Desktop.
DPAPI - ProtectedData.Protect - Example for hiding sensitive information in Windows
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