Node.js v18.18.2 文档


目录

传输层安全 (SSL)#

稳定性:2 - 稳定

源代码: lib/tls.js

node:tls模块提供构建在 OpenSSL 之上的传输层安全 (TLS) 和安全套接字层 (SSL) 协议的实现。可以使用以下方式访问该模块:

const tls = require('node:tls'); 

确定加密支持是否不可用#

Node.js 的构建可以不包含对 node:crypto模块的支持。在这种情况下,尝试从tls调用import或调用require('node:tls')将导致抛出错误。

使用 CommonJS 时,可以使用 try/catch 捕获抛出的错误:

let tls;
try {
  tls = require('node:tls');
} catch (err) {
  console.error('tls support is disabled!');
} 

当使用词法 ESM import关键字时,只有在尝试加载模块之前注册了 process.on('uncaughtException') 的处理程序(例如,使用预加载),才能捕获错误模块)。

使用 ESM 时,如果代码有可能在未启用加密支持的 Node.js 版本上运行,请考虑使用 import()函数而不是词法import关键字:

let tls;
try {
  tls = await import('node:tls');
} catch (err) {
  console.error('tls support is disabled!');
} 

TLS/SSL 概念#

TLS/SSL 是一组依赖公钥基础设施 (PKI) 来实现客户端和服务器之间安全通信的协议。对于大多数常见情况,每个服务器都必须有一个私钥。

私钥可以通过多种方式生成。下面的示例说明了如何使用 OpenSSL 命令行界面生成 2048 位 RSA 私钥:

openssl genrsa -out ryans-key.pem 2048 

使用 TLS/SSL,所有服务器(和某些客户端)都必须拥有证书。证书是与私钥相对应的公钥,并且由证书颁发机构或私钥所有者进行数字签名(此类证书称为“自签名”)。获取证书的第一步是创建证书签名请求 (CSR) 文件。

OpenSSL 命令行界面可用于生成私钥的 CSR:

openssl req -new -sha256 -key ryans-key.pem -out ryans-csr.pem 

生成 CSR 文件后,可以将其发送到证书颁发机构进行签名或用于生成自签名证书。

下面的示例说明了如何使用 OpenSSL 命令行界面创建自签名证书:

openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem 

证书生成后,可用于生成.pfx.p12文件:

openssl pkcs12 -export -in ryans-cert.pem -inkey ryans-key.pem \
      -certfile ca-cert.pem -out ryans.pfx 

在哪里:

  • in:是签名的证书
  • inkey:是关联的私钥
  • certfile:将所有证书颁发机构 (CA) 证书串联到一个文件中,例如cat ca1-cert.pem ca2-cert.pem > ca-cert.pem

完美的前向保密性#

术语前向保密完美前向保密描述了密钥协商(即密钥交换)方法的特征。也就是说,服务器和客户端密钥用于协商专门用于当前通信会话的新临时密钥。实际上,这意味着即使服务器的私钥被泄露,如果攻击者设法获取专门为会话生成的密钥对,通信也只能被窃听者解密。

完美的前向保密是通过在每次 TLS/SSL 握手时随机生成密钥协议密钥对来实现的(与对所有会话使用相同的密钥相反)。实现此技术的方法称为“短暂的”。

目前,通常使用两种方法来实现完美的前向保密(请注意传统缩写后面附加的字符“E”):

  • ECDHE:椭圆曲线 Diffie-Hellman 密钥协商协议的临时版本。
  • DHE:Diffie-Hellman 密钥协商协议的临时版本。

默认情况下启用使用 ECDHE 的完美前向保密。创建 TLS 服务器时可以使用ecdhCurve选项 来自定义要使用的受支持 ECDH 曲线列表。请参阅tls.createServer()了解更多信息。

默认情况下禁用 DHE,但可以通过将 dhparam选项设置为'auto'与 ECDHE 一起启用。还支持自定义 DHE 参数,但不鼓励使用自动选择的众所周知的参数。

在 TLSv1.2 之前,完美前向保密是可选的。从 TLSv1.3 开始,始终使用 (EC)DHE(仅 PSK 连接除外)。

ALPN 和 SNI#

ALPN(应用层协议协商扩展)和SNI​​(服务器名称指示)是TLS握手扩展:

  • ALPN:允许将一台 TLS 服务器用于多种协议(HTTP、HTTP/2)
  • SNI:允许使用一台 TLS 服务器来处理具有不同证书的多个主机名。

预共享密钥#

TLS-PSK 支持可作为普通基于证书的身份验证的替代方案。它使用预共享密钥而不是证书来验证 TLS 连接,从而提供相互身份验证。TLS-PSK 和公钥基础设施并不相互排斥。客户端和服务器可以同时容纳两者,在正常的密码协商步骤中选择其中一个。

仅当存在与每台连接计算机安全共享密钥的方法时,TLS-PSK 才是一个不错的选择,因此它不会取代大多数 TLS 使用的公钥基础设施 (PKI)。近年来,OpenSSL 中的 TLS-PSK 实现存在许多安全缺陷,主要是因为它仅由少数应用程序使用。在切换到 PSK 密码之前,请考虑所有替代解决方案。在生成 PSK 时,使用足够的熵至关重要,如RFC 4086中所述。从密码或其他低熵来源派生共享秘密并不安全。

PSK 密码默认处于禁用状态,因此使用 TLS-PSK 需要使用ciphers选项显式指定密码套件。可以通过openssl ciphers -v 'PSK'检索可用密码的列表。所有 TLS 1.3 密码都符合 PSK 条件,并且可以通过openssl ciphers -v -s -tls1_3 -psk检索 。

根据RFC 4279,必须支持长度最多为 128 字节的 PSK 身份和长度最多为 64 字节的 PSK。从 OpenSSL 1.1.0 开始,最大身份大小为 128 字节,最大 PSK 长度为 256 字节。

由于底层 OpenSSL API 的限制,当前实现不支持异步 PSK 回调。

客户端发起的重新协商攻击缓解#

TLS 协议允许客户端重新协商 TLS 会话的某些方面。不幸的是,会话重新协商需要不成比例的服务器端资源,使其成为拒绝服务攻击的潜在媒介。

为了降低风险,重新协商限制为每十分钟 3 次。当超过此阈值时,会在 tls.TLSSocket实例上发出 'error' 事件。限制是可配置的:

  • tls.CLIENT_RENEG_LIMIT <number>指定重新协商请求的数量。默认值: 3
  • tls.CLIENT_RENEG_WINDOW <number>指定时间重新协商窗口(以秒为单位)。默认值: 600(10 分钟)。

在未充分了解影响和风险的情况下,不应修改默认的重新谈判限制。

TLSv1.3 不支持重新协商。

会话恢复#

建立 TLS 会话可能相对较慢。通过保存并稍后重用会话状态可以加快该过程。有几种机制可以做到这一点,这里从最旧到最新(和首选)进行讨论。

会话标识符#

服务器为新连接生成唯一的 ID 并将其发送给客户端。客户端和服务器保存会话状态。重新连接时,客户端发送其保存的会话状态的 ID,如果服务器也有该 ID 的状态,则可以同意使用它。否则,服务器将创建一个新会话。有关详细信息,请参阅RFC 2246第 23 和 30 页。

在发出 HTTPS 请求时,大多数 Web 浏览器都支持使用会话标识符进行恢复。

对于 Node.js,客户端等待'session'事件来获取会话数据,并将数据提供给后续tls.connect()session 选项 以重用会议。服务器必须实现'newSession''resumeSession'事件的处理程序,以使用会话 ID 作为重用会话的查找键来保存和恢复会话数据。要跨负载均衡器或集群工作进程重用会话,服务器必须在其会话处理程序中使用共享会话缓存(例如 Redis)。

会话凭据#

服务器加密整个会话状态并将其作为“票据”发送给客户端。重新连接时,状态会发送到初始连接中的服务器。这种机制避免了对服务器端会话缓存的需要。如果服务器出于任何原因(解密失败、太旧等)不使用该票证,它将创建一个新会话并发送一个新票证。有关详细信息,请参阅RFC 5077 。

在发出 HTTPS 请求时,许多 Web 浏览器普遍支持使用会话票证进行恢复。

对于 Node.js,客户端使用与会话票证恢复相同的 API 来恢复会话标识符。对于调试,如果 tls.TLSSocket.getTLSTicket()返回一个值,则会话数据包含票证,否则包含客户端会话状态。

