关于 HTTPS 和 SSL

许多文章、论文和博客已经讨论了 HTTPS、SSL 和 Web 安全。尽管如此,人们仍然错过了基础知识。在这篇文章中,我试图以问卷的形式把所有的东西放在一起。这篇文章将是一篇长篇文章,一些问题听起来很基础,但是当我试图记下来时,请耐心等待,保持简单和扣人心弦。

“这一切都是为了在不安全的互联网世界中保护您的系统。”

在了解 HTTPS 及其术语之前,让我们通过一些统计数据了解 HTTPS 的用法。根据 Google 的 HTTPS 加密透明度,80% 的页面是在 Windows 上的 Chrome 中使用 HTTPS 加载的。网络变得越来越安全,现在整个网络流量的一半以上都是加密的。谷歌开始强制网站适应 HTTPS 并在其搜索排名中提供 SEO 激励。

现在,让我们进入 HTTPS 的技术细节

什么是 SSL 和 TLS 协议?

SSL(安全套接字层)和 TLS(传输层安全性)都是通过网络提供安全性的加密协议。它们广泛用于不同的应用程序。SSL 及其最新版本存在许多漏洞,因此,TLS 在 1999 年作为 SSL 的更新版本引入。SSL 已于 2015 年被 Internet 工程任务组 (IETF) 弃用。因此,您应该拥有 TLS为您的应用程序启用的协议。在人们习惯 TLS 之前,您仍然会看到许多组织使用大量 SSL 术语。

让我们继续讨论这个大问题。

HTTPS 是如何工作的?

通俗地说,HTTPS 是 HTTP 的安全版本。默认情况下,许多网站和应用程序都启用 HTTPS——尤其是在您使用渐进式 Web 应用程序时。作为保护您的应用程序的一部分,HTTPS 已成为一种规范。客户端和服务器之间传输的每个数据包都使用公钥或私钥加密进行加密。

HTTPS 确保在两方之间的通信中至少存在基本级别的安全性,而 HTTP 是不安全的,攻击者 (MiM) 可以破坏安全性。

让我们首先了解一些术语,然后将所有这些点联系起来,以更全面地了解 HTTPS 的工作原理。

请注意,我将 HTTPS 与 Java 编程语言相关联,以在本文中描述很多这些概念。

非对称加密

对称加密

非对称密钥加密更强大,更难破解,但缺点是计算时间也很长。由于在客户端和服务器之间共享对称密钥以进行加密和解密,因此很有可能出现安全隐患。而非对称密钥没有这个问题,因为服务器只维护私钥。数据使用分发的公钥加密,只有拥有私钥的人才能解密数据。

TLS 证书

证书是具有加密密钥的数据文件,其中包含与组织相关的域名、主机名和服务器详细信息等附加信息。如果您作为组织或实体希望使用 SSL 保护您的应用程序,则需要在您的 Web 服务器上安装 SSL/TLS 证书。如今,扩展验证证书是可提供最强安全性的证书,可替代标准 SSL 证书。

以下是 GlobalSign 的快照,他们很好地描述了如果您安装 EV SSL 证书会发生什么,如下图所示,启用 EV SSL 的网站将有一个挂锁和一个绿色的地址栏,就像在 IE 中一样。您还可以通过单击安全网站上的挂锁来查看浏览器中安装的证书。

在谈论公钥证书(通常是 X.509)时,使用了三个关键组件:公钥、私钥和证书。公钥和私钥形成一对。您可以使用私钥签名和解密,并且可以使用公钥验证(签名)和加密。公钥是用来分发的,而私钥是用来保密的。

密钥库和信任库

许多 Java 开发人员在谈到 Keystore 和 Truststore 时会感到困惑。事实上,很少有人同时使用 Keystore 和 Truststore 并将所有证书存储在一个 JKS 中,我们将进一步讨论。您始终可以这样做,但推荐的方法是为您维护一个 Keystore 以表示为主机,并为您信任的站点维护 Truststore。

Keystore 将具有标识组织的私钥。通常,您会将 KeyPair(私钥和公钥)存储在 Keystore 中。让我们看一个例子。

如果您作为服务器希望客户端通过 HTTPS 与您通信,您应该设置 Keystore。每当客户端向服务器发出请求时,服务器将从 Keystore 提供其证书,并且客户端将使用其(客户端)信任库中的证书验证该证书。

那么 Keystore 或 Truststore 持有什么?我使用Keystore Explorer工具演示了基于 Java 的应用程序的 HTTPS 的一些细节。作为另一种选择,您可以尝试使用 JDK 的 Keytool 命令行实用程序来创建/管理证书或存储。

证书颁发机构

证书颁发机构 (CA) 是颁发数字证书的实体。数字证书通过证书的命名主体(证书中的通用名称或 CN )来证明公钥的所有权。这允许其他人(依赖方)依赖签名或关于与认证公钥对应的私钥的断言。CA 充当受信任的第三方——受证书主体(所有者)和依赖证书的一方信任。这些证书的格式由 X.509 标准指定。

