Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 以编程方式安装证书吊销列表C_C#_.net_Wcf_Wcf Security_Certificate Revocation - Fatal编程技术网

C# 以编程方式安装证书吊销列表C

C# 以编程方式安装证书吊销列表C,c#,.net,wcf,wcf-security,certificate-revocation,C#,.net,Wcf,Wcf Security,Certificate Revocation,我正在使用C/WCF。我有一个由客户端调用的web服务。 这是服务定义: 这就是约束力: 如果我理解正确,从服务器发送到客户端的消息将使用证书进行加密。目前我仍在使用开发者证书。 我在服务器上创建了根证书、证书更新列表和密钥 我正在使用Windows Installer安装客户端,我有一个自定义安装操作来安装证书 下面的代码显示了如何将证书添加到存储中 Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManif

我正在使用C/WCF。我有一个由客户端调用的web服务。 这是服务定义:

这就是约束力:

如果我理解正确,从服务器发送到客户端的消息将使用证书进行加密。目前我仍在使用开发者证书。 我在服务器上创建了根证书、证书更新列表和密钥

我正在使用Windows Installer安装客户端,我有一个自定义安装操作来安装证书

下面的代码显示了如何将证书添加到存储中

Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ClientCertificates.MyRoot.cer");
byte[] buffer = new byte[((int)(manifestResourceStream.Length - 1L)) + 1];
manifestResourceStream.Read(buffer, 0, (int)manifestResourceStream.Length);
manifestResourceStream.Close();

var cert = new X509Certificate2(buffer);
var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
store.Close();

/*
// The CRL is also needed, no idea why
manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ClientCertificates.MyRoot.crl");
buffer = new byte[((int)(manifestResourceStream.Length - 1L)) + 1];
manifestResourceStream.Read(buffer, 0, (int)manifestResourceStream.Length);
manifestResourceStream.Close();
cert = new X509Certificate2(buffer);
store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
store.Close();
*/

// This is the key 
manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ClientCertificates.MyTestServer.cer");
buffer = new byte[((int)(manifestResourceStream.Length - 1L)) + 1];
manifestResourceStream.Read(buffer, 0, (int)manifestResourceStream.Length);
manifestResourceStream.Close();

cert = new X509Certificate2(buffer);
store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
store.Close();
我现在有两种行为: 安装证书是可行的,但是当我调用web服务时,我得到一个SecurityNegotiationException。 当我手动添加证书吊销列表时,与服务器的通信正常。 当我尝试以编程方式执行时,看到上面的代码,它就不起作用了。我收到一个“找不到请求的对象”异常

我尝试使用不同的商店,但没有成功

我有两个问题: a为什么我需要客户机上的CRL? b如果我需要它,我如何以编程方式安装它?上面我的错误在哪里

谢谢你的帮助,
Kay

一般来说,CRL必须在线可用,并且可以从服务器证书中指定的吊销URL下载。我不知道是否有带外机制来获取它,但即使有,它也有点违背了允许客户端发现服务器证书已被泄露/吊销的目的。这就是说,CRL对于自签名证书来说真是杀伤力太大了,除非您使用证书进行真正的相互身份验证,并且担心密钥被泄露。在这种情况下,购买一个商业证书,让他们处理它

如果您无法在没有撤销URL的情况下获得生成的证书,我建议您完全禁用CRL的客户端检查,除非您确实需要它。您可以通过将以下内容添加到webservice客户端的app.config来完成此操作:

  <system.net>
    <settings>
      <servicePointManager checkCertificateRevocationList="false"/>
    </settings>
  </system.net>

如果您正在使用WCF,您可能需要在serviceCertificate->revocationMode:NoCheck下使用clientCredentials endpointBehavior将其连接起来。

通常,CRL必须在线可用,并且可以从服务器证书中指定的吊销URL下载。我不知道是否有带外机制来获取它,但即使有,它也有点违背了允许客户端发现服务器证书已被泄露/吊销的目的。这就是说,CRL对于自签名证书来说真是杀伤力太大了,除非您使用证书进行真正的相互身份验证,并且担心密钥被泄露。在这种情况下,购买一个商业证书,让他们处理它

如果您无法在没有撤销URL的情况下获得生成的证书,我建议您完全禁用CRL的客户端检查,除非您确实需要它。您可以通过将以下内容添加到webservice客户端的app.config来完成此操作:

  <system.net>
    <settings>
      <servicePointManager checkCertificateRevocationList="false"/>
    </settings>
  </system.net>

如果您正在使用WCF,您可能需要在serviceCertificate->revocationMode:NoCheck下使用clientCredentials endpointBehavior将其连接起来。

自动安装证书吊销列表的方法,包括通过C代码,可以在此处找到:

自动安装证书吊销列表的方法,包括通过C代码,可以在这里找到:

我们只能使用Win32 API来完成这项工作。没有一流的C系统API可以做到这一点