使用 TLSv1.3,请注意,服务器可能会发送多个票证,从而导致多个'session'事件,请参阅'session'了解更多信息。

单进程服务器不需要特定的实现来使用会话票证。要在服务器重新启动或负载均衡器之间使用会话票证,所有服务器必须具有相同的票证密钥。内部有三个 16 字节密钥,但为了方便起见,tls API 将它们公开为单个 48 字节缓冲区。

可以通过在一个服务器实例上调用server.getTicketKeys()来获取票证密钥,然后分发它们,但更合理的做法是安全地生成 48 字节的安全随机数据并使用 ticketKeys设置它们tls.createServer()的选项。应定期重新生成密钥,并且可以使用 server.setTicketKeys()重置服务器的密钥。

会话票证密钥是加密密钥,必须安全地存储它们。对于 TLS 1.2 及更低版本,如果它们受到威胁,则所有使用它们加密的票证的会话都可以被解密。它们不应存储在磁盘上,并且应定期重新生成。

如果客户端宣传对票证的支持,服务器将发送它们。服务器可以通过 在secureOptions 中提供 require('node:constants').SSL_OP_NO_TICKET来禁用票证。

会话标识符和会话票证都超时,导致服务器创建新会话。可以使用tls.createServer()sessionTimeout 选项配置超时。

对于所有机制,当恢复失败时,服务器将创建新会话。由于未能恢复会话不会导致 TLS/HTTPS 连接失败,因此很容易注意到不必要的 TLS 性能不佳。OpenSSL CLI 可用于验证服务器是否正在恢复会话。使用 -reconnect选项openssl s_client,例如:

$ openssl s_client -connect localhost:443 -reconnect 

通读调试输出。第一个连接应显示“New”,例如:

New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256 

后续连接应显示“Reused”,例如:

Reused, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256 

修改默认 TLS 密码套件#

Node.js 是使用默认的启用和禁用 TLS 密码套件构建的。可以在构建 Node.js 时配置此默认密码列表,以允许发行版提供自己的默认列表。

以下命令可用于显示默认密码套件:

node -p crypto.constants.defaultCoreCipherList | tr ':' '\n'
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-SHA256
DHE-RSA-AES128-SHA256
ECDHE-RSA-AES256-SHA384
DHE-RSA-AES256-SHA384
ECDHE-RSA-AES256-SHA256
DHE-RSA-AES256-SHA256
HIGH
!aNULL
!eNULL
!EXPORT
!DES
!RC4
!MD5
!PSK
!SRP
!CAMELLIA 

可以使用--tls-cipher-list 命令行开关(直接或通过NODE_OPTIONS环境变量)完全替换此默认值。例如,以下代码使ECDHE-RSA-AES128-GCM-SHA256:!RC4 成为默认 TLS 密码套件:

node --tls-cipher-list='ECDHE-RSA-AES128-GCM-SHA256:!RC4' server.js

export NODE_OPTIONS=--tls-cipher-list='ECDHE-RSA-AES128-GCM-SHA256:!RC4'
node server.js 

要进行验证,请使用以下命令显示设置的密码列表,请注意defaultCoreCipherListdefaultCipherList之间的区别:

node --tls-cipher-list='ECDHE-RSA-AES128-GCM-SHA256:!RC4' -p crypto.constants.defaultCipherList | tr ':' '\n'
ECDHE-RSA-AES128-GCM-SHA256
!RC4 

defaultCoreCipherList列表在编译时设置,而 defaultCipherList在运行时设置。

要在运行时内修改默认密码套件,请修改 tls.DEFAULT_CIPHERS变量,这必须在侦听任何套接字之前执行,它不会影响已打开的套接字。例如:

// Remove Obsolete CBC Ciphers and RSA Key Exchange based Ciphers as they don't provide Forward Secrecy
tls.DEFAULT_CIPHERS +=
  ':!ECDHE-RSA-AES128-SHA:!ECDHE-RSA-AES128-SHA256:!ECDHE-RSA-AES256-SHA:!ECDHE-RSA-AES256-SHA384' +
  ':!ECDHE-ECDSA-AES128-SHA:!ECDHE-ECDSA-AES128-SHA256:!ECDHE-ECDSA-AES256-SHA:!ECDHE-ECDSA-AES256-SHA384' +
  ':!kRSA'; 

还可以使用tls.createSecureContext()中的ciphers选项在每个客户端或服务器上替换默认值 ,该选项也可在tls.createServer()tls.connect(),以及创建新的 tls.TLSSocket时。

密码列表可以包含 TLSv1.3 密码套件名称(以'TLS_'开头的混合)以及 TLSv1.2 及以下密码套件的规范。TLSv1.2 密码支持旧规范格式,有关详细信息,请参阅 OpenSSL密码列表格式文档,但这些规范不适用于 TLSv1.3 密码。TLSv1.3 套件只能通过在密码列表中包含其全名来启用。例如,无法使用旧版 TLSv1.2 'EECDH''!EECDH'规范来启用或禁用它们。

尽管 TLSv1.3 和 TLSv1.2 密码套件的相对顺序不同,但 TLSv1.3 协议明显比 TLSv1.2 更安全,并且如果握手表明支持该协议,并且如果有任何 TLSv1 协议,则始终选择 TLSv1.2。 .3 密码套件已启用。

Node.js 中包含的默认密码套件经过精心挑选,以反映当前的安全最佳实践和风险缓解。更改默认密码套件可能会对应用程序的安全性产生重大影响。仅在绝对必要时才应使用--tls-cipher-list开关和ciphers选项。

默认密码套件更喜欢使用 GCM 密码来实现Chrome 的“现代密码学”设置,并且还更喜欢使用 ECDHE 和 DHE 密码来实现完美的前向保密,同时提供一些向后兼容性。

依赖不安全且已弃用的 RC4 或基于 DES 的密码(如 Internet Explorer 6)的旧客户端无法使用默认配置完成握手过程。如果必须支持这些客户端, TLS 建议可能会提供兼容的密码套件。有关该格式的更多详细信息,请参阅 OpenSSL密码列表格式文档。

TLSv1.3 密码套件只有五种:

  • 'TLS_AES_256_GCM_SHA384'
  • 'TLS_CHACHA20_POLY1305_SHA256'
  • 'TLS_AES_128_GCM_SHA256'
  • 'TLS_AES_128_CCM_SHA256'
  • 'TLS_AES_128_CCM_8_SHA256'

前三个默认启用。TLSv1.3 支持这两个基于CCM的套件,因为它们在受限系统上可能具有更高的性能,但默认情况下不会启用它们,因为它们提供的安全性较低。

X509 证书错误代码#

由于 OpenSSL 报告的证书错误,多个功能可能会失败。在这种情况下,该函数通过其回调提供一个<Error>,该回调具有属性code,该属性可以采用以下值之一:

  • 'UNABLE_TO_GET_ISSUER_CERT':无法获取颁发者证书。
  • 'UNABLE_TO_GET_CRL':无法获取证书 CRL。
  • 'UNABLE_TO_DECRYPT_CERT_SIGNATURE':无法解密证书的签名。
  • 'UNABLE_TO_DECRYPT_CRL_SIGNATURE':无法解密 CRL 的签名。
  • 'UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY':无法解码颁发者公钥。
  • 'CERT_SIGNATURE_FAILURE':证书签名失败。
  • 'CRL_SIGNATURE_FAILURE':CRL 签名失败。
  • 'CERT_NOT_YET_VALID':证书尚未生效。
  • 'CERT_HAS_EXPIRED':证书已过期。
  • 'CRL_NOT_YET_VALID':CRL 尚未生效。
  • 'CRL_HAS_EXPIRED':CRL 已过期。
  • 'ERROR_IN_CERT_NOT_BEFORE_FIELD':证书的 notBefore 字段格式错误。
  • 'ERROR_IN_CERT_NOT_AFTER_FIELD':证书的 notAfter 字段格式错误。
  • 'ERROR_IN_CRL_LAST_UPDATE_FIELD':CRL 的 LastUpdate 字段中存在格式错误。
  • 'ERROR_IN_CRL_NEXT_UPDATE_FIELD':CRL 的 nextUpdate 字段中存在格式错误。
  • 'OUT_OF_MEM':内存不足。
  • 'DEPTH_ZERO_SELF_SIGNED_CERT':自签名证书。
  • 'SELF_SIGNED_CERT_IN_CHAIN':证书链中的自签名证书。
  • 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY':无法获取本地颁发者证书。
  • 'UNABLE_TO_VERIFY_LEAF_SIGNATURE':无法验证第一个证书。
  • 'CERT_CHAIN_TOO_LONG':证书链太长。
  • 'CERT_REVOKED':证书已吊销。
  • 'INVALID_CA':CA 证书无效。
  • 'PATH_LENGTH_EXCEEDED':超出路径长度限制。
  • 'INVALID_PURPOSE':证书用途不受支持。
  • 'CERT_UNTRUSTED':证书不受信任。
  • 'CERT_REJECTED':证书被拒绝。
  • 'HOSTNAME_MISMATCH':主机名不匹配。

