public static byte[] ProtectWithDpapiNG(ISecret secret, NCryptDescriptorHandle protectionDescriptorHandle)
        {
            Debug.Assert(secret != null);
            Debug.Assert(protectionDescriptorHandle != null);

            byte[] 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);
                }
            }
        }
        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;
            int 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)
            {
                byte[] retVal = new byte[cbProtectedData];
                if (cbProtectedData > 0)
                {
                    fixed (byte* pbRetVal = retVal)
                    {
                        bool handleAcquired = false;
            #if !NETSTANDARD1_3
                        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;
            }
        }