public static byte[] ProtectWithDpapiNG(ISecret secret, NCryptDescriptorHandle protectionDescriptorHandle) { Debug.Assert(secret != null); Debug.Assert(protectionDescriptorHandle != null); var plaintextSecret = new byte[secret.Length]; fixed(byte *pbPlaintextSecret = plaintextSecret) { try { secret.WriteSecretIntoBuffer(new ArraySegment <byte>(plaintextSecret)); byte dummy; // used to provide a valid memory address if secret is zero-length return(ProtectWithDpapiNGCore( protectionDescriptorHandle: protectionDescriptorHandle, pbData: (pbPlaintextSecret != null) ? pbPlaintextSecret : &dummy, cbData: (uint)plaintextSecret.Length)); } finally { // Limits secret exposure to garbage collector. Array.Clear(plaintextSecret, 0, plaintextSecret.Length); } } }
// http://msdn.microsoft.com/en-us/library/windows/desktop/hh706811(v=vs.85).aspx internal static extern int NCryptUnprotectSecret( [Out] out NCryptDescriptorHandle phDescriptor, [In] uint dwFlags, [In] byte *pbProtectedBlob, [In] uint cbProtectedBlob, [In] IntPtr pMemPara, [In] IntPtr hWnd, [Out] out LocalAllocHandle ppbData, [Out] out uint pcbData);
internal static extern int NCryptUnprotectSecret( #endif out NCryptDescriptorHandle phDescriptor, uint dwFlags, byte *pbProtectedBlob, uint cbProtectedBlob, IntPtr pMemPara, IntPtr hWnd, out LocalAllocHandle ppbData, out uint pcbData);
private static byte[] ProtectWithDpapiNGCore(NCryptDescriptorHandle protectionDescriptorHandle, byte *pbData, uint cbData) { Debug.Assert(protectionDescriptorHandle != null); Debug.Assert(pbData != null); // Perform the encryption operation, putting the protected data into LocalAlloc-allocated memory. LocalAllocHandle protectedData; uint cbProtectedData; var ntstatus = UnsafeNativeMethods.NCryptProtectSecret( hDescriptor: protectionDescriptorHandle, dwFlags: NCRYPT_SILENT_FLAG, pbData: pbData, cbData: cbData, pMemPara: IntPtr.Zero, hWnd: IntPtr.Zero, ppbProtectedBlob: out protectedData, pcbProtectedBlob: out cbProtectedData); UnsafeNativeMethods.ThrowExceptionForNCryptStatus(ntstatus); CryptoUtil.AssertSafeHandleIsValid(protectedData); // Copy the data from LocalAlloc-allocated memory into a managed memory buffer. using (protectedData) { var retVal = new byte[cbProtectedData]; if (cbProtectedData > 0) { fixed(byte *pbRetVal = retVal) { var handleAcquired = false; #if NETSTANDARD2_0 RuntimeHelpers.PrepareConstrainedRegions(); #endif try { protectedData.DangerousAddRef(ref handleAcquired); UnsafeBufferUtil.BlockCopy(from: (void *)protectedData.DangerousGetHandle(), to: pbRetVal, byteCount: cbProtectedData); } finally { if (handleAcquired) { protectedData.DangerousRelease(); } } } } return(retVal); } }
// https://msdn.microsoft.com/en-us/library/windows/desktop/hh706801(v=vs.85).aspx internal static extern int NCryptGetProtectionDescriptorInfo( [In] NCryptDescriptorHandle hDescriptor, [In] IntPtr pMemPara, [In] uint dwInfoType, [Out] out LocalAllocHandle ppvInfo);
// http://msdn.microsoft.com/en-us/library/windows/desktop/hh706800(v=vs.85).aspx internal static extern int NCryptCreateProtectionDescriptor( [In, MarshalAs(UnmanagedType.LPWStr)] string pwszDescriptorString, [In] uint dwFlags, [Out] out NCryptDescriptorHandle phDescriptor);
internal static extern int NCryptGetProtectionDescriptorInfo( #endif NCryptDescriptorHandle hDescriptor, IntPtr pMemPara, uint dwInfoType, out LocalAllocHandle ppvInfo);
internal static extern int NCryptCreateProtectionDescriptor( #endif [MarshalAs(UnmanagedType.LPWStr)] string pwszDescriptorString, uint dwFlags, out NCryptDescriptorHandle phDescriptor);