类:tls.CryptoStream#

稳定性:0 - 已弃用:使用tls.TLSSocket代替。

tls.CryptoStream类表示加密数据流。此类已被弃用,不应再使用。

cryptoStream.bytesWritten#

cryptoStream.bytesWritten属性返回写入底层套接字的总字节数,包括实现 TLS 协议所需的字节数。

类:tls.SecurePair#

稳定性:0 - 已弃用:使用tls.TLSSocket代替。

tls.createSecurePair()返回。

事件:'secure'#

建立安全连接后,'secure'事件由SecurePair对象发出。

与检查服务器 'secureConnection' 事件一样,应检查pair.cleartext.authorized以确认所使用的证书是否经过正确授权。

类:tls.Server#

接受使用 TLS 或 SSL 的加密连接。

事件:'connection'#

在 TLS 握手开始之前建立新的 TCP 流时会发出此事件。socket通常是net.Socket类型的对象,但与从net.Server 'connection'事件创建的套接字不同,它不会接收事件。通常用户不想访问此事件。

用户还可以显式发出此事件,以将连接注入 TLS 服务器。在这种情况下,任何Duplex流都可以传递。

事件:'keylog'#

  • line <Buffer> ASCII 文本行,采用 NSS SSLKEYLOGFILE格式。
  • tlsSocket <tls.TLSSocket>生成它的tls.TLSSocket实例。

当通过与此服务器的连接生成或接收密钥材料时(通常在握手完成之前,但不一定),会发出 keylog事件。可以存储此密钥材料以供调试,因为它允许解密捕获的 TLS 流量。每个套接字可能会多次发出它。

一个典型的用例是将接收到的行附加到通用文本文件中,稍后由软件(例如 Wireshark)使用该文件来解密流量:

const logFile = fs.createWriteStream('/tmp/ssl-keys.log', { flags: 'a' });
// ...
server.on('keylog', (line, tlsSocket) => {
  if (tlsSocket.remoteAddress !== '...')
    return; // Only log keys for a particular IP
  logFile.write(line);
}); 

事件:'newSession'#

创建新的 TLS 会话时会发出'newSession'事件。这可用于将会话存储在外部存储器中。数据应提供给'resumeSession'回调。

调用侦听器回调时会传递三个参数:

  • sessionId <Buffer> TLS 会话标识符
  • sessionData <Buffer> TLS 会话数据
  • callback <Function>不带参数的回调函数,必须调用该函数才能通过安全连接发送或接收数据。

侦听此事件仅对添加事件侦听器后建立的连接产生影响。

事件:'OCSPRequest'#

当客户端发送证书状态请求时,会发出'OCSPRequest'事件。调用侦听器回调时会传递三个参数:

  • certificate <Buffer>服务器证书
  • issuer <Buffer>颁发者的证书
  • callback <Function>必须调用才能提供 OCSP 请求结果的回调函数。

可以解析服务器当前的证书,获取OCSP URL和证书ID;获得 OCSP 响应后,将调用callback(null, resp) ,其中resp是包含 OCSP 响应的Buffer实例。certificateissuer都是主证书和颁发者证书的Buffer DER 表示形式。这些可用于获取 OCSP 证书 ID 和 OCSP 端点 URL。

或者,可以调用callback(null, null),表明没有 OCSP 响应。

调用callback(err)将导致socket.destroy(err)调用。

OCSP请求的典型流程如下:

  1. 客户端连接到服务器并发送'OCSPRequest'(通过 ClientHello 中的状态信息扩展)。
  2. 服务器接收请求并发出'OCSPRequest'事件,调用监听器(如果已注册)。
  3. 服务器从certificateissuer中提取 OCSP URL ,并向 CA执行OCSP 请求。
  4. 服务器从 CA接收'OCSPResponse'并通过callback参数将其发送回客户端
  5. 客户端验证响应并销毁套接字或执行握手。

如果证书是自签名的或颁发者不在根证书列表中,则issuer可以是null 。(建立 TLS 连接时可以通过ca选项提供颁发者。)

侦听此事件仅对添加事件侦听器后建立的连接产生影响。

可以使用像asn1.js这样的 npm 模块来解析证书。

事件:'resumeSession'#

当客户端请求恢复之前的 TLS 会话时,会发出'resumeSession'事件。调用侦听器回调时会传递两个参数:

事件侦听器应使用给定的sessionId在外部存储中 查找由'newSession'事件处理程序 保存的sessionData。如果找到,请调用callback(null, sessionData)恢复会话。如果未找到,则无法恢复会话。必须在没有 sessionData 的情况下调用callback(),以便握手可以继续并可以创建新会话。可以调用callback(err)来终止传入连接并销毁套接字。

侦听此事件仅对添加事件侦听器后建立的连接产生影响。

下图说明了恢复 TLS 会话:

const tlsSessionStore = {};
server.on('newSession', (id, data, cb) => {
  tlsSessionStore[id.toString('hex')] = data;
  cb();
});
server.on('resumeSession', (id, cb) => {
  cb(null, tlsSessionStore[id.toString('hex')] || null);
}); 

事件:'secureConnection'#

新连接的握手过程成功完成后,会发出'secureConnection'事件。调用时,侦听器回调将传递一个参数:

tlsSocket.authorized属性是一个boolean,指示客户端是否已由服务器提供的证书颁发机构之一进行验证。如果tlsSocket.authorizedfalse,则 设置socket.authorizationError来描述授权失败的原因。根据 TLS 服务器的设置,未经授权的连接可能仍会被接受。

tlsSocket.alpnProtocol属性是一个包含所选 ALPN 协议的字符串。当 ALPN 没有选择的协议时,tlsSocket.alpnProtocol 等于false

tlsSocket.servername属性是一个字符串,其中包含通过 SNI 请求的服务器名称。

事件:'tlsClientError'#

当建立安全连接之前发生错误时,会发出'tlsClientError'事件。调用侦听器回调时会传递两个参数:

server.addContext(hostname, context)#

server.addContext()方法添加一个安全上下文,如果客户端请求的 SNI 名称与提供的hostname(或通配符)匹配,则将使用该上下文。

当存在多个匹配上下文时,将使用最近添加的一个。

server.address()#

返回操作系统报告的服务器的绑定地址、地址族名称和端口。请参阅net.Server.address()了解更多信息。

server.close([callback])#

  • callback <Function>将注册以侦听服务器实例的'close'事件的侦听器回调。
  • 返回:<tls.Server>

server.close()方法阻止服务器接受新连接。

该函数异步运行。当服务器不再有打开的连接时,将发出'close'事件。

server.getTicketKeys()#

  • 返回:<Buffer>包含会话票证密钥的 48 字节缓冲区。

返回会话票证密钥。

有关详细信息,请参阅会话恢复。

server.listen()#

启动服务器侦听加密连接。此方法与net.Server中的 server.listen()相同。

server.setSecureContext(options)#

server.setSecureContext()方法替换现有服务器的安全上下文。与服务器的现有连接不会中断。

server.setTicketKeys(keys)#

设置会话票证密钥。

对票证密钥的更改仅对将来的服务器连接有效。现有或当前挂起的服务器连接将使用以前的密钥。

有关详细信息,请参阅会话恢复。

类:tls.TLSSocket#

对写入数据和所有必需的 TLS 协商执行透明加密。

tls.TLSSocket的实例实现双工Stream接口。

返回 TLS 连接元数据的方法(例如 tls.TLSSocket.getPeerCertificate())将仅在连接打开时返回数据。

