브라우저에서 암호화할 때, 평문이 나가지 않았는지 직접 확인하는 법

페이지의 「로컬 암호화」「업로드 없음」만으로는 증명되지 않습니다. 개발자 도구 Network를 열고, 이번 실험에만 있는 카나리아 문자열로 검색하세요. 요청 줄, 요청 본문, 분석 전송에 평문, 암호, 해시 뒤의 키가 나와서는 안 됩니다. AES-256-GCM은 이 기기의 Web Crypto에서 끝난 뒤에만 암호문이 나갈 수 있습니다.

문구는 확인할 수 없고, 트래픽은 확인할 수 있습니다

많은 사람이 「온라인 암호화」 페이지의 안전을, 로컬 계산, 업로드 제로, 종단 간이라는 한 문장으로 판단합니다. 그 문장은 파일을 서버에 POST한 뒤 대신 암호화하는 사이트에도 붙을 수 있습니다. 증거가 아닙니다.

그 자리에서 볼 수 있는 것은 현재 탭이 보낸 요청입니다. 브라우저 개발자 도구 Network 패널은 메서드, 주소, 쿼리 문자열, 요청 본문, 일부 방문 통계를 나열합니다. 방금 고른 파일 이름, 암호, 당신만 아는 카나리아 평문이 여기에 나오면, 이른바 로컬 암호화는 성립하지 않습니다.

반대로 Network에 평문이 없다고 해서, 메모리에 평문이 없다거나 확장 프로그램이 클립보드를 읽지 않았다거나 다음 버전에서도 같다는 뜻은 아닙니다. 확인의 가치는 검증할 수 없는 홍보를, 반복 가능한 관찰로 줄이는 데 있습니다.

「로컬」이 가리키는 계산 층

「브라우저 로컬」은 「이 도메인이 안전해 보인다」가 아니라, 「암호화·복호화가 지금 보고 있는 이 탭에서 일어난다」는 뜻입니다. AES-256-GCM의 일반적인 올바른 경로는 Web Crypto API입니다. 키 파생, 암호화, 인증 태그가 브라우저가 제공하는 암호학 인터페이스에서 끝나야 하며, 원문을 원격 API에 맡겨 계산하면 안 됩니다.

파일 암호화의 전형적인 흐름은 이렇습니다. 파일 선택기로 이 기기의 파일을 고르고, 스크립트가 메모리의 바이너리 덩어리로 읽은 뒤 덩어리마다 암호화하고, 브라우저가 암호문 다운로드를 시작합니다. 내려받은 .lock 또는 .enc는 결과 파일이며 업로드 영수증이 아닙니다. 단일 파일 상한이 5 GB라면, 이 기기의 스트리밍 처리 능력을 뜻하며 서버가 5 GB 원문을 받았다는 뜻이 아닙니다.

「업무 업로드」와 「페이지가 원래 보내는 요청」도 나누어야 합니다. 바로 쓰는 도구 사이트도 스타일과 스크립트를 로드하고, 본문 없는 방문 통계를 보낼 수 있습니다. 그런 요청이 있다고 해서 「파일이 업로드됐다」고 단정할 수는 없습니다. 다만 통계 요청의 query나 body에 방금 입력한 암호나 검사할 비밀번호가 있다면, 이야기는 달라집니다.

계산 경계를 확인할 수 있는 문장으로 쓰는 편이 형용사보다 낫습니다. 비밀번호 생성, 비밀번호 검사, UTM 제거·마스킹, 파일 암호의 평문과 키는 기본적으로 브라우저를 떠나지 않습니다. 일회용 링크는 암호문만 나갈 수 있고, 복호화 키는 URL의 # 프래그먼트에 둡니다. MakePwd는 이 경계로 도구를 구현하며, 전부 바로 쓰고 계정이 없습니다. 약속은 여전히 약속입니다. 아래에서는 Network로 점검 항목을 만듭니다.

실제 키, 신분증, 마스킹하지 않은 표로 실험하지 마세요. 버려도 되는 작은 파일과 일회용 긴 문장을 쓰세요. 확인하는 것은 트래픽이지, 개인정보를 다시 노출하는 일이 아닙니다.

Network로 반복 가능한 점검을 한 번 하기

먼저 실제 업무에 나오지 않을 표식을 준비하세요. 파일 이름은 canary-local-2026.xlsx로 두고, 암호는 무작위 긴 문장, 본문에는 이번 실험에만 있는 한 줄을 넣으세요. 카나리아의 역할은 검색입니다. Network 필터에 붙여넣어 적중하면 실패입니다.

