首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WebSocket安全连接自签名证书

WebSocket安全连接自签名证书
EN

Stack Overflow用户
提问于 2017-07-14 03:24:13
回答 3查看 9.6K关注 0票数 7

我们的目标是开发一个与安装在用户pc上的C#应用程序交换信息的web应用程序。客户端应用程序是websocket服务器,浏览器是websocket客户端。

最后,通过Angular持久地创建用户浏览器中的websocket客户端,应用程序在pc上运行并执行某些操作。

使用的C#库是WebSocket-Sharp。websocket客户端是普通的javascript。

显然,这种连接只发生在本地,所以客户端连接到localhost。由于网站是通过HTTPS安全的,所以websocket也必须得到保护。为此,C#应用程序在启动时创建一个证书(实际上只是为了测试目的)。

连接不起作用,因为证书不受信任。对客户端的所有服务器检查都已禁用,但无法建立连接。

这是创建服务器的部分

代码语言:javascript
复制
_server = new WebSocketServer($"wss://localhost:4649")
{
    SslConfiguration =
    {
        ServerCertificate = Utils.Certificate.CreateSelfSignedCert(),
        ClientCertificateRequired = false,
        CheckCertificateRevocation = false,
        ClientCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
    }
};
_server.AddWebSocketService<CommandsBehaviour>("/commands");
_server.AddWebSocketService<NotificationsBehaviour>("/notifications");

_server.Start();

这就是使用BouncyCastle创建证书的方式

代码语言:javascript
复制
private static AsymmetricKeyParameter CreatePrivateKey(string subjectName = "CN=root")
{
    const int keyStrength = 2048;

    // Generating Random Numbers
    var randomGenerator = new CryptoApiRandomGenerator();
    var random = new SecureRandom(randomGenerator);

    // The Certificate Generator
    var certificateGenerator = new X509V3CertificateGenerator();

    // Serial Number
    var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random);
    certificateGenerator.SetSerialNumber(serialNumber);

    // Issuer and Subject Name
    var subjectDn = new X509Name(subjectName);
    var issuerDn = subjectDn;
    certificateGenerator.SetIssuerDN(issuerDn);
    certificateGenerator.SetSubjectDN(subjectDn);

    // Valid For
    var notBefore = DateTime.UtcNow.Date;
    var notAfter = notBefore.AddYears(70);

    certificateGenerator.SetNotBefore(notBefore);
    certificateGenerator.SetNotAfter(notAfter);

    // Subject Public Key
    var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
    var keyPairGenerator = new RsaKeyPairGenerator();
    keyPairGenerator.Init(keyGenerationParameters);
    var subjectKeyPair = keyPairGenerator.GenerateKeyPair();

    return subjectKeyPair.Private;
}

public static X509Certificate2 CreateSelfSignedCert(string subjectName = "CN=localhost", string issuerName = "CN=root")
{
    const int keyStrength = 2048;
    var issuerPrivKey = CreatePrivateKey();

    // Generating Random Numbers
    var randomGenerator = new CryptoApiRandomGenerator();
    var random = new SecureRandom(randomGenerator);
    ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerPrivKey, random);
    // The Certificate Generator
    var certificateGenerator = new X509V3CertificateGenerator();
    certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(new GeneralName[] { new GeneralName(GeneralName.DnsName, "localhost"), new GeneralName(GeneralName.DnsName, "127.0.0.1") }));
    certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage((new ArrayList() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1") })));

    // Serial Number
    var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
    certificateGenerator.SetSerialNumber(serialNumber);

    // Signature Algorithm
    //const string signatureAlgorithm = "SHA512WITHRSA";
    //certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);

    // Issuer and Subject Name
    var subjectDn = new X509Name(subjectName);
    var issuerDn = new X509Name(issuerName);
    certificateGenerator.SetIssuerDN(issuerDn);
    certificateGenerator.SetSubjectDN(subjectDn);

    // Valid For
    var notBefore = DateTime.UtcNow.Date;
    var notAfter = notBefore.AddYears(70);

    certificateGenerator.SetNotBefore(notBefore);
    certificateGenerator.SetNotAfter(notAfter);

    // Subject Public Key
    var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
    var keyPairGenerator = new RsaKeyPairGenerator();
    keyPairGenerator.Init(keyGenerationParameters);
    var subjectKeyPair = keyPairGenerator.GenerateKeyPair();

    certificateGenerator.SetPublicKey(subjectKeyPair.Public);

    // self sign certificate
    var certificate = certificateGenerator.Generate(signatureFactory);

    // corresponding private key
    var info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);


    // merge into X509Certificate2
    var x509 = new X509Certificate2(certificate.GetEncoded());

    var seq = (Asn1Sequence)Asn1Object.FromByteArray(info.ParsePrivateKey().GetDerEncoded());
    if (seq.Count != 9)
    {
        throw new PemException("malformed sequence in RSA private key");
    }

    var rsa = RsaPrivateKeyStructure.GetInstance(seq); //new RsaPrivateKeyStructure(seq);
    var rsaparams = new RsaPrivateCrtKeyParameters(
        rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);

    x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
    return x509;

}

这种行为是合乎逻辑的,尽管它很奇怪,因为证书检查不应该在本地执行。有没有可能绕过这个问题?我已经考虑过将颁发者证书安装到受信任的证书,但这不是最佳解决方案。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-08-06 15:31:39

我的最后一个解决方案是为子域创建一个有效的证书,然后将A/AAAA记录更改为localhost。这样,就可以通过HTTPS信任连接。

票数 0
EN

Stack Overflow用户

发布于 2017-07-20 08:58:18

你有没有试过这个question的答案

总而言之,看起来你可以尝试以下几种选择:

在接受相同自签名证书的同一端口上,使用参数

  • 启动Chrome,浏览到该服务器并接受该证书,然后您就可以在Firefox network.websocket.allowInsecureFromHTTPS to true上使用--ignore-certificate-errors WebSocket specified.
  • Start配置选项,然后使用ws://而不是wss://地址。

如果所有这一切都是为了测试,并且你有可能控制这类事情,那么我认为其中一个或多个应该可以工作。如果您需要您的标准最终用户能够做到这一点,我认为您将需要一个不同的解决方案。正如您已经发现的,如果您将服务器设置为不关心证书,这并不重要,客户端最终必须决定是接受证书还是不接受连接。

票数 6
EN

Stack Overflow用户

发布于 2017-07-22 02:54:38

@Kdawg答案是正确的。

您不可能让客户端浏览器仅通过服务器端调优来接受不安全的连接。接受未签名(或自签名)证书的所有行为都在客户端。

除了@Kdawg的回答之外,我想补充的是,在Windows网络上,私人组织最常见的做法是:

  1. 分配Windows服务器作为证书颁发机构
  2. 将证书颁发机构的公共根证书添加到Windows主机(通过GPO)或使用Windows CA服务器

manually

  • Sign自定义证书

这听起来很痛苦,事实也是如此。

如果我是你,我会去制作一个标准的公开签名的证书,并在完成之前关闭SSL。

请在Let's Encrypt上查看您的域的免费SSL证书。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45089384

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档