new tls.TLSSocket(socket[, options])#

  • socket <net.Socket> | <stream.Duplex> 在服务器端,任何Duplex流。在客户端,任何net.Socket实例(对于客户端的通用Duplex流支持,必须使用tls.connect() )。
  • options <对象>
    • enableTrace:参见tls.createServer()
    • isServer:SSL/TLS 协议是不对称的,TLSSockets 必须知道它们是充当服务器还是客户端。如果true TLS 套接字将被实例化为服务器。默认值: false
    • server <net.Server>一个net.Server实例。
    • requestCert:是否通过请求证书来验证远程对等点。客户端始终请求服务器证书。服务器(isServer为 true)可以将requestCert设置为 true 以请求客户端证书。
    • rejectUnauthorized:参见tls.createServer()
    • ALPNProtocols:参见tls.createServer()
    • SNICallback:参见tls.createServer()
    • session <Buffer>包含 TLS 会话的Buffer实例。
    • requestOCSP <boolean>如果为true,则指定 OCSP 状态请求扩展将添加到客户端 hello 中,并且之前将在套接字上发出'OCSPResponse'事件建立安全的通信
    • secureContext:使用 tls.createSecureContext()创建的 TLS 上下文对象。如果未提供secureContext,则会通过将整个options对象传递给 tls.createSecureContext()来创建一个。
    • ...:如果缺少secureContext选项,则使用 tls.createSecureContext()选项。否则,它们将被忽略。

从现有 TCP 套接字构造一个新的tls.TLSSocket对象。

事件:'keylog'#

  • line <Buffer> ASCII 文本行,采用 NSS SSLKEYLOGFILE格式。

当套接字生成或接收密钥材料时,会在 tls.TLSSocket上发出 keylog 事件。可以存储此密钥材料以供调试,因为它允许解密捕获的 TLS 流量。它可以在握手完成之前或之后多次发出。

一个典型的用例是将接收到的行附加到通用文本文件中,稍后由软件(例如 Wireshark)使用该文件来解密流量:

const logFile = fs.createWriteStream('/tmp/ssl-keys.log', { flags: 'a' });
// ...
tlsSocket.on('keylog', (line) => logFile.write(line)); 

事件:'OCSPResponse'#

如果在创建 tls.TLSSocket 并收到 OCSP 响应时设置了 requestOCSP 选项,则会发出 'OCSPResponse'事件。调用时,侦听器回调将传递一个参数:

  • response <Buffer>服务器的 OCSP 响应

通常,response是来自服务器 CA 的数字签名对象,其中包含有关服务器证书吊销状态的信息。

事件:'secureConnect'#

新连接的握手过程成功完成后,会发出'secureConnect'事件。无论服务器的证书是否已授权,都会调用监听回调。客户端有责任检查tlsSocket.authorized属性以确定服务器证书是否由指定 CA 之一签名。如果是 tlsSocket.authorized === false ,则可以通过检查tlsSocket.authorizationError属性来发现错误 。如果使用 ALPN,则 可以检查tlsSocket.alpnProtocol属性以确定协商的协议。

使用new tls.TLSSocket()构造函数创建<tls.TLSSocket>时,不会发出 'secureConnect'事件。

事件:'session'#

当新会话或 TLS 票证可用时,会在客户端tls.TLSSocket上发出'session'事件。这可能会或可能不会在握手完成之前进行,具体取决于协商的 TLS 协议版本。该事件不会在服务器上发出,或者如果未创建新会话(例如,当连接恢复时)。对于某些 TLS 协议版本,该事件可能会多次发出,在这种情况下,所有会话都可以用于恢复。

在客户端,可以将session提供给tls.connect()session选项来恢复连接。

有关详细信息,请参阅会话恢复。

对于 TLSv1.2 及更低版本,握手完成后可以调用tls.TLSSocket.getSession()对于 TLSv1.3,协议仅允许基于票证的恢复,发送多个票证,并且直到握手完成后才会发送票证。因此需要等待 'session'事件来获取可恢复的会话。应用程序应使用'session'事件而不是getSession()以确保它们适用于所有 TLS 版本。仅期望获取或使用一个会话的应用程序应仅侦听此事件一次:

tlsSocket.once('session', (session) => {
  // The session can be used immediately or later.
  tls.connect({
    session: session,
    // Other connect options...
  });
}); 

tlsSocket.address()#

返回操作系统报告的底层套接字的 绑定address、地址family名称和port{ port: 12346, family: 'IPv4', address: '127.0.0.1' }

tlsSocket.authorizationError#

返回对等方证书未验证的原因。仅当tlsSocket.authorized === false时才设置此属性。

tlsSocket.authorized#

如果对等证书是由创建 tls.TLSSocket实例时指定的 CA 之一签署的,则此属性为 true ,否则为false

tlsSocket.disableRenegotiation()#

禁用此TLSSocket实例的 TLS 重新协商。一旦调用,尝试重新协商将触发TLSSocket上的 'error'事件。

tlsSocket.enableTrace()#

启用后,TLS 数据包跟踪信息将写入stderr。这可用于调试 TLS 连接问题。

输出的格式与 openssl s_client -traceopenssl s_server -trace的输出相同。虽然它是由 OpenSSL 的SSL_trace()函数生成的,但该格式未记录在案,可能会更改,恕不另行通知,因此不应依赖该格式。

tlsSocket.encrypted#

始终返回true。这可用于区分 TLS 套接字与常规 net.Socket实例。

tlsSocket.exportKeyingMaterial(length, label[, context])#

密钥材料用于验证以防止网络协议中的不同类型的攻击,例如 IEEE 802.1X 规范中的攻击。

例子

const keyingMaterial = tlsSocket.exportKeyingMaterial(
  128,
  'client finished');

/*
 Example return value of keyingMaterial:
 <Buffer 76 26 af 99 c5 56 8e 42 09 91 ef 9f 93 cb ad 6c 7b 65 f8 53 f1 d8 d9
    12 5a 33 b8 b5 25 df 7b 37 9f e0 e2 4f b8 67 83 a3 2f cd 5d 41 42 4c 91
    74 ef 2c ... 78 more bytes>
*/ 

有关更多信息,请参阅 OpenSSL SSL_export_keying_material文档。

tlsSocket.getCertificate()#

返回表示本地证书的对象。返回的对象具有与证书的字段相对应的一些属性。

有关证书结构的示例,请参阅tls.TLSSocket.getPeerCertificate()

如果没有本地证书,将返回一个空对象。如果套接字已被销毁,则将返回null

tlsSocket.getCipher()#

返回一个包含协商密码套件信息的对象。

例如,具有 AES256-SHA 密码的 TLSv1.2 协议:

{
    "name": "AES256-SHA",
    "standardName": "TLS_RSA_WITH_AES_256_CBC_SHA",
    "version": "SSLv3"
} 

有关详细信息,请参阅 SSL_CIPHER_get_name 。

tlsSocket.getEphemeralKeyInfo()#

返回一个对象,表示客户端连接上完全前向保密的临时密钥交换的参数的类型、名称和大小。当密钥交换不是临时的时,它返回一个空对象。因为这仅在客户端套接字上受支持;如果在服务器套接字上调用,则返回null 。支持的类型为'DH''ECDH'。仅当 type 为 'ECDH' 时, name属性才可 用。

例如:{ type: 'ECDH', name: 'prime256v1', size: 256 }

tlsSocket.getFinished()#

  • 返回:<缓冲区> | <undefined>作为 SSL/TLS 握手的一部分发送到套接字的最新Finished消息,如果没有发送Finished消息,则为undefined然而。

由于Finished消息是完整握手的消息摘要(TLS 1.0 总共 192 位,SSL 3.0 总共 192 位),因此当 SSL/TLS 提供身份验证时,它们可以用于外部身份验证过程是不想要的或还不够。

对应于OpenSSL 中的SSL_get_finished例程,可用于实现RFC 5929中的tls-unique通道绑定。

tlsSocket.getPeerCertificate([detailed])#

  • detailed <boolean>如果true则包含完整的证书链,否则仅包含对等方的证书。
  • 返回:<Object>证书对象。

返回表示对等方证书的对象。如果对等方不提供证书,则将返回一个空对象。如果套接字已被销毁,则将返回null

如果请求完整的证书链,则每个证书将包含一个 issuerCertificate属性,其中包含代表其颁发者证书的对象。

证书对象#

