-
Notifications
You must be signed in to change notification settings - Fork 23.2k
RTCDtlsTransport: getRemoteCertificates() docs #44543
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
hamishwillee
wants to merge
7
commits into
mdn:main
Choose a base branch
from
hamishwillee:ff153getremotecert
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+113
−3
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
ee63e85
FF153 RTCDtlsTransport: getRemoteCertificates()
hamishwillee 422c589
Fixes to return value
hamishwillee 8e175d6
Add info about the data in returned ArrayBuffers
hamishwillee 2baae04
code review - easy suggestions
hamishwillee 099570d
code review - accept suggestion on handshake info
hamishwillee a639084
Apply suggestions from code review
hamishwillee f662d02
Apply suggestion from @hamishwillee
hamishwillee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
111 changes: 111 additions & 0 deletions
111
files/en-us/web/api/rtcdtlstransport/getremotecertificates/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| --- | ||
| title: "RTCDtlsTransport: getRemoteCertificates() method" | ||
| short-title: getRemoteCertificates() | ||
| slug: Web/API/RTCDtlsTransport/getRemoteCertificates | ||
| page-type: web-api-instance-method | ||
| browser-compat: api.RTCDtlsTransport.getRemoteCertificates | ||
| --- | ||
|
|
||
| {{APIRef("WebRTC")}} | ||
|
|
||
| The **`getRemoteCertificates()`** method of the {{domxref("RTCDtlsTransport")}} interface returns the certificates chain of the remote peer of the DTLS connection. | ||
|
|
||
| ## Syntax | ||
|
|
||
| ```js-nolint | ||
| getRemoteCertificates() | ||
| ``` | ||
|
|
||
| ### Parameters | ||
|
|
||
| None. | ||
|
|
||
| ### Return value | ||
|
|
||
| An array of {{jsxref("ArrayBuffer")}} objects that represents the remote peer's certificate chain. | ||
| Each object contains a DER-encoded X.509 certificate. | ||
|
|
||
| For [`new`](/en-US/docs/Web/API/RTCDtlsTransport/state#new) connections, this is an empty array. | ||
| It is populated with the certificates from the remote peer when the state of the transport changes to [`connected`](/en-US/docs/Web/API/RTCDtlsTransport/state#connected). | ||
|
|
||
| ### Exceptions | ||
|
|
||
| None | ||
|
|
||
| ## Description | ||
|
|
||
| WebRTC media and data channels are secured using DTLS (Datagram Transport Layer Security). | ||
| During signaling, each endpoint advertises the fingerprint of the DTLS certificate it will present. | ||
| During the DTLS handshake, the user agent verifies that the certificate presented by the remote peer matches the fingerprint in the negotiated SDP. | ||
|
|
||
| DTLS guarantees the connected peer is the one you've been negotiating with, because only that peer has the private key matching the certificate whose fingerprint was exchanged during signaling. | ||
| However, since WebRTC uses self-signed certificates rather than certificates issued by a certificate authority, the certificate does not identify the person, service, or device at the other end. | ||
| Establishing the identity of the remote peer usually requires an out-of-band mechanism such as comparing certificate fingerprints verbally over a phone call, or using a separate authenticated channel. | ||
|
|
||
| The `getRemoteCertificates()` method allows you to get the remote certificates used by DTLS and use them for _application-layer_ authentication of the remote peer. | ||
|
|
||
| For fingerprint continuity, each peer must use the same certificate across sessions, rather than generating a new one each time they connect." | ||
| After connecting to the remote peer, you'd exchange information out-of-band to verify that it is the intended party, and use `getRemoteCertificates()` to get its certificates. | ||
| When you subsequently connect to that remote peer, you'd only allow communication if it has exactly the same certificate fingerprints. | ||
| There is still a window for a person-in-the-middle attack, but it only exists for the very first connection between peers. | ||
|
|
||
| Note that `getRemoteCertificates()` returns raw DER-encoded X.509 certificates as `ArrayBuffer` objects. | ||
| DER (Distinguished Encoding Rules) is the binary serialization format used for X.509 certificates in TLS and DTLS. | ||
| Unlike {{domxref("RTCCertificate")}}, these buffers do not expose fingerprints and expiration date directly. | ||
| To work with them you must process the raw bytes: you can hash the buffer with {{domxref("SubtleCrypto.digest()")}} to compute a fingerprint (as shown in the example below), or pass it to an X.509 parsing library to inspect individual fields. | ||
|
|
||
| ## Example | ||
|
|
||
| ### Basic usage | ||
|
|
||
| This example shows how to fingerprint the remote peer's certificate after the DTLS handshake and compare it against a stored value. | ||
|
|
||
| ```js | ||
| async function getRemoteFingerprint(dtlsTransport) { | ||
| const certs = dtlsTransport.getRemoteCertificates(); | ||
| if (certs.length === 0) { | ||
| return null; | ||
| } | ||
|
|
||
| // Hash the raw DER-encoded certificate with SHA-256 | ||
| const digest = await crypto.subtle.digest("SHA-256", certs[0]); | ||
|
|
||
| // Format as colon-separated hex, matching the SDP a=fingerprint convention | ||
| return Array.from(new Uint8Array(digest)) | ||
| .map((b) => b.toString(16).padStart(2, "0")) | ||
| .join(":"); | ||
| } | ||
|
|
||
| // Call once DTLS handshake is complete | ||
| pc.addEventListener("connectionstatechange", async () => { | ||
| if (pc.connectionState === "connected") { | ||
| const sender = pc.getSenders()[0]; | ||
| if (!sender?.transport) return; | ||
|
|
||
| const fingerprint = await getRemoteFingerprint(sender.transport); | ||
| if (!fingerprint) return; | ||
| const stored = localStorage.getItem("remote-peer-fingerprint"); | ||
|
|
||
| if (!stored) { | ||
| localStorage.setItem("remote-peer-fingerprint", fingerprint); | ||
| } else if (stored !== fingerprint) { | ||
| console.error("Certificate mismatch — closing connection"); | ||
| pc.close(); | ||
| } | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| ## Specifications | ||
|
|
||
| {{Specifications}} | ||
|
|
||
| ## Browser compatibility | ||
|
|
||
| {{Compat}} | ||
|
|
||
| ## See also | ||
|
|
||
| - {{domxref("RTCPeerConnection.generateCertificate()")}} | ||
| - [WebRTC API](/en-US/docs/Web/API/WebRTC_API) | ||
|
hamishwillee marked this conversation as resolved.
|
||
| - [Introduction to the Real-time Transport Protocol (RTP)](/en-US/docs/Web/API/WebRTC_API/Intro_to_RTP) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.