Skip to main content
Every data channel and media track in HashDrop is protected by the encryption built into the WebRTC standard. No configuration is required — the browser negotiates and enforces encryption automatically. On top of the transport layer, HashDrop adds SHA-256 file integrity checks so the receiver can be certain the file arrived byte-for-byte intact.

WebRTC DTLS/SRTP encryption

WebRTC mandates two complementary protocols for encrypted communication:
  • DTLS (Datagram Transport Layer Security) — negotiates session keys and authenticates both peers during the WebRTC handshake. It is the UDP equivalent of TLS and provides the same certificate-based security model.
  • SRTP (Secure Real-time Transport Protocol) — encrypts the actual media and data payloads in flight using the keys established by DTLS.
Both protocols apply across all of HashDrop’s transfer modes:
Transfer typeProtected by
File transfer (data channel)DTLS + SRTP
Video conferencing (audio/video tracks)DTLS + SRTP via LiveKit
Text / chat messages (data channel)DTLS + SRTP
The encryption is negotiated in the browser using the Web Crypto API and is not accessible to the HashDrop server at any point. The server sees only the ICE candidates needed to route the initial connection — not the session keys or any payload.
DTLS/SRTP is the same encryption stack used by Zoom and Google Meet. It is a mandatory part of the WebRTC specification; no WebRTC-compliant browser can skip it.

SHA-256 file integrity verification

Transport encryption prevents eavesdropping, but it does not by itself guarantee the file was not corrupted during chunked reassembly. HashDrop adds an explicit integrity check using SHA-256.

How the hash is computed

The sender calls calculateFileHash before the transfer begins. The function reads the entire file into an ArrayBuffer and passes it to the browser’s native crypto.subtle.digest implementation:
/**
 * Calculate SHA-256 hash of a file
 */
export async function calculateFileHash(file: File): Promise<string> {
  const buffer = await file.arrayBuffer()
  const hashBuffer = await crypto.subtle.digest('SHA-256', buffer)
  const hashArray = Array.from(new Uint8Array(hashBuffer))
  const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
  return hashHex
}
The resulting 64-character hex string is sent to the receiver alongside the file metadata.

How the hash is verified

After the receiver reassembles all chunks into a complete File object, calculateFileHash is called again on the reconstructed file. The result is compared against the sender’s hash using verifyFileHash:
/**
 * Verify file integrity by comparing hashes
 */
export function verifyFileHash(calculatedHash: string, expectedHash: string): boolean {
  return calculatedHash === expectedHash
}
If the hashes match, the download is offered to the user. If they differ, the transfer is marked as failed and the file is discarded.

Verification flow

1

Sender computes hash

Before any data is sent, calculateFileHash produces a SHA-256 digest of the original file using crypto.subtle.digest.
2

Metadata transmitted

The hash, filename, MIME type, and total size are sent to the receiver over the encrypted WebRTC data channel.
3

File streams as chunks

The file is split into 16 KB binary chunks, sequenced, and streamed across the peer connection.
4

Receiver reassembles

The receiver collects all chunks and reassembles them into a single Blob in the correct order.
5

Hash verified

calculateFileHash runs on the reassembled file. verifyFileHash compares the result to the sender’s hash. On a match, the file is made available for download.

Web Crypto API usage

HashDrop relies exclusively on the browser’s built-in window.crypto object and never ships a third-party cryptography library for core security operations:
OperationAPI used
SHA-256 file hashingcrypto.subtle.digest('SHA-256', buffer)
Warp Code generationcrypto.getRandomValues(new Uint32Array(1))
Using the native Web Crypto API means the cryptographic primitives are implemented in the browser’s C++ runtime, not in JavaScript, and are subject to the same auditing and update cycle as the browser itself.

Build docs developers (and LLMs) love