개발자 도구를 열고 Network로 전환한 뒤 Preserve log를 켜고 XHR / Fetch를 필터하세요. 「성공한 요청」만 보지 마세요. 취소되거나 4xx가 난 요청에도 이미 평문이 실렸을 수 있습니다.

이어서 전체 조작을 한 번 하세요. 파일을 고르고, 암호를 입력하고, 암호화 또는 생성을 누릅니다. 끝난 뒤 패널을 닫지 말고 아래 세 곳을 봅니다.

  1. 필터에 카나리아 문자열을 붙여넣고, 먼저 빨간 적중이 있는지 보세요. 적중이 있으면 그 요청을 읽고 멈추세요. 「로컬처럼 느껴진다」는 판단은 더 하지 않아도 됩니다.
  2. 적중이 없으면 XHR / Fetch를 하나씩 열어 요청 줄, 쿼리 문자열, 요청 본문을 대조하세요. 정적 자원, 글꼴, 스크립트는 무시해도 됩니다.
  3. 방문 통계 경로는 따로 필터한 뒤 query와 body를 여세요. 페이지 제목과 경로는 나와도 됩니다. 방금 입력한 암호, 검사할 비밀번호, 정제 전 원문, 파일 내용은 나오면 안 됩니다.

요청 줄 보기

전체 URL의 path와 ? 뒤 쿼리는 글자 단위로 볼 가치가 있습니다. id 같은 위치 필드는 나와도 됩니다. 파일 이름, 암호, 검사할 비밀번호, # 뒤의 키는 나오면 안 됩니다. 주소창 전체와 요청 줄을 비교하세요. 해시 뒤가 요청 줄에 들어갔다면, fragment를 query로 잘못 썼거나 스크립트가 읽은 뒤 요청에 넣었다는 뜻입니다.

요청 본문 보기

POST / PUT payload가 두 번째 지점입니다. 파일 암호화가 로컬에서 끝난다고 한다면, 요청 본문에 원본 파일 바이너리나 암호가 있으면 안 됩니다. 일회용 링크에는 암호문 필드가 있을 수 있고, 그건 예상된 출고 데이터입니다. 방금 입력한 원문처럼 보이지 않는지만 확인하면 됩니다. 비밀번호 검사 페이지가 검사할 비밀번호를 POST한다면, 목적이 「유출 조회」든 「강도 계산」이든 이미 이 기기를 떠난 것입니다.

분석 전송은 따로 보기

방문 통계는 자주 빠집니다. 주 인터페이스가 깨끗해도 전송에 입력창 전문이 실리면, 이번 조작을 「평문이 브라우저에 남았다」고 볼 수 없습니다. 통계 경로를 필터할 때 「분석 스크립트는 무조건 무해하다」고 가정하지 마세요. 또 다른 출고 요청일 뿐이며, 검사 방식은 업무 인터페이스와 같습니다.

Preserve log를 켜 두세요. 암호화 후 페이지가 이동하거나 새로고침되면, 체크하지 않았을 때 평문을 실은 첫 요청이 이미 지워져 「패널이 비어 있다」는 착각이 납니다.

물음표는 HTTP로 가고, 해시는 기본으로 가지 않습니다

URL에는 자주 섞이는 두 구간이 있습니다. 물음표 뒤 쿼리는 HTTP 요청 줄에 들어가고, 서버, 리버스 프록시, 액세스 로그가 모두 볼 수 있습니다. 해시 뒤 프래그먼트는 기본으로 브라우저가 로컬에 남겨 현재 페이지 스크립트가 읽으며, 이번 문서 요청과 함께 서버로 가지 않습니다.

그래서 일회용 암호문 링크가 키를 #에 두면, 수신자가 s.html?id=...#키를 열 때 서버는 설계상 id만 보고 키는 보지 못합니다. 추가 암호화 프로토콜이 아니라, 브라우저의 fragment 기본 동작입니다. 한계도 있습니다. 전체 주소를 티켓, 단체 채팅, 해시를 버리는 리다이렉트 페이지에 붙이면, 키는 「HTTP에 안 들어감」에서 「다른 사람 화면과 로그에 나타남」으로 바뀝니다.

확인 방법도 구체적입니다. 테스트 일회용 링크를 하나 만들어, 생성 요청 body에 암호문만 있는지 보세요. 읽기 페이지를 열 때 문서 요청과 이후 인터페이스 URL에 id만 있는지 보세요. 주소창 # 뒤는 이 요청들에 나오면 안 됩니다. 읽기 페이지는 수신자에게 공개이며 로그인이 필요 없습니다.