证书对象具有与证书字段相对应的属性。

  • 如果是证书颁发机构 (CA),则为ca <boolean> true ,否则为false
  • raw <Buffer> DER 编码的 X.509 证书数据。
  • subject <Object>证书主题,以国家/地区 ( C )、州或省 ( ST )、地点 ( L )来描述、组织 ( O )、OrganizationalUnit ( OU ) 和 CommonName ( CN )。CommonName 通常是带有 TLS 证书的 DNS 名称。示例: {C: 'UK', ST: 'BC', L: 'Metro', O: 'Node Fans', OU: 'Docs', CN: 'example.com'}
  • issuer <Object>证书颁发者,其描述方式与subject相同 。
  • valid_from <string>证书有效的日期时间。
  • valid_to <string>证书有效的日期时间。
  • serialNumber <string>证书序列号,十六进制字符串形式。示例:'B9B0D332A1AA5635'
  • fingerprint <string> DER 编码证书的 SHA-1 摘要。它以:分隔的十六进制字符串形式返回。示例:'2A:7A:C2:DD:...'
  • fingerprint256 <string> DER 编码证书的 SHA-256 摘要。它以:分隔的十六进制字符串形式返回。示例: '2A:7A:C2:DD:...'
  • fingerprint512 <string> DER 编码证书的 SHA-512 摘要。它以:分隔的十六进制字符串形式返回。示例: '2A:7A:C2:DD:...'
  • ext_key_usage <Array>(可选)扩展密钥用法,一组 OID。
  • subjectaltname <string>(可选)包含主题的串联名称的字符串,是subject名称的替代方案。
  • infoAccess <Array>(可选)描述 AuthorityInfoAccess 的数组,与 OCSP 一起使用。
  • issuerCertificate <Object>(可选)颁发者证书对象。对于自签名证书,这可能是循环引用。

证书可能包含有关公钥的信息,具体取决于密钥类型。

对于 RSA 密钥,可以定义以下属性:

  • bits <number> RSA 位大小。示例:1024
  • exponent <string> RSA 索引,采用十六进制数字表示法的字符串。示例:'0x010001'
  • modulus <string> RSA 模数,作为十六进制字符串。示例: 'B56CE45CB7...'
  • pubkey <Buffer>公钥。

对于 EC 密钥,可以定义以下属性:

  • pubkey <Buffer>公钥。
  • bits <number>密钥大小(以位为单位)。示例:256
  • asn1Curve <string>(可选)椭圆曲线 OID 的 ASN.1 名称。众所周知的曲线由 OID 标识。虽然这很不寻常,但曲线有可能是通过其数学属性来识别的,在这种情况下,它不会有 OID。示例:'prime256v1'
  • nistCurve <string>(可选)椭圆曲线的 NIST 名称(如果有的话)(并非所有众所周知的曲线都已由 NIST 指定名称)。示例: 'P-256'

证书示例:

{ subject:
   { OU: [ 'Domain Control Validated', 'PositiveSSL Wildcard' ],
     CN: '*.nodejs.org' },
  issuer:
   { C: 'GB',
     ST: 'Greater Manchester',
     L: 'Salford',
     O: 'COMODO CA Limited',
     CN: 'COMODO RSA Domain Validation Secure Server CA' },
  subjectaltname: 'DNS:*.nodejs.org, DNS:nodejs.org',
  infoAccess:
   { 'CA Issuers - URI':
      [ 'http://crt.comodoca.com/COMODORSADomainValidationSecureServerCA.crt' ],
     'OCSP - URI': [ 'http://ocsp.comodoca.com' ] },
  modulus: 'B56CE45CB740B09A13F64AC543B712FF9EE8E4C284B542A1708A27E82A8D151CA178153E12E6DDA15BF70FFD96CB8A88618641BDFCCA03527E665B70D779C8A349A6F88FD4EF6557180BD4C98192872BCFE3AF56E863C09DDD8BC1EC58DF9D94F914F0369102B2870BECFA1348A0838C9C49BD1C20124B442477572347047506B1FCD658A80D0C44BCC16BC5C5496CFE6E4A8428EF654CD3D8972BF6E5BFAD59C93006830B5EB1056BBB38B53D1464FA6E02BFDF2FF66CD949486F0775EC43034EC2602AEFBF1703AD221DAA2A88353C3B6A688EFE8387811F645CEED7B3FE46E1F8B9F59FAD028F349B9BC14211D5830994D055EEA3D547911E07A0ADDEB8A82B9188E58720D95CD478EEC9AF1F17BE8141BE80906F1A339445A7EB5B285F68039B0F294598A7D1C0005FC22B5271B0752F58CCDEF8C8FD856FB7AE21C80B8A2CE983AE94046E53EDE4CB89F42502D31B5360771C01C80155918637490550E3F555E2EE75CC8C636DDE3633CFEDD62E91BF0F7688273694EEEBA20C2FC9F14A2A435517BC1D7373922463409AB603295CEB0BB53787A334C9CA3CA8B30005C5A62FC0715083462E00719A8FA3ED0A9828C3871360A73F8B04A4FC1E71302844E9BB9940B77E745C9D91F226D71AFCAD4B113AAF68D92B24DDB4A2136B55A1CD1ADF39605B63CB639038ED0F4C987689866743A68769CC55847E4A06D6E2E3F1',
  exponent: '0x10001',
  pubkey: <Buffer ... >,
  valid_from: 'Aug 14 00:00:00 2017 GMT',
  valid_to: 'Nov 20 23:59:59 2019 GMT',
  fingerprint: '01:02:59:D9:C3:D2:0D:08:F7:82:4E:44:A4:B4:53:C5:E2:3A:87:4D',
  fingerprint256: '69:AE:1A:6A:D4:3D:C6:C1:1B:EA:C6:23:DE:BA:2A:14:62:62:93:5C:7A:EA:06:41:9B:0B:BC:87:CE:48:4E:02',
  fingerprint512: '19:2B:3E:C3:B3:5B:32:E8:AE:BB:78:97:27:E4:BA:6C:39:C9:92:79:4F:31:46:39:E2:70:E5:5F:89:42:17:C9:E8:64:CA:FF:BB:72:56:73:6E:28:8A:92:7E:A3:2A:15:8B:C2:E0:45:CA:C3:BC:EA:40:52:EC:CA:A2:68:CB:32',
  ext_key_usage: [ '1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2' ],
  serialNumber: '66593D57F20CBC573E433381B5FEC280',
  raw: <Buffer ... > } 

tlsSocket.getPeerFinished()#

  • 返回:<缓冲区> | <undefined> 作为SSL/TLS 握手的一部分,预期或实际从套接字收到的最新Finished消息,或者undefined如果没有Finished到目前为止的消息。

由于Finished消息是完整握手的消息摘要(TLS 1.0 总共 192 位,SSL 3.0 总共 192 位),因此当 SSL/TLS 提供身份验证时,它们可以用于外部身份验证过程是不想要的或还不够。

对应于OpenSSL 中的SSL_get_peer_finished例程,可用于实现RFC 5929中的tls-unique通道绑定。

tlsSocket.getPeerX509Certificate()#

以<X509Certificate>对象的形式返回对等证书。

如果没有对等证书,或者套接字已被破坏, 则将返回undefined

tlsSocket.getProtocol()#

返回一个字符串,其中包含当前连接协商的 SSL/TLS 协议版本。对于尚未完成握手过程的已连接套接字,将返回值'unknown' 。对于服务器套接字或断开连接的客户端套接字,将返回值null

协议版本有:

  • 'SSLv3'
  • 'TLSv1'
  • 'TLSv1.1'
  • 'TLSv1.2'
  • 'TLSv1.3'

有关更多信息,请参阅 OpenSSL SSL_get_version文档。

tlsSocket.getSession()#

返回 TLS 会话数据,如果未协商任何会话,则返回undefined 。在客户端,可以将数据提供给tls.connect()session选项来恢复连接。在服务器上,它可能对调试有用。

有关详细信息,请参阅会话恢复。

注意:getSession()仅适用于 TLSv1.2 及更低版本。对于 TLSv1.3,应用程序必须使用'session'事件(它也适用于 TLSv1.2 及更低版本)。

tlsSocket.getSharedSigalgs()#

  • 返回:<Array>服务器和客户端之间共享的签名算法列表,按优先级递减的顺序排列。

有关详细信息,请参阅 SSL_get_shared_sigalgs 。

tlsSocket.getTLSTicket()#

对于客户端,返回 TLS 会话票证(如果可用),或 undefined。对于服务器,始终返回undefined

它可能对调试有用。

有关详细信息,请参阅会话恢复。

tlsSocket.getX509Certificate()#

将本地证书作为<X509Certificate>对象返回。

如果没有本地证书,或者套接字已被破坏, 则将返回undefined

