RTCCertificate: getFingerprints() 方法

基准线 2025
新推出

自 ⁨2025 年 4 月⁩起,此功能适用于最新设备和浏览器版本。此功能可能不适用于较旧的设备或浏览器。

RTCCertificate 接口的 getFingerprints() 方法用于获取一个证书指纹的数组。

这可以在应用层代码中用于获取证书指纹,这些指纹是使用浏览器支持的各种算法创建的证书的哈希

语法

js
getFingerprints()

参数

无。

返回值

一个包含指纹值的数组。每个指纹由一个具有以下属性的对象表示:

algorithm

一个字符串,指示用于在 value 中创建指纹的哈希函数算法。允许的值包括:"sha-1""sha-224""sha-256""sha-384""sha-512""md5""md2"

value

一个字符串,包含证书指纹,以小写十六进制字符串表示,使用 algorithm 哈希函数计算得出。格式在RFC4572, Section 5 中有更精确的定义。

描述

用于特定 RTCPeerConnectionRTCCertificate 实例可以通过 RTCPeerConnection.generateCertificate() 静态方法创建,或者从 IndexedDB 存储中获取,并在构造函数中设置。如果在构造函数中未传递任何证书,则会自动创建,在这种情况下,可以使用 RTCPeerConnection.getConfiguration() 获取使用的证书。

浏览器将在 SDP 提议阶段自动交换与每个 RTCPeerConnection 关联的证书和指纹,并将它们用作 DTLS 握手的一部分,以验证远程方是否与 SDP 中发送的证书/端点匹配。这提供了一种低级别的验证,以确保 WebRTC 通信是与发起提议的远程方建立的,但它不提供任何关于通信用户身份的验证。

在某些情况下,应用层将证书指纹带外共享会很有用。

  • 如果两个浏览器之间已建立信任关系,则可以通过存储证书并在后续会话中(最多一年内)重新使用它们来持久化这种信任。受信任的证书通过其指纹进行标识。
  • 想要识别特定用户的对等方可以发送指纹,并在“带外”(即,在浏览器管理的 WebRTC 通信流程之外)验证关联的用户。应用程序可以使用该指纹来识别后续与特定用户的会话。
  • 在某些会议服务器(“middlebox”)实现中,服务器可能需要在进行任何提议/应答之前了解指纹。

对等方可能支持不同的算法集。在比较证书时,应匹配对等方支持的算法集的所有指纹值。

示例

获取证书指纹

此示例展示了如何从本地对等方获取证书指纹,并将其与远程对等方的指纹进行比较。

首先,我们创建一个连接并获取证书及其指纹。我们通过“某种带外机制”从远程对等方获取指纹。

js
// Get the certificate fingerprints from the local peer.
const rtcPeerConnection = new RTCPeerConnection();
const configuration = rtcPeerConnection.getConfiguration();
const certificates = configuration.certificates;
let fingerprintsFromClient;

if (certificates && certificates.length > 0) {
  certificates.forEach((cert) => {
    // For purpose of demonstration, just get first certificate
    fingerprintsFromClient = cert.getFingerprints();
    break;
  });
}

// Get the certificate fingerprints from the remote peer for particular certificate (pseudo code)
const fingerprintsFromServer = [
  /* … */
];

有多种方法可以比较特定证书的指纹数组。在这里,我们将数组转换为字典对象,其中算法名称是属性,然后进行比较。这样做是可行的,因为每种算法只能有一个指纹值。(还有许多其他方法可以对两个数组进行排序和比较)。

js
let clientFingerprintDict = Object.fromEntries(
  fingerprintsFromClient.map((x) => [x.algorithm, x.value]),
);
let serverFingerprintDict = Object.fromEntries(
  fingerprintsFromServer.map((x) => [x.algorithm, x.value]),
);

// Function to compare two objects and return true if there are common properties
// and all common properties match.
function compareObjects(obj1, obj2) {
  const commonProperties = Object.keys(obj1).filter((prop) =>
    Object.hasOwn(obj2, prop),
  );
  // Return false if there are no common properties
  if (Object.keys(commonProperties).length === 0) return false;

  // Return false if any common properties don't match
  for (const prop of commonProperties) {
    if (obj1[prop] !== obj2[prop]) {
      return false;
    }
  }

  return true;
}

const matchingFingerprints = compareObjects(
  clientFingerprintDict,
  serverFingerprintDict,
);
console.log(matchingFingerprints);

规范

规范
WebRTC:浏览器中的实时通信
# dom-rtccertificate-getfingerprints

浏览器兼容性