안녕하세요! 2채널 호환 게시판 시스템 「つゔぁいちゃんねる (2ch.biz)」 개발 기록, 제34회입니다.
지난번(제33회)에는 원하는 사람만 다운로드할 수 있는 '온디맨드 Pull형 파일 전송'을 통해 WebRTC 특유의 대역폭 폭발 및 메모리 고갈 문제를 극복했습니다.
하지만 누구나 자유롭게 P2P로 파일을 주고받게 되면서, 다음에 우리가 직면한 것은 **'보안과 가용성의 결정적인 위기'**였습니다.
-
악의적인 파일 변조나 손상: 악의를 가진 피어가 '최신 툴 zip이야'라며 내용물을 바이러스나 불법 스크립트로 바꿔서 전송해 온다면 어떻게 방어할 수 있을까요?
-
중간 패킷 누락으로 인해 깨진 이미지나 바이너리를 열었을 때 단말기가 충돌하지 않을까요?
-
전송자가 접속을 끊으면 다운로드할 수 없는 문제: 거대한 파일을 공유해 준 전송자(Alice)가 방을 퇴실하는 순간, 나중에 '나도 그 이미지가 갖고 싶다'고 생각한 사람이 다운로드할 수 없게 됩니다.
본고에서는 BitTorrent의 분산 공유 사상을 도입하여, Web Crypto API를 이용한 SHA-256 암호학적 해시 검증과 **'분산 시딩(대리 재배포)'**을 결합한 철벽의 P2P 파일 보안에 대해 설명합니다!
클라이언트-서버형 서비스라면, 서버 측에서 바이러스 스캔을 실행하거나 AWS S3 같은 고가용성 스토리지에 파일을 보관할 수 있습니다.
하지만 완전 서버리스 P2P에서는 **'상대방의 단말기도 통신 경로도 일절 신뢰할 수 없다(Zero Trust)'**는 전제에 서야 합니다.
파일을 공유할 때, 전송자는 먼저 브라우저의 Web Crypto API를 사용하여 파일 전체의 SHA-256 해시값을 계산합니다. 이 해시값은 메타데이터(file_offer)에 담겨 사전에 모든 피어에게 브로드캐스트됩니다.
/**
* ArrayBuffer에서 SHA-256 해시 문자열(16진수)을 계산
*/
...
해시 검증을 통과한 안전한 파일을 받은 Bob은, 그 파일을 브라우저 메모리 내의 sharedFiles 맵에 등록하고 자동으로 **'2차 시더(배포자)'**로 승격합니다.
【분산 시딩의 이점】
1. Alice가 '도쿄 여행 사진 모음.zip'을 공유.
2. Bob이 다운로드 완료 및 해시 검증 통과 (Bob이 시더가 됨).
...
// 2차 시더 등록 로직
function registerAsSecondarySeeder(fileId, fileBlob) {
// 정상성이 보장된 파일만 재배포 리스트에 추가
...
}
이를 통해 전송자가 퇴실하더라도, 방에 단 한 명이라도 파일을 수신한 사람이 남아 있다면 파일 공유가 영속화되는 놀라운 내결함성을 획득했습니다.
사용자가 위험한 파일과 안전한 파일을 한눈에 식별할 수 있도록 UI 디자인에도 명확한 대비를 주었습니다.
해시 검증을 통과한 파일에는 선명한 에메랄드 그린의 '🛡️ 검증 완료 (SHA-256)' 배지가 빛나, 안심하고 저장할 수 있음을 보장합니다.
단 1바이트라도 데이터가 변조되었다면, 다운로드 버튼은 완전히 사라지고, 굵은 빨간색 박스로 **'🚨 변조/손상 감지 (다운로드는 차단되었습니다)'**라는 경고가 표시됩니다. 오클릭으로 인한 피해를 100% 근절합니다.
단일 테스트 스크립트를 사용하여, 일부러 전송 중인 청크의 1바이트를 의도적으로 변경하는 변조 공격 시뮬레이션을 실시했습니다.
| 테스트 시나리오 | 조건 | 예상 동작 | 실행 결과 |
|---|
| 정상계 전송 | 무변조 바이너리 전송 | SHA-256 일치, 저장 다이얼로그 발화 | ✅ PASS (검증 성공) |
| 중간 변조 공격 | 청크 내 1바이트를 반전 | 즉시 폐기, 경고 UI 표시, DL 차단 | ✅ PASS (완전 차단) |
| 전송자 퇴실 시나리오 | 전송자가 연결 끊긴 후, 제3자가 요청 | 2차 시더로부터 대리 전송 성공 | ✅ PASS (재배포 성공) |
Web Crypto API의 SHA-256을 이용한 암호학적 검증과, BitTorrent류의 분산 시딩으로 P2P 채팅의 파일 공유는 '안전'하고 '끊기지 않는' 강력한 시스템으로 진화했습니다.
하지만 PC에서의 개발 및 검증은 순조롭게 진행되는 반면, 스마트폰(iOS Safari / Android Chrome) 실기에서 테스트하던 팀으로부터 예상치 못한 **'스마트폰 특유의 UI 붕괴'**가 보고되었습니다.
"스마트폰으로 문자를 입력하려고 하면, 소프트웨어 키보드가 아래에서 튀어 올라와서,
메시지 입력란이 화면 밖으로 숨겨져 보이지 않아요!"
"키보드가 열릴 때마다 화면 전체의 스크롤 위치가 심하게 흔들려요!"
네이티브 앱이라면 당연한 '키보드에 딱 붙는 입력 바'를, 브라우저의 웹 기술만으로 어떻게 구현할 수 있을까요?
실제 서비스: https://2ch.biz/