tlsSocket.isSessionReused()#

  • 如果会话被重用,则返回<boolean> true ,否则返回 false

有关详细信息,请参阅会话恢复。

tlsSocket.localAddress#

返回本地 IP 地址的字符串表示形式。

tlsSocket.localPort#

返回本地端口的数字表示形式。

tlsSocket.remoteAddress#

返回远程 IP 地址的字符串表示形式。例如, '74.125.127.100''2001:4860:a005::68'

tlsSocket.remoteFamily#

返回远程 IP 系列的字符串表示形式。'IPv4''IPv6'

tlsSocket.remotePort#

返回远程端口的数字表示形式。例如,443

tlsSocket.renegotiate(options, callback)#

  • options <对象>

    • rejectUnauthorized <boolean>如果不是false,则根据提供的 CA 列表验证服务器证书。如果验证失败,则会发出'error'事件;err.code包含 OpenSSL 错误代码。默认值: true
    • requestCert
  • callback <Function>如果renegotiate()返回true,则回调会附加到'secure'事件一次。如果renegotiate()返回false,则 callback将在下一个tick中被调用并出现错误,除非 tlsSocket已被销毁,其中case callback根本不会被调用。

  • 返回:<boolean> true如果重新协商已启动,则false否则。

tlsSocket.renegotiate()方法启动 TLS 重新协商过程。完成后,将向callback函数传递一个参数,该参数可以是Error(如果请求失败)或null

此方法可用于在建立安全连接后请求对等方的证书。

当作为服务器运行时,套接字将在 handshakeTimeout超时后被销毁并出现错误。

对于TLSv1.3,无法发起重新协商,协议不支持。

tlsSocket.setMaxSendFragment(size)#

  • size <number>最大 TLS 片段大小。最大值为16384默认值: 16384
  • 返回:<布尔值>

tlsSocket.setMaxSendFragment()方法设置最大 TLS 片段大小。如果设置限制成功,则返回truefalse否则。

较小的片段大小可以减少客户端的缓冲延迟:较大的片段由 TLS 层缓冲,直到接收到整个片段并验证其完整性;大片段可能跨越多个往返,并且它们的处理可能由于数据包丢失或重新排序而延迟。但是,较小的片段会增加额外的 TLS 帧字节和 CPU 开销,这可能会降低服务器的整体吞吐量。

tls.checkServerIdentity(hostname, cert)#

验证证书cert是否颁发给hostname

返回<Error>对象,失败时用reasonhostcert填充它。成功时,返回<undefined>

此函数旨在与可传递给tls.connect()checkServerIdentity 选项结合使用 ,并因此对证书对象进行操作。出于其他目的,请考虑使用 x509.checkHost()

可以通过提供替代函数作为 传递给tls.connect()options.checkServerIdentity 选项来覆盖此函数。当然,覆盖函数可以调用tls.checkServerIdentity(),以通过额外的验证来增强检查。

仅当证书通过了所有其他检查(例如由受信任的 CA ( options.ca )颁发)时,才会调用此函数。

如果存在匹配的uniformResourceIdentifier主体备用名称,早期版本的 Node.js 会错误地接受给定 hostname 的证书(请参阅CVE-2021-44531)。希望接受 uniformResourceIdentifier主题备用名称的应用程序可以使用自定义 options.checkServerIdentity函数来实现所需的行为。

tls.connect(options[, callback])#

  • options <对象>
    • enableTrace:参见tls.createServer()

    • host <string>客户端应连接到的主机。默认值: 'localhost'

    • port <number>客户端应连接的端口。

    • path <string>创建到路径的 Unix 套接字连接。如果指定此选项,则忽略hostport

    • socket <stream.Duplex>在给定套接字上建立安全连接,而不是创建新套接字。通常,这是net.Socket的实例 ,但允许任何Duplex流。如果指定此选项,则忽略pathhostport,证书验证除外。通常,套接字在传递给tls.connect()时已经连接,但可以稍后连接。socket的连接/断开/破坏是用户的责任;调用tls.connect()不会导致调用net.connect()

    • allowHalfOpen <boolean>如果设置为false,那么当可读端结束时,套接字将自动结束可写端。如果 设置了socket选项,则此选项无效。有关详细信息,请参阅net.SocketallowHalfOpen选项。默认值: false

    • rejectUnauthorized <boolean>如果不是false,则根据提供的 CA 列表验证服务器证书。如果验证失败,则会发出'error'事件;err.code包含 OpenSSL 错误代码。默认值: true

    • pskCallback <函数>

      • 提示:<string>从服务器发送的可选消息,以帮助客户端决定在协商期间使用哪个身份。如果使用 TLS 1.3,则始终为null
      • 返回:<Object>,格式为 { psk: <Buffer|TypedArray|DataView>, identity: <string> }null以停止协商过程。psk必须与所选密码的摘要兼容。 identity必须使用 UTF-8 编码。

      协商 TLS-PSK(预共享密钥)时,将使用服务器提供的可选身份hint或 在 TLS 1.3 中的null来调用此函数,其中hint去掉了。需要为连接提供自定义tls.checkServerIdentity(), 因为默认连接将尝试根据证书检查服务器的主机名/IP,但这不适用于 PSK,因为不会有证书展示。更多信息可以在RFC 4279中找到。

    • ALPNProtocols : <字符串[]> | <缓冲区[]> | <TypedArray[]> | <数据视图[]> | <缓冲区> | <类型化数组> | <Da​​taView> 字符串数组、BufferTypedArrayDataView,或单个BufferTypedArray或包含受支持的 ALPN 协议的DataViewBuffer的格式应为[len][name][len][name]... 例如'\x08http/1.1\x08http/1.0',其中len字节是下一个协议名称的长度。传递数组通常要简单得多,例如 ['http/1.1', 'http/1.0']。列表中前面的协议比后面的协议具有更高的优先级。

    • servername<string> SNI(服务器名称指示)TLS 扩展的服务器名称。它是所连接的主机的名称,并且必须是主机名,而不是 IP 地址。多宿主服务器可以使用它来选择要呈现给客户端的正确证书,请参阅 tls.createServer()SNICallback选项。

    • checkServerIdentity(servername, cert) <Function>检查服务器主机名时使用的回调函数(而不是内置的tls.checkServerIdentity()函数)(或显式设置时提供的servername)针对证书。如果验证失败,这应该返回<Error> 。如果servernamecert已验证,该方法应返回undefined

    • session <Buffer>一个Buffer实例,包含 TLS 会话。

    • minDHSize <number>接受 TLS 连接的 DH 参数的最小大小(以位为单位)。当服务器提供的 DH 参数大小小于minDHSize时,TLS 连接将被破坏并引发错误。 默认值: 1024

    • highWaterMark : <number>与可读流highWaterMark参数一致。 默认值: 16 * 1024

    • secureContext:使用 tls.createSecureContext()创建的 TLS 上下文对象。如果未提供secureContext,则会通过将整个options对象传递给 tls.createSecureContext()来创建一个。

    • onread <Object>如果缺少socket选项,则传入数据将存储在单个buffer中,并在以下情况下传递到提供的callback数据到达套接字,否则该选项将被忽略。有关详细信息,请参阅 net.Socketonread选项。

    • ...:如果 缺少secureContext选项,则使用tls.createSecureContext()选项,否则将被忽略。

    • ...:任何尚未列出的socket.connect()选项。

  • callback <函数>
  • 返回:<tls.TLSSocket>

callback函数(如果指定)将被添加为 'secureConnect'事件的侦听器。

tls.connect()返回一个tls.TLSSocket对象。

https API 不同,tls.connect()默认情况下不启用 SNI(服务器名称指示)扩展,这可能会导致某些服务器返回不正确的证书或完全拒绝连接。要启用 SNI,除了host之外,还需设置servername选项。

以下说明了来自 tls.createServer()的 echo 服务器示例的客户端:

// Assumes an echo server that is listening on port 8000.
const tls = require('node:tls');
const fs = require('node:fs');

const options = {
  // Necessary only if the server requires client certificate authentication.
  key: fs.readFileSync('client-key.pem'),
  cert: fs.readFileSync('client-cert.pem'),

  // Necessary only if the server uses a self-signed certificate.
  ca: [ fs.readFileSync('server-cert.pem') ],

  // Necessary only if the server's cert isn't for "localhost".
  checkServerIdentity: () => { return null; },
};