어디를 볼까 HTTP로 가나 통과 기준
페이지 문구 해당 없음 증거가 될 수 없고, 대조용일 뿐입니다
요청 줄 / query 카나리아 없음, 암호 없음, fragment 키 없음
POST body 원문 없음; 일회용 링크는 암호문만 허용
URL # 프래그먼트 기본은 아니오 주소창에는 있고 요청 줄에는 없음
방문 통계 구현에 따름 입력창 원문 없음

무엇을 증명할 수 있고, 무엇을 증명할 수 없는가

이번 점검이 받쳐 주는 결론은 좁습니다. 그 한계를 적어 두는 편이 더 쓸모 있습니다.

받쳐 줄 수 있는 것: 지금 쓰는 이 브라우저, 이 버전, 이번 조작에서 평문, 암호, fragment 키가 관찰된 HTTP 업무 데이터나 분석 원문으로 탭을 떠나지 않았다는 점.

받쳐 줄 수 없는 것: 다른 탭이나 확장이 클립보드를 읽지 않는다, 디스크의 다운로드 폴더가 안전하다, 상대가 암호문을 받은 뒤 스크린샷을 찍지 않는다, 비밀번호 검사가 전 세계 유출 라이브러리를 덮는다. 검사가 로컬 엔트로피와 공개 약한 비밀번호 Top 목록만 한다면, 「흔한 약한 비밀번호처럼 보이는가」만 답할 수 있고 「어떤 유출에도 나온 적 없다」는 답하지 못합니다. 전 세계 HIBP 조회가 아닙니다. 목록 범위를 어떻게 쓸지, 줄 수를 그 자리에서 세는 단계는 로컬 약한 비밀번호 목록이 증명하는 것, 전 세계 유출 조회가 아닌 이유에 있습니다.

침투 테스트로 이해하지도 마세요. WebSocket, Service Worker 캐시를 검사하지 않았고, 난독화 스크립트를 역분석하지도 않았습니다. 목표는 동료에게 이렇게 말할 수 있는 것입니다. Network를 열었고, 카나리아로 검색했으며, 요청 줄과 body가 깨끗했다. 「공식 사이트에 업로드 안 한다고 적혀 있다」를 전달하는 것보다 엔지니어링 토론에 가깝습니다.

같은 단계를 바로 쓰는 도구에도 적용하기

계산 경계를 분명히 적어 둔 페이지로 연습하려면 MakePwd 파일 암호화부터 시작하면 됩니다. 열자마자 쓸 수 있고 가입이 필요 없습니다. 실제 개인정보가 없는 작은 파일을 고르고, 암호는 카나리아로 쓴 뒤 암호화하여 .lock을 받으세요. 동시에 Network를 보세요. 정적 자원과 방문 통계는 보일 수 있지만, 원본 파일이나 암호가 업무 필드로 보이면 안 됩니다. 사이트 설명대로 알고리즘은 AES-256-GCM이며 Web Crypto에서 계산하고, 단일 파일은 5 GB를 넘지 않습니다.

일회용 링크는 두 번째 연습에 맞습니다. 무해한 테스트 텍스트를 만들어 출고가 암호문인지 확인하세요. 읽기 페이지는 수신자에게 공개이며, 링크 형태는 s.html?id={id}#{key}입니다. 비밀번호 검사는 「입력창 내용이 통계에 들어가나」를 연습하기 좋습니다. 제품 설명대로 검사할 비밀번호는 업로드하지 않고, 대조는 로컬 목록에서 일어납니다.

이 연습의 목적은 어떤 사이트가 「절대 안전하다」고 증명하는 것이 아니라, 같은 확인 단계를 익히는 것입니다. 로컬 암호화를 주장하는 어떤 페이지로 바꿔도 단계는 같습니다. 카나리아, Preserve log, 요청 줄, 요청 본문, 통계 전송.

다음에 확인할 때 기억할 세 가지

첫째, 트래픽을 보고 문구를 보지 마세요. 둘째, 암호문 출고는 받아들일 수 있고, 키와 원문은 안 됩니다. 셋째, 브라우저, 버전, 기능을 바꾼 뒤에는 카나리아 검색을 다시 하세요. 반복할 수 있는 관찰만 여러분 보안 설명에 적을 가치가 있습니다.

「왜 키를 해시 뒤에 둘 수 있나」를 더 묻고 싶다면, 그건 다른 글의 주제입니다. 브라우저가 URL fragment를 어떻게 다루는지, 어떤 경우에 깨지는지. 이 글은 「평문이 이 탭을 떠났는가」만 그 자리에서 끝낼 수 있는 점검으로 줄입니다.