/// <summary> /// decrypt the data using DPAPI, data is a base64-encoded encrypted string /// </summary> /// <param name="data"></param> /// <param name="store"></param> /// <returns></returns> public static string Decrypt(string data, Store store) { // holds the result string string result = ""; // blobs used in the CryptUnprotectData call Win32.DATA_BLOB inBlob = new Win32.DATA_BLOB(); Win32.DATA_BLOB entropyBlob = new Win32.DATA_BLOB(); Win32.DATA_BLOB outBlob = new Win32.DATA_BLOB(); try { // setup flags passed to the CryptUnprotectData call int flags = Win32.CRYPTPROTECT_UI_FORBIDDEN | (int)((store == Store.Machine) ? Win32.CRYPTPROTECT_LOCAL_MACHINE : 0); // the CryptUnprotectData works with a byte array, convert string data byte[] bits = Convert.FromBase64String(data); // setup input blobs, the data to be decrypted and entropy blob SetBlobData(ref inBlob, bits); SetBlobData(ref entropyBlob, Consts.EntropyData); // call the DPAPI function, returns true if successful and fills in the outBlob if (Win32.CryptUnprotectData(ref inBlob, null, ref entropyBlob, IntPtr.Zero, IntPtr.Zero, flags, ref outBlob)) { byte[] resultBits = GetBlobData(ref outBlob); if (resultBits != null) { result = ASCIIEncoding.ASCII.GetString(resultBits); } } } catch { // an error occurred, return an empty string } finally { // clean up if (inBlob.pbData.ToInt32() != 0) { Marshal.FreeHGlobal(inBlob.pbData); } if (entropyBlob.pbData.ToInt32() != 0) { Marshal.FreeHGlobal(entropyBlob.pbData); } } return(result); }
/// <summary> /// helper method that gets data from a DATA_BLOB, /// copies data from unmanaged memory to managed /// </summary> /// <param name="blob"></param> /// <returns></returns> private static byte[] GetBlobData(ref Win32.DATA_BLOB blob) { // return an empty string if the blob is empty if (blob.pbData.ToInt32() == 0) { return(null); } // copy information from the blob byte[] data = new byte[blob.cbData]; Marshal.Copy(blob.pbData, data, 0, blob.cbData); Win32.LocalFree(blob.pbData); return(data); }
/// <summary> /// encrypt the data using DPAPI, returns a base64-encoded encrypted string /// </summary> /// <param name="data"></param> /// <param name="store"></param> /// <returns></returns> public static string Encrypt(string data, Store store) { // holds the result string string result = ""; // blobs used in the CryptProtectData call Win32.DATA_BLOB inBlob = new Win32.DATA_BLOB(); Win32.DATA_BLOB entropyBlob = new Win32.DATA_BLOB(); Win32.DATA_BLOB outBlob = new Win32.DATA_BLOB(); try { // setup flags passed to the CryptProtectData call int flags = Win32.CRYPTPROTECT_UI_FORBIDDEN | (int)((store == Store.Machine) ? Win32.CRYPTPROTECT_LOCAL_MACHINE : 0); // setup input blobs, the data to be encrypted and entropy blob SetBlobData(ref inBlob, ASCIIEncoding.ASCII.GetBytes(data)); SetBlobData(ref entropyBlob, EntropyData); // call the DPAPI function, returns true if successful and fills in the outBlob if (Win32.CryptProtectData(ref inBlob, "", ref entropyBlob, IntPtr.Zero, IntPtr.Zero, flags, ref outBlob)) { byte[] resultBits = GetBlobData(ref outBlob); if (resultBits != null) { result = Convert.ToBase64String(resultBits); } } } finally { // clean up if (inBlob.pbData.ToInt32() != 0) { Marshal.FreeHGlobal(inBlob.pbData); } if (entropyBlob.pbData.ToInt32() != 0) { Marshal.FreeHGlobal(entropyBlob.pbData); } } return(result); }
/// <summary> /// helper method that fills in a DATA_BLOB, copies /// data from managed to unmanaged memory /// </summary> /// <param name="blob"></param> /// <param name="bits"></param> private static void SetBlobData(ref Win32.DATA_BLOB blob, byte[] bits) { blob.cbData = bits.Length; blob.pbData = Marshal.AllocHGlobal(bits.Length); Marshal.Copy(bits, 0, blob.pbData, bits.Length); }