본문으로 건너뛰기
HexaTransfer
블로그로 돌아가기
암호화 및 보안

클라이언트 사이드 암호화란? 브라우저가 작업을 수행합니다

클라이언트 사이드 암호화는 업로드 전 브라우저에서 파일이 암호화됨을 의미합니다. 최대한의 개인정보보호와 통제.

클라이언트 사이드 암호화는 브라우저나 앱이 네트워크에 닿기 전에 기기에서 파일을 암호화하는 방식입니다. 서버는 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 위에 패스워드를 추가할 수 있게 합니다. 흐름:

  1. 브라우저가 무작위 128비트 솔트를 생성하고 PBKDF2-HMAC-SHA-256(600,000회 반복, OWASP 2023 권장) 또는 Argon2id(memory=64 MB, iterations=3)로 키를 파생합니다.
  2. 파일이 파생된 키로 암호화됩니다.
  3. 솔트가 URL fragment에 들어갑니다; 패스워드는 대역 외로 전달됩니다.
  4. 수신자가 패스워드를 입력하면 로컬에서 키를 재파생합니다.

이렇게 하면 단일 채널 공유(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 자료.
  • 개인 기록: 세금 신고서, 여권, 의료 검사 — 제공자 침해 헤드라인에 나오길 불편해할 파일.

진정한 클라이언트 사이드 암호화를 인식하는 방법

서비스가 실제로 클라이언트 사이드 암호화를 하는 네 가지 신호:

  1. URL fragment가 키를 포함: 공유 URL에 base64 인코딩된 무작위 바이트처럼 보이는 # 이후 텍스트가 있습니다.
  2. 업로드가 암호문: 업로드 중 DevTools → Network를 엽니다; 요청 본문이 무작위 바이트처럼 보여야 합니다.
  3. 대용량 파일도 빠르게 작동: 진정한 클라이언트 사이드 흐름은 청크를 스트리밍합니다.
  4. 개인정보 처리방침에 "파일을 복호화할 수 없습니다": 기술적 백서와 함께, 마케팅 문구만이 아닌.

통과하는 서비스: SwissTransfer의 E2EE 티어, Tresorit Send, Proton Drive 공유 링크, Mega.nz, HexaTransfer. 통과하지 못하는 서비스: WeTransfer(표준), Google Drive, Dropbox 공유 링크.

hexatransfer.com에서 사용해 보세요 — 무료, 계정 불필요, 최대 10GB.

엔드투엔드 암호화로 대용량 파일을 안전하게 전송

엔드투엔드 암호화로 최대 10GB의 파일을 무료로 전송하세요. 계정이 필요하지 않습니다. 업로드 전에 브라우저에서 파일이 암호화되어 다른 사람은 읽을 수 없습니다.

파일 보내기