从本质上讲,证书颁发机构负责说“是的,这个人就是他们所说的那个人,而我们,CA,证明这一点。”

下面是带有根 CA 的“信任链”的图片

CA 永远无法访问私钥。私钥保留在服务器上,永远不会共享。公钥包含在 SSL 证书中并与客户端共享,客户端可以是浏览器、移动设备或其他服务器。尽管 SSL 证书的构成由私钥和公钥组成,但 SSL 证书本身有时也称为“公钥”。SSL 证书也称为“最终实体”证书,因为它位于证书链的底部,不用于签署/颁发其他证书。

现在我们讨论了所有这些有助于建立安全通道的概念(TLS、证书、加密、CA、密钥库等),这个安全通道使攻击者无法读取客户端和服务器之间的数据,而你知道你是与您打算与之交谈的服务器交谈。

有哪些不同的密钥库类型?

    如果您在 Java 世界中,Java Key Store 的 .jks 首字母缩写词是最常见的默认 Keystore 类型。 .jceks 是 Java 加密扩展密钥库。它具有 JKS 的所有功能,并允许使用更多算法。 .p12 或 PKCS12 是 Java 和其他语言的密钥库类型。与 JKS 不同,您可以从 PKCS#12 中提取私钥。
    PKCS11 或 .p11 用于访问硬件加密令牌(如网卡)的频率较低 .bks 是BouncyCastle跨 Android 和移动设备使用的提供程序。

以及更多类型,如 MacOS、Windows 等中的 Keychain - 它们都存储私钥、密钥和证书。

Java 证书有哪些不同的文件扩展名?

您可能经历过很多扩展,例如“.DER”、“.CER”、“.CRT”、“.PEM”。开发人员对何时使用什么感到困惑。

.PEM 是包含公共证书或整个证书链的容器格式。它包括以下方式的页眉、正文和页脚。

-----BEGIN CERTIFICATE REQUEST----- 和 -----END CERTIFICATE REQUEST----- 显示 PEM 格式的 CSR。

-----BEGIN RSA PRIVATE KEY----- 和 -----END RSA PRIVATE KEY----- 显示 PEM 格式的私钥。

-----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE----- 显示 PEM 格式的证书文件。

.DER 是 Windows 中主要使用的 .PEM 文件的二进制或 base64 格式。Windows 会将证书导出为 .DER 编码文件,扩展名为 .CER 或 .CRT

.CRT 是实际数字证书的文件扩展名。

自签名和 CA 有什么区别?

当我们处理签名证书时,有两种类型的 SSL 证书:

自签名 那 本人签名/签发 由受信任的认证机构签署的证书 免费使用 支付给信任权威 浏览器无法识别 受浏览器信任和认可 在没有敏感信息时使用 用于 PII 和敏感数据的情况 用于预生产环境,可降低 本地基础设施的成本(内联网、测试) 可在任何地方使用,但需额外付费

如果您观察左侧的图像-“颁发者”和“颁发给”与它是由自身签名的自签名证书相同。此外,您会注意到 CA 根证书不受信任。

当您需要多个证书时,在公司中,您可以设置自己的 CA 并将该 CA 的证书安装在所有客户端的根 Keystore 中。然后,这些客户端将接受您的 CA 签名的所有证书。

左边这个是谷歌的认证路径,由 CA-GlobalSign 和信任链中的一个中间 CA-G3 签署。

如果您想构建自己的公钥基础设施 (PKI) 并颁发其他证书,您还需要成为 CA。

1-Way 和 2-Way SSL 的区别?

一般来说,单向 SSL 是验证您正在访问的网站的真实性并形成安全通道的常用方法。在此身份验证中,客户端永远不会被验证,因为正在验证的内容是与服务器一起进行的。 相反,对于 2-way SSL,客户端和服务器都交换证书并验证真实性。CA 对双方证书进行验证后,就获得了相互信任。

如何在您的应用程序中配置 TLS

由于 SSL 已被弃用,我们将着眼于为应用程序配置 TLS。网上有很多网站,您可以在其中检查您的服务器是否启用了 SSL,以及是否应该启用它们。您还可以在浏览器中查看证书(例如单击 Chrome 中的挂锁符号)。

那么,如何为您的应用程序配置安全层呢?安装证书是否会为您的服务器配置 TLS?证书与协议有何不同?

如您所知,传输层也称为第 4 层,它是处理网络堆栈和主机到主机通信的层(您可以在 )。TLS/SSL 不适合 OSI 模型的任何这些层,但位于传输层之上。我只是想简要说明 TLS 在何处以及如何与计算机网络及其安全性相关。

安装证书与配置 TLS 不同。您的服务器将决定使用哪个版本和使用什么协议。

