#region Copyright 2010-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0 /* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #endregion using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.ComponentModel; namespace CSharpTest.Net.Crypto { /// /// Provides the ability to encrypt and decrypt data accessable by the current /// process only, requires /// public class RtlProcessKey : AsymmetricKey { /// Returns a single instance of the encryptor, it's thread-safe. public static readonly IEncryptDecrypt Encryptor = new RtlProcessKey(); const int BLOCK = 32; /// The size of an input block protected override int BlockSize { get { return BLOCK - 1; } } /// The size of an output block protected override int TransformSize { get { return BLOCK; } } /// Encrypts the block of data protected override byte[] EncryptBlock(byte[] blob) { byte[] output = new byte[BLOCK]; GCHandle h = GCHandle.Alloc(output, GCHandleType.Pinned); try { output[0] = (byte)blob.Length; Array.Copy(blob, 0, output, 1, blob.Length); Win32.Protect(h.AddrOfPinnedObject(), BLOCK); return output; } finally { h.Free(); } } /// Decrypts the block of data protected override byte[] DecryptBlock(byte[] blob) { byte[] temp = new byte[BLOCK]; GCHandle h = GCHandle.Alloc(temp, GCHandleType.Pinned); try { Array.Copy(blob, 0, temp, 0, blob.Length); Win32.Unprotect(h.AddrOfPinnedObject(), BLOCK); byte[] result = new byte[Check.InRange(temp[0], 0, BLOCK - 1)]; Array.Copy(temp, 1, result, 0, result.Length); Array.Clear(temp, 0, temp.Length); return result; } finally { h.Free(); } } /// Uses the same API as System.Security.SecureString private static class Win32 { //Vista/2k3 only : [DllImport("Crypt32.dll")] [DllImport("advapi32.dll", EntryPoint="SystemFunction040", SetLastError = true)] static extern int CryptProtectMemory(IntPtr pDataIn, int cbDataIn, int dwFlags); //Vista/2k3 only : [DllImport("Crypt32.dll")] [DllImport("advapi32.dll", EntryPoint = "SystemFunction041", SetLastError = true)] static extern int CryptUnprotectMemory(IntPtr pData, int cbData, int dwFlags); public static void Protect(IntPtr ptr, int szBytes) { Check.Assert(CryptProtectMemory(ptr, szBytes, 0) >= 0); } public static void Unprotect(IntPtr ptr, int szBytes) { Check.Assert(CryptUnprotectMemory(ptr, szBytes, 0) >= 0); } } } }