클라이언트 사이드 암호화란? 브라우저가 작업을 수행합니다
클라이언트 사이드 암호화는 업로드 전 브라우저에서 파일이 암호화됨을 의미합니다. 최대한의 개인정보보호와 통제.
클라이언트 사이드 암호화는 브라우저나 앱이 네트워크에 닿기 전에 기기에서 파일을 암호화하는 방식입니다. 서버는 AES-256-GCM 출력인 암호문만 받으며, 이는 무작위 잡음과 구별할 수 없습니다. 복호화 키는 클라이언트를 절대 벗어나지 않습니다. 이는 제공자가 키를 보유하여 기술적으로 파일을 읽을 수 있는 서버 사이드 암호화의 반대입니다. Web Crypto API(window.crypto.subtle)는 플러그인 없이 모든 현대 브라우저에서 이를 가능하게 하며, AES-NI 하드웨어에서 약 2~3 GB/s 속도로 실행됩니다. HexaTransfer, SwissTransfer, Tresorit Send, Proton Drive는 이 모델을 사용하여 서비스 자체가 침해되더라도 파일의 프라이버시를 보장합니다.
브라우저가 암호화 엔진이 된 전환
5년 전만 해도 진정한 암호화는 데스크탑 앱을 설치하거나 명령줄에서 PGP를 사용해야 했습니다. W3C가 2017년 표준화한 Web Crypto API가 이를 바꾸었습니다. Chrome, Firefox, Safari, Edge 모든 주류 브라우저에서 JavaScript로 AES-GCM, RSA-OAEP, ECDH, HMAC, PBKDF2, SHA-256을 직접 사용할 수 있습니다.
성능은 더 이상 장벽이 아닙니다. Intel AES-NI 명령어는 AES-256-GCM을 코어당 3~5 GB/s로 처리합니다. Apple M 시리즈와 Qualcomm Snapdragon 칩의 ARM 암호화 확장도 비슷한 처리량을 제공합니다. 브라우저에서 1 GB 파일 암호화는 중급 노트북에서 약 300~500 ms가 걸립니다.
남은 과제는 브라우저 메모리보다 큰 파일 처리입니다. Streams API와 ReadableStream을 사용하면 파일을 4 MB 청크로 처리하고, 각 청크를 고유한 카운터 모드 IV로 독립적으로 암호화할 수 있습니다. 이것이 서비스가 한도를 10 GB 이상으로 높이는 방법입니다.
최소한의 클라이언트 사이드 암호화 흐름
일반적인 브라우저 기반 서비스가 실행하는 순서:
// 1. 무작위 256비트 AES 키 생성
const key = await crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]
);
// 2. 파일을 청크로 읽기
const file = fileInput.files[0];
const chunkSize = 4 * 1024 * 1024;
// 3. 고유한 12바이트 IV로 각 청크 암호화
for (let offset = 0; offset < file.size; offset += chunkSize) {
const chunk = file.slice(offset, offset + chunkSize);
const iv = crypto.getRandomValues(new Uint8Array(12));
const ciphertext = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv }, key, await chunk.arrayBuffer()
);
// 4. [iv || ciphertext]를 서버에 업로드
}
// 5. 키를 내보내고 공유 URL fragment에 삽입
const keyBytes = await crypto.subtle.exportKey("raw", key);
const shareUrl = `https://example.com/d/${fileId}#k=${base64url(keyBytes)}`;
서버는 무작위처럼 보이는 바이트와 파일 ID만 봅니다. 키는 사용자의 브라우저 메모리와 URL fragment에만 존재합니다.
서버 사이드 암호화보다 나은 이유
서버 사이드 암호화는 제공자가 요청 시 복호화한다는 의미입니다 — 썸네일 생성, 바이러스 검사, 검색 쿼리 처리, 법적 요청 대응 등을 위해. 2023년 Apple 공개 사항에 따르면 고급 데이터 보호가 출시되기 전 iCloud 백업은 Apple과 미국 법 집행 기관이 유효한 요청으로 접근할 수 있었습니다.
클라이언트 사이드는 이를 뒤집습니다. 키가 제공자에 도달하지 않으므로:
- 불량 직원은 아무것도 볼 수 없습니다: 데이터베이스 접근 권한을 가진 엔지니어는 암호문만 얻습니다.
- 영장은 암호문을 생성합니다: 제공자는 키 없이는 쓸모없는 암호화된 블롭을 제출하여 영장에 응할 수 있습니다.
- 침해는 암호문을 유출합니다: 2021년 LastPass 사례가 이의 중요성을 보여줬습니다.
- 제공자 장애가 데이터를 침해하지 않습니다: 회사가 문을 닫아도 공유 링크의 로컬 복사본(URL)이 파일을 복호화합니다.
서버가 여전히 볼 수 있는 것
클라이언트 사이드 암호화는 파일 내용을 보호하지만 전부는 아닙니다. 서버는 보통 다음을 관찰합니다.
- 파일 크기: 암호문 길이가 평문 길이를 근사합니다(AES-GCM은 암호화당 16바이트 오버헤드에 12바이트 IV를 더합니다).
- 타임스탬프와 함께 업로드 및 다운로드 IP 주소.
- 클라이언트의 TLS 지문을 포함한 TLS 핸드셰이크의 세션 메타데이터.
- 파일명이 암호화된 페이로드에 포함되지 않으면 파일명이 노출될 수 있습니다.
좋은 클라이언트 사이드 서비스는 파일명을 암호문 헤더의 일부로 암호화하고, 크기를 버킷(1 MB, 10 MB, 100 MB)으로 패딩하여 숨깁니다.
패스워드로 보호된 클라이언트 사이드 암호화
많은 서비스가 URL fragment 위에 패스워드를 추가할 수 있게 합니다. 흐름:
- 브라우저가 무작위 128비트 솔트를 생성하고 PBKDF2-HMAC-SHA-256(600,000회 반복, OWASP 2023 권장) 또는 Argon2id(
memory=64 MB, iterations=3)로 키를 파생합니다. - 파일이 파생된 키로 암호화됩니다.
- 솔트가 URL fragment에 들어갑니다; 패스워드는 대역 외로 전달됩니다.
- 수신자가 패스워드를 입력하면 로컬에서 키를 재파생합니다.
이렇게 하면 단일 채널 공유(URL이면 충분)에서 이중 요소로 전환됩니다. 공격자는 링크와 패스워드 모두 필요합니다. PBKDF2 600,000회 반복으로 오프라인 무차별 대입은 현대 GPU에서 추측당 약 10초가 걸리므로, 패스워드는 40비트 이상의 엔트로피가 필요합니다.
신뢰 이동: 서비스에서 클라이언트 코드로
클라이언트 사이드 암호화는 신뢰 경계를 이동시킵니다. 이전에는 서비스가 평문을 잘 처리하길 신뢰했습니다. 이제는 서비스가 매 페이지 로드 시 브라우저에 전달하는 JavaScript를 신뢰합니다. 악의적인 업데이트는 암호화 전이나 도중에 키를 외부로 빼낼 수 있습니다.
세 가지 완화책이 있으며, 엄격성이 다릅니다.
- 하위 리소스 무결성(SRI): script 태그가 알려진 값과 JS 해시를 일치시킵니다.
- 코드 감사: Cure53, NCC Group, Trail of Bits 같은 회사가 암호화 로직의 건전성을 검증합니다.
- 재현 가능한 빌드: 독립적인 당사자가 배포된 코드가 공개된 소스와 일치하는지 확인합니다.
- 콘텐츠 보안 정책(CSP): 암호화를 변조할 수 있는 제3자 스크립트를 차단합니다.
클라이언트 사이드가 빛나는 사용 사례
클라이언트 사이드 암호화가 가치 있는 몇 가지 시나리오:
- 법률 및 의료 문서: HIPAA 45 CFR § 164.312와 변호사-의뢰인 특권은 모두 제공자 불가시적 아키텍처에서 크게 이점을 얻습니다. 한국의 PIPA도 개인 의료 정보에 동일한 원칙을 적용합니다.
- 언론 취재와 취재원 보호: 심지어 메타데이터 노출도 위험을 수반하는 미편집 문서 전송.
- 기업 지적재산: 파일 전송 제공자의 내부자 위협이 현실적인 우려인 이사회 자료, 재무 모델, M&A 자료.
- 개인 기록: 세금 신고서, 여권, 의료 검사 — 제공자 침해 헤드라인에 나오길 불편해할 파일.
진정한 클라이언트 사이드 암호화를 인식하는 방법
서비스가 실제로 클라이언트 사이드 암호화를 하는 네 가지 신호:
- URL fragment가 키를 포함: 공유 URL에 base64 인코딩된 무작위 바이트처럼 보이는
#이후 텍스트가 있습니다. - 업로드가 암호문: 업로드 중 DevTools → Network를 엽니다; 요청 본문이 무작위 바이트처럼 보여야 합니다.
- 대용량 파일도 빠르게 작동: 진정한 클라이언트 사이드 흐름은 청크를 스트리밍합니다.
- 개인정보 처리방침에 "파일을 복호화할 수 없습니다": 기술적 백서와 함께, 마케팅 문구만이 아닌.
통과하는 서비스: SwissTransfer의 E2EE 티어, Tresorit Send, Proton Drive 공유 링크, Mega.nz, HexaTransfer. 통과하지 못하는 서비스: WeTransfer(표준), Google Drive, Dropbox 공유 링크.
hexatransfer.com에서 사용해 보세요 — 무료, 계정 불필요, 최대 10GB.
엔드투엔드 암호화로 대용량 파일을 안전하게 전송
엔드투엔드 암호화로 최대 10GB의 파일을 무료로 전송하세요. 계정이 필요하지 않습니다. 업로드 전에 브라우저에서 파일이 암호화되어 다른 사람은 읽을 수 없습니다.
파일 보내기