const socket = tls.connect(8000, options, () => {
  console.log('client connected',
              socket.authorized ? 'authorized' : 'unauthorized');
  process.stdin.pipe(socket);
  process.stdin.resume();
});
socket.setEncoding('utf8');
socket.on('data', (data) => {
  console.log(data);
});
socket.on('end', () => {
  console.log('server ends connection');
}); 

tls.connect(path[, options][, callback])#

tls.connect()相同,只不过path可以作为参数而不是选项提供。

路径选项(如果指定)将优先于路径参数。

tls.connect(port[, host][, options][, callback])#

tls.connect()相同,只不过porthost可以作为参数而不是选项提供。

端口或主机选项(如果指定)将优先于任何端口或主机参数。

tls.createSecureContext([options])#

  • options <对象>
    • ca <字符串> | <字符串[]> | <缓冲区> | <Buffer[]>可选择覆盖受信任的 CA 证书。默认是信任由 Mozilla 策划的知名 CA。当使用此选项显式指定 CA 时,Mozilla 的 CA 将被完全替换。该值可以是字符串或Buffer,或者字符串的Array和/或Buffer。任何字符串或Buffer都可以包含连接在一起的多个 PEM CA。对等方的证书必须可链接到服务器信任的 CA,以便对连接进行身份验证。当使用不可链接到知名 CA 的证书时,必须将证书的 CA 明确指定为受信任的 CA,否则连接将无法进行身份验证。如果对等方使用的证书与默认 CA 之一不匹配或链接到,请使用ca选项提供对等方证书可以匹配或链接到的 CA 证书。对于自签名证书,该证书是其自己的 CA,并且必须提供。对于 PEM 编码的证书,支持的类型为“TRUSTED CERTIFICATE”、“X509 CERTIFICATE”和“CERTIFICATE”。另请参阅tls.rootCertificates
    • cert <字符串> | <字符串[]> | <缓冲区> | <Buffer[]> PEM 格式的证书链。每个私钥应提供一个证书链。每个证书链应包含所提供的私有key的 PEM 格式的证书,后跟 PEM 格式的中间证书(如果有),按顺序排列,并且不包括根 CA(根 CA 必须是预先生成的) - 对等方已知,请参阅ca)。提供多个证书链时,它们的顺序不必与key中的私钥相同。如果未提供中间证书,对等方将无法验证证书,握手将失败。
    • sigalgs <string>支持的签名算法的冒号分隔列表。该列表可以包含摘要算法(SHA256MD5等)、公钥算法(RSA-PSSECDSA等)、组合两者(例如 'RSA+SHA384')或 TLS v1.3 方案名称(例如rsa_pss_pss_sha512)。 有关详细信息,请参阅OpenSSL 手册页。
    • ciphers <string>密码套件规范,替换默认值。有关更多信息,请参阅修改默认 TLS 密码套件允许的密码可以通过tls.getCiphers()获取。密码名称必须大写以便 OpenSSL 接受它们。
    • clientCertEngine <string>可以提供客户端证书的 OpenSSL 引擎的名称。
    • crl <字符串> | <字符串[]> | <缓冲区> | <Buffer[]> PEM 格式的 CRL(证书吊销列表)。
    • dhparam <字符串> | <Buffer> 'auto'或自定义 Diffie-Hellman 参数,非 ECDHE完美前向保密所需。如果省略或无效,参数将被默默丢弃,并且 DHE 密码将不可用。 基于ECDHE的完美前向保密仍然可用。
    • ecdhCurve <string>描述命名曲线的字符串或以冒号分隔的曲线 NID 或名称列表,例如P-521:P-384:P-256,用于 ECDH 密钥协商。设置为auto以自动选择曲线。使用crypto.getCurves()获取可用曲线名称的列表。在最近的版本中,openssl ecparam -list_curves 还将显示每个可用椭圆曲线的名称和描述。 默认值: tls.DEFAULT_ECDH_CURVE
    • honorCipherOrder <boolean>尝试使用服务器的密码套件首选项而不是客户端的。当true导致 在secureOptions中设置SSL_OP_CIPHER_SERVER_PREFERENCE时,请参阅 OpenSSL 选项以了解更多信息。
    • key <字符串> | <字符串[]> | <缓冲区> | <缓冲区[]> | <Object[]> PEM 格式的私钥。PEM 允许选择加密私钥。加密的密钥将使用options.passphrase进行解密。使用不同算法的多个密钥可以以未加密密钥字符串或缓冲区的数组形式提供,也可以以 {pem: <string|buffer>[, passphrase: <string>]}形式的对象数组形式提供。对象形式只能出现在数组中。object.passphrase是可选的。如果提供了加密密钥,则将使用object.passphrase进行解密;如果未提供,则使用options.passphrase 进行解密。
    • privateKeyEngine <string>要从中获取私钥的 OpenSSL 引擎的名称。应与privateKeyIdentifier一起使用。
    • privateKeyIdentifier <string>由 OpenSSL 引擎管理的私钥标识符。应与privateKeyEngine一起使用。不应与key一起设置,因为这两个选项以不同的方式定义私钥。
    • maxVersion <string>(可选)设置允许的最大 TLS 版本。'TLSv1.3''TLSv1.2''TLSv1.1''TLSv1'之一。不能与secureProtocol选项一起指定;使用其中之一。 默认值: tls.DEFAULT_MAX_VERSION
    • minVersion <string>(可选)设置允许的最低 TLS 版本。'TLSv1.3''TLSv1.2''TLSv1.1''TLSv1'之一。不能与secureProtocol选项一起指定;使用其中之一。避免设置为低于 TLSv1.2,但这可能是互操作性所必需的。 默认值: tls.DEFAULT_MIN_VERSION
    • passphrase <string>用于单个私钥和/或 PFX 的共享密码。
    • pfx <字符串> | <字符串[]> | <缓冲区> | <缓冲区[]> | <Object[]> PFX 或 PKCS12 编码的私钥和证书链。pfx是单独提供 keycert的替代方法。PFX 通常是加密的,如果是, 则使用passphrase对其进行解密。多个 PFX 可以以未加密的 PFX 缓冲区数组的形式提供,也可以以 {buf: <string|buffer>[, passphrase: <string>]}形式的对象数组的形式提供。对象形式只能出现在数组中。object.passphrase是可选的。加密的 PFX 将使用object.passphrase (如果提供)进行解密,如果未提供,则使用options.passphrase 进行解密。
    • secureOptions <number>可选择影响 OpenSSL 协议行为,但这通常不是必需的。如果有的话,应该小心使用!值是OpenSSL Options中的 SSL_OP_*选项的数字位掩码。
    • secureProtocol <string>传统机制选择要使用的 TLS 协议版本,不支持独立控制最小和最大版本,也不支持将协议限制为 TLSv1.3。请改用 minVersionmaxVersion。可能的值列为 SSL_METHODS,使用函数名称作为字符串。例如,使用'TLSv1_1_method'强制使用 TLS 版本 1.1,或使用'TLS_method'允许任何 TLSv1.3 之前的 TLS 协议版本。不建议使用低于 1.2 的 TLS 版本,但互操作性可能需要它。 默认值:无,请参阅minVersion
    • sessionIdContext <string>服务器使用的不透明标识符,以确保会话状态不在应用程序之间共享。未被客户使用。
    • ticketKeys<Buffer> 48 字节的加密强伪随机数据。有关详细信息,请参阅会话恢复。
    • sessionTimeout <number>秒数,经过该秒数,服务器创建的 TLS 会话将不再可恢复。有关详细信息,请参阅 会话恢复。默认值: 300

tls.createServer()honorCipherOrder选项的默认值设置为true,创建安全上下文的其他 API 不设置它。

tls.createServer()使用从process.argv生成的 128 位截断 SHA1 哈希值作为sessionIdContext选项的默认值,其他创建安全上下文的 API 没有默认值。

tls.createSecureContext()方法创建一个SecureContext对象。它可用作多个tls API 的参数,例如server.addContext(),但没有公共方法。tls.Server构造函数和 tls.createServer()方法不支持secureContext选项。

使用证书的密码需要密钥。可以使用keypfx来提供它。

如果未给出ca选项,则 Node.js 将默认使用 Mozilla 的公开信任的 CA 列表

不鼓励使用自定义 DHE 参数,而应使用新的dhparam: 'auto' 选项。当设置为'auto'时,将自动选择足够强度的众所周知的 DHE 参数。否则,如有必要,可以使用openssl dhparam创建自定义参数。密钥长度必须大于或等于1024位,否则将抛出错误。尽管允许使用 1024 位,但为了增强安全性,请使用 2048 位或更大的位。

