gpt4 book ai didi

c# - 如何从 .Net/C# 调用 Schannel 函数

转载 作者:太空狗 更新时间:2023-10-29 22:22:44 26 4
gpt4 key购买 nike

出于合规性原因(我想在 .Net 中使用 256 位 AES 和临时 key ),我正在尝试重新排序/删除密码套件。但是,使用 WCF TCP 传输安全性,我将对安全性的所有控制都让给了 Windows 的 TLS 实现及其首选密码。我不想更改系统级密码。

我找到了这个 great Microsoft page列出了如何使用 BCryptEnumContextFunctions 在应用程序级别执行此操作, BCryptAddContextFunction , BCryptRemoveContextFunction ,但这全是 C,我没有足够的 P/Invoke 经验,甚至不知道从哪里开始。我用谷歌搜索但没有找到任何人这样做。

MSDN 页面上的 C++ 代码片段如下,我需要帮助将它们转换为 .Net P/Invoke 调用:

BCryptEnumContextFunctions

#include <stdio.h>
#include <windows.h>
#include <bcrypt.h>


void main()
{

HRESULT Status = ERROR_SUCCESS;
DWORD cbBuffer = 0;
PCRYPT_CONTEXT_FUNCTIONS pBuffer = NULL;

Status = BCryptEnumContextFunctions(
CRYPT_LOCAL,
L"SSL",
NCRYPT_SCHANNEL_INTERFACE,
&cbBuffer,
&pBuffer);
if(FAILED(Status))
{
printf_s("\n**** Error 0x%x returned by BCryptEnumContextFunctions\n", Status);
goto Cleanup;
}

if(pBuffer == NULL)
{
printf_s("\n**** Error pBuffer returned from BCryptEnumContextFunctions is null");
goto Cleanup;
}

printf_s("\n\n Listing Cipher Suites ");
for(UINT index = 0; index < pBuffer->cFunctions; ++index)
{
printf_s("\n%S", pBuffer->rgpszFunctions[index]);
}

Cleanup:
if (pBuffer != NULL)
{
BCryptFreeBuffer(pBuffer);
}
}

BCryptAddContextFunction

#include <stdio.h>
#include <windows.h>
#include <bcrypt.h>


void main()
{

SECURITY_STATUS Status = ERROR_SUCCESS;
LPWSTR wszCipher = (L"RSA_EXPORT1024_DES_CBC_SHA");

Status = BCryptAddContextFunction(
CRYPT_LOCAL,
L"SSL",
NCRYPT_SCHANNEL_INTERFACE,
wszCipher,
CRYPT_PRIORITY_TOP);
}

BCryptRemoveContextFunction

#include <stdio.h>
#include <windows.h>
#include <bcrypt.h>


void main()
{

SECURITY_STATUS Status = ERROR_SUCCESS;
LPWSTR wszCipher = (L"TLS_RSA_WITH_RC4_128_SHA");

Status = BCryptRemoveContextFunction(
CRYPT_LOCAL,
L"SSL",
NCRYPT_SCHANNEL_INTERFACE,
wszCipher);
}

有人可以帮我将它们转换为 .Net,以便我可以从托管代码中调用它们来调整密码吗?谢谢!

编辑:

昨晚晚些时候,我在测试程序中尝试了以下操作(仍然不知道我在 P/Invoke 中做了什么):

// I found this in bcrypt.h
const uint CRYPT_LOCAL = 0x00000001;
// I can't find this anywhere in Microsoft's headers in my SDK,
// but I found some random .c file with it in there. No idea
// what this constant actually is according to Microsoft
const uint NCRYPT_SCHANNEL_INTERFACE = 0x00010002;

public static void DoStuff()
{
PCRYPT_CONTEXT_FUNCTIONS pBuffer = new PCRYPT_CONTEXT_FUNCTIONS();
pBuffer.rgpszFunctions = String.Empty.PadRight(1500);
uint cbBuffer = (uint)Marshal.SizeOf(typeof(PCRYPT_CONTEXT_FUNCTIONS));

uint Status = BCryptEnumContextFunctions(
CRYPT_LOCAL,
"SSL",
NCRYPT_SCHANNEL_INTERFACE,
ref cbBuffer,
ref pBuffer);

Console.WriteLine(Status);
Console.WriteLine(pBuffer);
Console.WriteLine(cbBuffer);
Console.WriteLine(pBuffer.cFunctions);
Console.WriteLine(pBuffer.rgpszFunctions);
}
/*
typedef struct _CRYPT_CONTEXT_FUNCTIONS {
ULONG cFunctions;
PWSTR rgpszFunctions;
} CRYPT_CONTEXT_FUNCTIONS, *PCRYPT_CONTEXT_FUNCTIONS;
*/

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct PCRYPT_CONTEXT_FUNCTIONS
{
public uint cFunctions;
public string rgpszFunctions;
}