在 Apache 中配置 TLS

    编辑 Ubuntu 系统的配置文件 /etc/apache2/apache.conf 和基于 CentOS 的系统的 /etc/httpd/conf/httpd.conf。如果它是虚拟主机,则目录将是 /etc/apache2/sites-enabled 和 /etc/httpd/sites-enabled。 修改条目 > SSLProtocol all -SSLv2 -SSLv3 -TLSv1
    重启 Apache > service apache2 restart 或 > service httpd restart

这将启用除 SSLv2、SSLv3、TLSv1 之外的所有协议

为 Tomcat 配置 TLS

    编辑 TOMCAT_HOME/conf/server.xml 下的配置文件
    修改条目 > sslProtocols = "TLSv1.2" 用于 Tomcat 5&6 , > sslEnabledProtocols = "TLSv1.2" 用于 Tomcat 7 及更高版本 重新启动 Tomcat 服务。

为 Spring Boot 配置 TLS

    将以下属性放入 Spring Boot 应用程序的 application.properties 文件中
#enable/diable https
server.ssl.enabled=true

#ssl ciphers
server.ssl.ciphers=TLS_RSA_WITH_AES_128_CBC_SHA256, ADD_OTHER_CIPHERS_IF_REQUIRED

# SSL protocol to use.
server.ssl.protocol=TLS

# Enabled SSL protocols.
server.ssl.enabled-protocols=TLSv1.2
    或者,您可以更新 Embedded Servlet Container Factory 以添加/删除协议,如下所示:
@Bean
public EmbeddedServletContainerFactory servletContainerFactory()
{
  TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
  factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
    @Override
    public void customize(Connector connector)
    {
      connector.setAttribute("sslProtocols", "TLSv1.2");
      connector.setAttribute("sslEnabledProtocols", "TLSv1.2");
    }
  });
  return factory;
}

同样,您也可以为 Android、Apple 和其他设备配置 SSL。

SSL握手期间的异常?

浏览器可以了解是否安装了受信任的证书,如果没有添加到其信任库,然后打开 SSL 握手。这通过浏览器非常简单,但如果我们使用 Java 客户端访问安全站点,情况就有些不同了。使用您尝试访问的站点的证书在您的客户端安装您自己的 Truststore 是一个很好的做法。

由于客户端和服务器之间的多种原因,可能会发生 PKIX 握手异常。

    javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.SSL 证书不受信任或安装了错误的证书或无法加载 Truststore。 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested targ您可以在服务器启动时使用系统属性、JVM 参数或 bean 加载 Java 中的 Truststore,并使用 Trust 材料加载存储。如果其中任何一个无法加载信任库或根本无法找到信任库,则会发生此异常。 javax.net.ssl.SSLHandshakeException: no cipher suites in common 此异常可能是由于 TLS 版本不匹配或任何一方的详细密码协商(使用旧密码)。 主机名不匹配:当服务器密钥库中的 SSL/TLS 证书的通用名称与您尝试从客户端访问的域不匹配时,会发生通用名称不匹配错误。

还有其他例外情况,这会导致不安全的连接。对于本地/开发环境,您可以使用自签名证书并禁用别名匹配以进行测试。例如,您可以通过在创建时使用标志来控制主机名验证,SSLConnectionSocketFactory然后将该标志外部化到属性文件中。

SSLConnectionSocketFactory socketFactory;
if(verifyHostname){
socketFactory = new SSLConnectionSocketFactory(sslContext);
}else{
socketFactory = new SSLConnectionSocketFactory(sslContext, (HostNameVerifier) (hostname, session) -> true)
}

Java 是否维护自己的信任库?

JDK 附带了自己的 Truststore,命名cacerts为$JDK_HOME/jre/lib/security/. cacerts 维护着来自世界各地的大量 Root CA 列表,默认密码为“changeit”。您可以通过添加“.jks”扩展名来更改和打开它, KeyToolExplorer 或者使用 Keytool 命令列出所有证书。您必须谨慎并验证 Java 生产版本的受信任机构,并从 cacerts 中删除任何未使用或不受信任的 CA。

Java 客户端如果没有被您自己的 Truststore 覆盖,将首先查看 JDK 的默认 Truststore 并查看证书是否存在并建立安全连接。

把它包起来!

我们大多数人都认为,如果一个网站使用 HTTPS,它就是安全的。即使 HTTPS 也不安全,除非正确实施,否则无法完全保护您的网站或应用程序。您可以阅读关于 HTTPS 漏洞的新闻文章。尽管如此,每个网站都应该使用 HTTPS 保护,以防止攻击网站的微小可能性。

最后,保持系统更新。请检查 TLS 的最新版本、证书的有效性,并确保没有可以通过您的系统遍历的潜在攻击。

最终,尽管有局限性,但使用 HTTPS 总比不加密网络要好。

对我来说,密码学和安全就像一片海洋,我只是从海洋中挑选出一个小贝壳。我了解 HTTPS 的许多其他方面可以更详细地讨论。不过,感谢您阅读本文!

经验分享 程序员 微信小程序 职场和发展