tls.createSecurePair([context][, isServer][, requestCert][, rejectUnauthorized][, options])#

稳定性:0 - 已弃用:使用tls.TLSSocket代替。

  • context <Object>由tls.createSecureContext()返回的安全上下文对象
  • isServer <boolean> true指定此 TLS 连接应作为服务器打开。
  • requestCert <boolean> true指定服务器是否应向连接客户端请求证书。仅当isServertrue时适用。
  • rejectUnauthorized <boolean>如果不是false,服务器会自动拒绝具有无效证书的客户端。仅当isServertrue时适用。
  • options

创建一个具有两个流的新安全对对象,其中一个读取和写入加密数据,另一个读取和写入明文数据。通常,加密流通过管道传送到传入的加密数据流或从传入的加密数据流传送出来,并且明文数据流用作初始加密流的替代。

tls.createSecurePair()返回一个具有cleartextencrypted流属性的 tls.SecurePair 对象。

使用cleartexttls.TLSSocket具有相同的 API 。

tls.createSecurePair()方法现已弃用,取而代之的是 tls.TLSSocket()。例如,代码:

pair = tls.createSecurePair(/* ... */);
pair.encrypted.pipe(socket);
socket.pipe(pair.encrypted); 

可以替换为:

secureSocket = tls.TLSSocket(socket, options); 

其中secureSocketpair.cleartext具有相同的 API 。

tls.createServer([options][, secureConnectionListener])#

  • options <对象>
    • ALPNProtocols : <字符串[]> | <缓冲区[]> | <TypedArray[]> | <数据视图[]> | <缓冲区> | <类型化数组> | <Da​​taView> 字符串数组、BufferTypedArrayDataView,或单个 BufferTypedArray或包含受支持的 ALPN 协议的DataViewBuffer的格式应为[len][name][len][name]... 例如0x05hello0x05world,其中第一个字节是下一个协议名称的长度。传递数组通常要简单得多,例如 ['hello', 'world']。(协议应按其优先级排序。)

    • clientCertEngine <string>可以提供客户端证书的 OpenSSL 引擎的名称。

    • enableTrace <boolean>如果true,则将在新连接上调用tls.TLSSocket.enableTrace()建立安全连接后可以启用跟踪,但必须使用此选项来跟踪安全连接设置。默认值: false

    • handshakeTimeout <number>如果 SSL/TLS 握手未在指定的毫秒数内完成,则中止连接。每当握手超时时,就会在tls.Server对象上发出 'tlsClientError'默认值:120000(120 秒)。

    • rejectUnauthorized <boolean>如果不是false,服务器将拒绝任何未经所提供 CA 列表授权的连接。此选项仅在requestCerttrue时有效。默认值: true

    • requestCert <boolean>如果true,服务器将从连接的客户端请求证书并尝试验证该证书。默认值: false

    • sessionTimeout <number>秒数,经过该秒数,服务器创建的 TLS 会话将不再可恢复。有关详细信息,请参阅 会话恢复。默认值: 300

    • SNICallback(servername, callback) <Function>如果客户端支持 SNI TLS 扩展,将调用的函数。调用时将传递两个参数:servernamecallbackcallback是一个错误优先回调,它采用两个可选参数:errorctxctx(如果提供)是一个SecureContext实例。 tls.createSecureContext()可用于获取正确的SecureContext。如果使用虚假的 ctx 参数调用callback,则将使用服务器的默认安全上下文。如果未提供SNICallback,则将使用高级 API 的默认回调(见下文)。

    • ticketKeys<Buffer> 48 字节的加密强伪随机数据。有关详细信息,请参阅会话恢复。

    • pskCallback <函数>

      当协商 TLS-PSK(预共享密钥)时,将使用客户端提供的身份调用此函数。如果返回值为null,则协商过程将停止,并向对方发送“unknown_psk_identity”警报消息。如果服务器希望隐藏 PSK 身份未知的事实,则回调必须提供一些随机数据,如psk,以使连接在协商完成之前失败并显示“decrypt_error”。PSK 密码默认处于禁用状态,因此使用 TLS-PSK 需要使用ciphers选项显式指定密码套件。更多信息可以在RFC 4279中找到。

    • pskIdentityHint <string>发送给客户端的可选提示,以帮助在 TLS-PSK 协商期间选择身份。在 TLS 1.3 中将被忽略。如果设置 pskIdentityHint 失败,将发出'tlsClientError'代码和'ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED'代码。

    • ...:可以提供任何tls.createSecureContext()选项。对于服务器,通常需要身份选项(pfxkey / certpskCallback )。

    • ...:可以提供任何net.createServer()选项。

  • secureConnectionListener <函数>
  • 返回:<tls.Server>

创建一个新的tls.ServersecureConnectionListener(如果提供)会自动设置为'secureConnection'事件的侦听器。

ticketKeys选项会在node:cluster模块工作线程之间自动共享。

下图展示了一个简单的 echo 服务器:

const tls = require('node:tls');
const fs = require('node:fs');

const options = {
  key: fs.readFileSync('server-key.pem'),
  cert: fs.readFileSync('server-cert.pem'),

  // This is necessary only if using client certificate authentication.
  requestCert: true,

  // This is necessary only if the client uses a self-signed certificate.
  ca: [ fs.readFileSync('client-cert.pem') ],
};

const server = tls.createServer(options, (socket) => {
  console.log('server connected',
              socket.authorized ? 'authorized' : 'unauthorized');
  socket.write('welcome!\n');
  socket.setEncoding('utf8');
  socket.pipe(socket);
});
server.listen(8000, () => {
  console.log('server bound');
}); 

可以使用tls.connect()中的示例客户端连接到服务器来测试服务器 。

tls.getCiphers()#

返回一个数组,其中包含受支持的 TLS 密码的名称。由于历史原因,名称为小写,但必须为大写才能在tls.createSecureContext()ciphers选项中使用。

默认情况下,并非所有受支持的密码均启用。请参阅 修改默认 TLS 密码套件

'tls_'开头的密码名称适用于 TLSv1.3,所有其他密码名称均适用于 TLSv1.2 及更低版本。

console.log(tls.getCiphers()); // ['aes128-gcm-sha256', 'aes128-sha', ...] 

tls.rootCertificates#

一个不可变的字符串数组,表示当前 Node.js 版本提供的捆绑 Mozilla CA 存储中的根证书(PEM 格式)。

由 Node.js 提供的捆绑 CA 存储是在发布时修复的 Mozilla CA 存储的快照。它在所有支持的平台上都是相同的。

tls.DEFAULT_ECDH_CURVE#

用于 tls 服务器中 ECDH 密钥协商的默认曲线名称。默认值为'auto'。请参阅tls.createSecureContext()了解更多信息。

tls.DEFAULT_MAX_VERSION#

  • <string> tls.createSecureContext()maxVersion选项 的默认值。可以为其分配任何受支持的 TLS 协议版本:'TLSv1.3''TLSv1.2''TLSv1.1''TLSv1'默认值: 'TLSv1.3',除非使用 CLI 选项进行更改。使用 --tls-max-v1.2将默认值设置为'TLSv1.2'。使用--tls-max-v1.3将默认值设置为'TLSv1.3'。如果提供了多个选项,则使用最高的最大值。

tls.DEFAULT_MIN_VERSION#

  • <string> tls.createSecureContext()minVersion 选项 的默认值。可以为其分配任何受支持的 TLS 协议版本:'TLSv1.3''TLSv1.2''TLSv1.1''TLSv1'默认值: 'TLSv1.2',除非使用 CLI 选项进行更改。使用 --tls-min-v1.0将默认值设置为'TLSv1'。使用--tls-min-v1.1将默认值设置为'TLSv1.1'。使用--tls-min-v1.3将默认值设置为 'TLSv1.3'。如果提供多个​​选项,则使用最低的最小值。

tls.DEFAULT_CIPHERS#

  • <string> tls.createSecureContext()ciphers选项 的默认值。可以为其分配任何受支持的 OpenSSL 密码。默认为crypto.constants.defaultCoreCipherList的内容 ,除非使用--tls-default-ciphers使用 CLI 选项进行更改。

NodeJS中文文档为Read dev Docs平台提供托管,中文NodeJS文档均由英文版NodeJS文档翻译,版权属于nodejs.org