using System; using System.Runtime.InteropServices; using System.Text; namespace ArchestrAServices.Common; public class DPUtility { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct DATA_BLOB { public int cbData; public IntPtr pbData; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct CRYPTPROTECT_PROMPTSTRUCT { public int cbSize; public int dwPromptFlags; public IntPtr hwndApp; public string szPrompt; } public enum Store { USE_MACHINE_STORE = 1, USE_USER_STORE } private static IntPtr NullPtr = (IntPtr)0; private const int CRYPTPROTECT_UI_FORBIDDEN = 1; private const int CRYPTPROTECT_LOCAL_MACHINE = 4; private Store store; [DllImport("Crypt32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool CryptProtectData(ref DATA_BLOB pDataIn, string szDataDescr, ref DATA_BLOB pOptionalEntropy, IntPtr pvReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPromptStruct, int dwFlags, ref DATA_BLOB pDataOut); [DllImport("Crypt32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool CryptUnprotectData(ref DATA_BLOB pDataIn, string szDataDescr, ref DATA_BLOB pOptionalEntropy, IntPtr pvReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPromptStruct, int dwFlags, ref DATA_BLOB pDataOut); public DPUtility(Store tempStore) { store = tempStore; } public byte[] Encrypt(byte[] plainText, byte[] optionalEntropy) { if (plainText == null || plainText.Length == 0) { if (optionalEntropy == null) { optionalEntropy = new byte[0]; } return new byte[0]; } DATA_BLOB pDataIn = default(DATA_BLOB); DATA_BLOB pDataOut = default(DATA_BLOB); DATA_BLOB pOptionalEntropy = default(DATA_BLOB); CRYPTPROTECT_PROMPTSTRUCT ps = default(CRYPTPROTECT_PROMPTSTRUCT); InitPromptstruct(ref ps); try { try { int num = plainText.Length; pDataIn.pbData = Marshal.AllocHGlobal(num); if (IntPtr.Zero == pDataIn.pbData) { throw new Exception("Unable to allocate plaintext buffer."); } pDataIn.cbData = num; Marshal.Copy(plainText, 0, pDataIn.pbData, num); } catch (Exception ex) { throw new Exception("Exception marshalling data. " + ex.Message); } int dwFlags; if (Store.USE_MACHINE_STORE == store) { dwFlags = 5; if (optionalEntropy == null) { optionalEntropy = new byte[0]; } try { int num2 = optionalEntropy.Length; pOptionalEntropy.pbData = Marshal.AllocHGlobal(optionalEntropy.Length); if (IntPtr.Zero == pOptionalEntropy.pbData) { throw new Exception("Unable to allocate entropy data buffer."); } Marshal.Copy(optionalEntropy, 0, pOptionalEntropy.pbData, num2); pOptionalEntropy.cbData = num2; } catch (Exception ex2) { throw new Exception("Exception entropy marshalling data. " + ex2.Message); } } else { dwFlags = 1; } if (!CryptProtectData(ref pDataIn, string.Empty, ref pOptionalEntropy, IntPtr.Zero, ref ps, dwFlags, ref pDataOut)) { throw new Exception("Encryption failed."); } if (IntPtr.Zero != pDataIn.pbData) { Marshal.FreeHGlobal(pDataIn.pbData); } if (IntPtr.Zero != pOptionalEntropy.pbData) { Marshal.FreeHGlobal(pOptionalEntropy.pbData); } } catch (Exception ex3) { throw new Exception("Exception encrypting. " + ex3.Message); } byte[] array = new byte[pDataOut.cbData]; Marshal.Copy(pDataOut.pbData, array, 0, pDataOut.cbData); Marshal.FreeHGlobal(pDataOut.pbData); return array; } private void InitPromptstruct(ref CRYPTPROTECT_PROMPTSTRUCT ps) { ps.cbSize = Marshal.SizeOf(typeof(CRYPTPROTECT_PROMPTSTRUCT)); ps.dwPromptFlags = 0; ps.hwndApp = NullPtr; ps.szPrompt = null; } public byte[] Decrypt(byte[] cipherText, byte[] optionalEntropy) { if (cipherText == null || cipherText.Length == 0) { if (optionalEntropy == null) { optionalEntropy = new byte[0]; } return new byte[0]; } DATA_BLOB pDataOut = default(DATA_BLOB); DATA_BLOB pDataIn = default(DATA_BLOB); CRYPTPROTECT_PROMPTSTRUCT ps = default(CRYPTPROTECT_PROMPTSTRUCT); InitPromptstruct(ref ps); try { try { int num = cipherText.Length; pDataIn.pbData = Marshal.AllocHGlobal(num); if (IntPtr.Zero == pDataIn.pbData) { throw new Exception("Unable to allocate cipherText buffer."); } pDataIn.cbData = num; Marshal.Copy(cipherText, 0, pDataIn.pbData, pDataIn.cbData); } catch (Exception ex) { throw new Exception("Exception marshalling data. " + ex.Message); } DATA_BLOB pOptionalEntropy = default(DATA_BLOB); int dwFlags; if (Store.USE_MACHINE_STORE == store) { dwFlags = 5; if (optionalEntropy == null) { optionalEntropy = new byte[0]; } try { int num2 = optionalEntropy.Length; pOptionalEntropy.pbData = Marshal.AllocHGlobal(num2); if (IntPtr.Zero == pOptionalEntropy.pbData) { throw new Exception("Unable to allocate entropy buffer."); } pOptionalEntropy.cbData = num2; Marshal.Copy(optionalEntropy, 0, pOptionalEntropy.pbData, num2); } catch (Exception ex2) { throw new Exception("Exception entropy marshalling data. " + ex2.Message); } } else { dwFlags = 1; } if (!CryptUnprotectData(ref pDataIn, null, ref pOptionalEntropy, IntPtr.Zero, ref ps, dwFlags, ref pDataOut)) { throw new Exception("Decryption failed."); } if (IntPtr.Zero != pDataIn.pbData) { Marshal.FreeHGlobal(pDataIn.pbData); } if (IntPtr.Zero != pOptionalEntropy.pbData) { Marshal.FreeHGlobal(pOptionalEntropy.pbData); } } catch (Exception ex3) { throw new Exception("Exception decrypting. " + ex3.Message); } byte[] array = new byte[pDataOut.cbData]; Marshal.Copy(pDataOut.pbData, array, 0, pDataOut.cbData); Marshal.FreeHGlobal(pDataOut.pbData); return array; } public byte[] GetOptionalEntropy() { return Encoding.Unicode.GetBytes("wonderware"); } }