public class CRLHandler
{
    private const int CERT_STORE_PROV_SYSTEM = 10;
    private const int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2 << 16);

    public const int X509_ASN_ENCODING = 0x00000001;
    public const int PKCS_7_ASN_ENCODING = 0x00010000;

    public const int CERT_STORE_ADD_REPLACE_EXISTING = 3;

    [DllImport("CRYPT32.DLL", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr CertOpenStore(
      int storeProvider,
      int encodingType,
      IntPtr hcryptProv,
      int flags,
      string pvPara);

    [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CertCreateCRLContext(
        int dwCertEncodingType,
        byte[] pbCrlEncoded,
        int cbCrlEncoded);

    [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool CertAddCRLContextToStore(
      IntPtr hCertStore,
      IntPtr pCertContext,
      uint dwAddDisposition,
      IntPtr ppStoreContext);

    [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool CertFreeCRLContext(
        IntPtr pCrlContext);

    public void AddOrUpdateCRLToStore(string crlString)
    {
        IntPtr crlContext = IntPtr.Zero;
        try
        {
            byte[] rawData = Convert.FromBase64String(crlString);

            IntPtr hLocalCertStore = CertOpenStore(
                  CERT_STORE_PROV_SYSTEM,
                  0,
                  IntPtr.Zero,
                  CERT_SYSTEM_STORE_LOCAL_MACHINE,
                  "CA");

            crlContext = CertCreateCRLContext(
                X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                rawData,
                rawData.Length);

            if (crlContext == IntPtr.Zero)
            {
                string error = "AddOrUpdateCRLToStore - CertCreateCRLContext error #" + Marshal.GetLastWin32Error();
                throw new Exception(error);
            }

            bool crlAddResult = CertAddCRLContextToStore(
                hLocalCertStore, crlContext, CERT_STORE_ADD_REPLACE_EXISTING, IntPtr.Zero);

            if (!crlAddResult)

            {
                string error = "AddOrUpdateCRLToStore - CertAddCRLContextToStore #" + Marshal.GetLastWin32Error();
                throw new Exception(error);
            }
        }
        finally
        {
            if(crlContext != IntPtr.Zero)
            {
                CertFreeCRLContext(crlContext);
            }
        }
    }
}
addorUpdaterlToStore方法获取一个不带头和尾的base64编码的crl字符串,然后将crl导入本地计算机的CA存储


要修改诸如本地计算机、证书存储在该API中的值,我们只需使用Win32 API即可。没有一流的C系统API可以做到这一点

public class CRLHandler
{
    private const int CERT_STORE_PROV_SYSTEM = 10;
    private const int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2 << 16);

    public const int X509_ASN_ENCODING = 0x00000001;
    public const int PKCS_7_ASN_ENCODING = 0x00010000;

    public const int CERT_STORE_ADD_REPLACE_EXISTING = 3;

    [DllImport("CRYPT32.DLL", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr CertOpenStore(
      int storeProvider,
      int encodingType,
      IntPtr hcryptProv,
      int flags,
      string pvPara);

    [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CertCreateCRLContext(
        int dwCertEncodingType,
        byte[] pbCrlEncoded,
        int cbCrlEncoded);

    [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool CertAddCRLContextToStore(
      IntPtr hCertStore,
      IntPtr pCertContext,
      uint dwAddDisposition,
      IntPtr ppStoreContext);

    [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool CertFreeCRLContext(
        IntPtr pCrlContext);

    public void AddOrUpdateCRLToStore(string crlString)
    {
        IntPtr crlContext = IntPtr.Zero;
        try
        {
            byte[] rawData = Convert.FromBase64String(crlString);

            IntPtr hLocalCertStore = CertOpenStore(
                  CERT_STORE_PROV_SYSTEM,
                  0,
                  IntPtr.Zero,
                  CERT_SYSTEM_STORE_LOCAL_MACHINE,
                  "CA");

            crlContext = CertCreateCRLContext(
                X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                rawData,
                rawData.Length);

            if (crlContext == IntPtr.Zero)
            {
                string error = "AddOrUpdateCRLToStore - CertCreateCRLContext error #" + Marshal.GetLastWin32Error();
                throw new Exception(error);
            }

            bool crlAddResult = CertAddCRLContextToStore(
                hLocalCertStore, crlContext, CERT_STORE_ADD_REPLACE_EXISTING, IntPtr.Zero);

            if (!crlAddResult)

            {
                string error = "AddOrUpdateCRLToStore - CertAddCRLContextToStore #" + Marshal.GetLastWin32Error();
                throw new Exception(error);
            }
        }
        finally
        {
            if(crlContext != IntPtr.Zero)
            {
                CertFreeCRLContext(crlContext);
            }
        }
    }
}
addorUpdaterlToStore方法获取一个不带头和尾的base64编码的crl字符串,然后将crl导入本地计算机的CA存储

要修改像本地机器一样的值,证书存储在此API中