/*
NTSTATUS WINAPI BCryptEnumContextFunctions(
ULONG dwTable,
LPCWSTR pszContext,
ULONG dwInterface,
ULONG *pcbBuffer,
PCRYPT_CONTEXT_FUNCTIONS *ppBuffer
);
*/
[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern uint BCryptEnumContextFunctions(uint dwTable, string pszContext, uint dwInterface, ref uint pcbBuffer, ref PCRYPT_CONTEXT_FUNCTIONS ppBuffer);

到目前为止,我得到的唯一方法的输出是:

0
MyClass+PCRYPT_CONTEXT_FUNCTIONS
2400
8934576
[1500 spaces that I initialized rgpszFunctions with, not the cipher functions]

最佳答案

这是一个文档不足的库。例如,CRYPT_CONTEXT_FUNCTION_PROVIDERS 的声明实际上是:

typedef struct _CRYPT_CONTEXT_FUNCTION_PROVIDERS
{
ULONG cProviders;
PWSTR *rgpszProviders;
}
CRYPT_CONTEXT_FUNCTION_PROVIDERS, *PCRYPT_CONTEXT_FUNCTION_PROVIDERS;

这是直接从 bcrypt.h 中提取的。

无论如何,这是为您翻译的 C++ 代码:

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
class Program
{
[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
static extern uint BCryptEnumContextFunctions(uint dwTable, string pszContext, uint dwInterface, ref uint pcbBuffer, ref IntPtr ppBuffer);

[DllImport("Bcrypt.dll")]
static extern void BCryptFreeBuffer(IntPtr pvBuffer);

[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
static extern uint BCryptAddContextFunction(uint dwTable, string pszContext, uint dwInterface, string pszFunction, uint dwPosition);

[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
static extern uint BCryptRemoveContextFunction(uint dwTable, string pszContext, uint dwInterface, string pszFunction);

[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_CONTEXT_FUNCTIONS
{
public uint cFunctions;
public IntPtr rgpszFunctions;
}

const uint CRYPT_LOCAL = 0x00000001;
const uint NCRYPT_SCHANNEL_INTERFACE = 0x00010002;
const uint CRYPT_PRIORITY_TOP = 0x00000000;
const uint CRYPT_PRIORITY_BOTTOM = 0xFFFFFFFF;

public static void DoStuff()
{
uint cbBuffer = 0;
IntPtr ppBuffer = IntPtr.Zero;
uint Status = BCryptEnumContextFunctions(
CRYPT_LOCAL,
"SSL",
NCRYPT_SCHANNEL_INTERFACE,
ref cbBuffer,
ref ppBuffer);
if (Status == 0)
{
CRYPT_CONTEXT_FUNCTIONS functions = (CRYPT_CONTEXT_FUNCTIONS)Marshal.PtrToStructure(ppBuffer, typeof(CRYPT_CONTEXT_FUNCTIONS));
Console.WriteLine(functions.cFunctions);
IntPtr pStr = functions.rgpszFunctions;
for (int i = 0; i < functions.cFunctions; i++)
{
Console.WriteLine(Marshal.PtrToStringUni(Marshal.ReadIntPtr(pStr)));
pStr += IntPtr.Size;
}
BCryptFreeBuffer(ppBuffer);
}
}

static void Main(string[] args)
{
DoStuff();
Console.ReadLine();
}
}
}

在我的机器上输出是:

30TLS_RSA_WITH_AES_128_CBC_SHA256TLS_RSA_WITH_AES_128_CBC_SHATLS_RSA_WITH_AES_256_CBC_SHA256TLS_RSA_WITH_AES_256_CBC_SHATLS_RSA_WITH_RC4_128_SHATLS_RSA_WITH_3DES_EDE_CBC_SHATLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384TLS_DHE_DSS_WITH_AES_128_CBC_SHA256TLS_DHE_DSS_WITH_AES_128_CBC_SHATLS_DHE_DSS_WITH_AES_256_CBC_SHA256TLS_DHE_DSS_WITH_AES_256_CBC_SHATLS_DHE_DSS_WITH_3DES_EDE_CBC_SHATLS_RSA_WITH_RC4_128_MD5SSL_CK_RC4_128_WITH_MD5SSL_CK_DES_192_EDE3_CBC_WITH_MD5TLS_RSA_WITH_NULL_SHA256TLS_RSA_WITH_NULL_SHA

我敦促您掌握一些简单的 C++ 以取得进步。从 MSDN 中获取示例并编译它。在调试器下运行一下,熟悉一下。使用 Visual Studio 查找定义和声明。例如,Visual Studio 直接将我带到了 NCRYPT_SCHANNEL_INTERFACE 的定义。

关于c# - 如何从 .Net/C# 调用 Schannel 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19695623/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com