WebSocket安全连接自签名证书

2024-06-20

目标是一个与用户电脑上安装的 C# 应用程序交换信息的 Web 应用程序。 客户端应用程序是 websocket 服务器,浏览器是 websocket 客户端。

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

使用的C#库是WebSocket-Sharp https://github.com/sta/websocket-sharp。 websocket客户端是普通的javascript。

显然,此连接仅发生在本地,因此客户端连接到本地主机。 由于网站通过 HTTPS 进行保护,因此 websocket 也必须受到保护。为此,C# 应用程序在启动时创建一个证书(实际上仅用于测试目的)。

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

这是创建服务器的部分

_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 创建证书的方式

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;

}

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


您是否尝试过此问题的任何答案question https://stackoverflow.com/questions/5312311/secure-websockets-with-self-signed-certificate?

总而言之,您可以尝试以下几种选择:

  • 启动 Chrome--ignore-certificate-errors指定参数。

  • 在采用相同自签名证书的同一端口上启动 HTTP 服务器,浏览到该服务器并接受该证书,之后您应该能够使用 WebSocket 连接。

  • 在 Firefox 上设置配置选项network.websocket.allowInsecureFromHTTPS to true,然后使用ws://而不是wss://地址。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebSocket安全连接自签名证书 的相关文章

随机推荐

  • 如何抑制/控制 Wagon-FTP Maven 扩展的日志记录?

    我正在通过 FTP 部署 Maven 站点 使用货车 FTP http maven apache org wagon wagon providers wagon ftp 工作正常 但输出充满了 FTP 连接 身份验证详细信息 这有效地向每个
  • 我的应用程序中的后退按钮出现问题[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想在手机关闭时清除共享首选项值 你
  • SQLite-Net 扩展 - GetAllWithChildrenAsync 未提取所有内容

    我正在尝试使用 SQLite Net 扩展来创建关系数据库 我在尝试从数据库中提取 Term 对象时遇到了问题 它成功地撤回了其关联的课程 但未撤回与课程关联的评估和笔记 我不确定问题是否在于如何将对象插入数据库 如何从数据库中提取对象 或
  • ansible unarchive 模块如何查找 tar 二进制文件?

    我正在尝试执行一个 ansible 剧本 该剧本的任务是利用unarchive模块 因为我是在 OSX 上执行此操作 所以我需要使用它gnu tar 而不是bsd tar通常与 OSX 一起提供 因为BSD tar 不受官方支持 https
  • 如何部署“SQL Server Express + EF”应用程序

    这是我第一次部署使用 SQL Server Express 数据库的应用程序 我首先使用实体 框架模型来联系数据库 我使用 Install Shield 创建了一个安装向导来安装应用程序 这些是我在目标计算机中安装应用程序所执行的步骤 安装
  • System.IO.FileNotFoundException:找不到网络路径。在 Windows 7 上使用 DirectoryEntry 对象时出现异常

    我正在尝试使用 DirectoryEntry 对象连接到远程 Windows 7 计算机 这是我的代码 DirectoryEntry obDirEntry new DirectoryEntry WinNT hostName hostName
  • Dagger 2 中“HasFragmentInjector”的实际用法是什么

    我之前已经实现了 dagger2 v2 2 但现在他们也添加了 dagger android 部分 所以我正在用它创建示例项目 我知道旧的方法论 Provide and Modules and 成分等注释 但从 Dagger 2 8 开始
  • post php mysql 的拆分关键字

    我有一个表存储帖子 ID 它的标签如下 Post id Tags 1 keyword1 keyword2 keyword3 我想循环遍历该表中的每一行并执行以下操作 将关键字1 关键字2 关键字3放入新表中 word id word val
  • 双枢轴快速排序和快速排序有什么区别?

    我以前从未见过双枢轴快速排序 是快速排序的升级版吗 双枢轴快速排序和快速排序有什么区别 我在 Java 文档中找到了这个 排序算法是双枢轴快速排序 作者 弗拉基米尔 雅罗斯拉夫斯基 乔恩 本特利和约书亚 布洛赫 这个算法 在许多数据集上提供
  • 如何为 UIImageView 随机化器实现滑动手势

    我一直在浏览大量的教程和问题 但似乎找不到我要找的东西 我有一种感觉 我只是错过了一个简单的步骤 我仍在学习诀窍 所以请承受和我一起做这个 我正在 xcode 4 3 3 上制作图像随机化器 并且我已经能够使用按钮来随机化图像 但我希望它能
  • 将图像存储在核心数据中

    我想在更新记录时存储每位员工的图像 我怎样才能做到这一点 我有一个字典 存储员工的姓名 ID 和部门 现在我想将图像保存在一起 Core Data 支持 二进制数据 类型 当您定义具有二进制数据字段的模型时 它会创建具有 NSData 字段
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • Javascript/Jquery:确定用户是否使用鼠标滚轮、滚动条或键盘滚动

    我正在尝试让用户界面正常工作 如果他们使用鼠标滚轮 我需要让它以一种方式滚动 如果他们使用滚动条 我需要让它以另一种方式滚动 如果他们使用键盘 我需要让它以另一种方式滚动 我相信滚轮和滚动条都充当鼠标事件 但是当单击滚动条时我无法让 jav
  • 通过浏览器关闭页面时出现 Websocket 错误:“已建立的连接被主机中的软件中止”

    我开发了一个实时通知系统Spring 4 代码可以在 Github 上找到 github com vdenotaris Spring Messaging https github com vdenotaris Spring Messagin
  • Angular 6 + RxJS 6.0:如何将新元素推送到 Observable 包含的数组

    我从 firebase 服务器分块接收数据 同时渲染该数据需要一个坚持可观察包含数组的库 我不知何故无法将新的数据块推送到可观察到的现有数据块数组 从数据服务中 我通过主题的下一个调用并尝试添加新的 calEvent this homeWo
  • 无法接收 UDP Windows RT

    我正在为 Windows 8 RT 编写一个 Windows Store Metro Modern RT 应用程序 需要在端口 49030 上接收 UDP 数据包 但我似乎无法接收任何数据包 我已按照使用教程进行操作DatagramSock
  • 非闪亮上下文中的反应式对象绑定

    实际问题 你怎样才能近似反应性环境 行为 http shiny rstudio com tutorial lesson6 建立者shiny http shiny rstudio com函数 或者甚至可能在一个函数中使用这些函数无光泽上下文以
  • 如何防止在Spring Boot单元测试中执行import.sql

    我的类路径中有一个 import sql 文件 其中包含一些 INSERT 语句 当使用 profile devel 运行我的应用程序时 它的数据被加载到 postgres 数据库中 到目前为止一切正常 当使用测试配置文件执行测试时 imp
  • 如何将Python3设置为Mac上的默认Python版本?

    有没有办法将 Python 3 8 3 设置为 macOS Catalina 版本 10 15 2 上的默认 Python 版本 我已经完成的步骤 看看它安装在哪里 ls l usr local bin python 我得到的输出是这样的
  • WebSocket安全连接自签名证书

    目标是一个与用户电脑上安装的 C 应用程序交换信息的 Web 应用程序 客户端应用程序是 websocket 服务器 浏览器是 websocket 客户端 最后 用户浏览器中的 websocket 客户端通过 Angular 持久创建 并且