2026-09-07
파일 암호화가 오히려 손해인 세 곳 — 동기화 폴더, 공동 작업, 그리고 Git
보안 관련 조언은 대체로 한 방향으로만 흐릅니다. 민감한가? 그러면 암호화하라. 이 답은 꽤 자주 맞기 때문에 마치 언제나 맞는 말처럼 들리고, 그래서 암호화가 실제로 무엇인지를 가려 버립니다. 암호화는 파일에 붙이는 속성이 아니라 교환입니다. 읽을 수 있는 바이트로 컴퓨터가 해 주던 일들 — 바뀐 부분만 골라 동기화하기, 두 사람의 수정을 합치기, 미리보기 띄우기, 변경분 비교하기, 악성코드 검사하기, 내용으로 검색하기, 이 사람에게만 권한 주기 — 을 전부 내놓는 대신, 암호를 모르는 사람에게 그 바이트가 아무 쓸모도 없게 만드는 거래죠.
파일이 내 손을 떠나는 중이라면 남는 장사입니다. 그런데 그 파일이 계속 여기 남아 매주 수정되고 동료 넷과 공유되는 중이라면, 대개 손해 보는 거래이고 청구서는 몇 주 뒤에 도착합니다. 뭐가 뭔지 구분 안 되는 암호화 파일이 쌓인 폴더, 어느새 용량이 세 배가 된 저장소, 세 명이 아는데 그중 한 명은 이미 퇴사한 암호. 이 글은 잘 안 쓰이는 나머지 절반입니다. 파일 암호화가 오히려 상황을 나쁘게 만드는 세 자리, 그 이유, 그리고 그 자리에 맞는 도구는 무엇인지. 저희는 그 암호화 도구를 만드는 쪽입니다. 언제나 "네"라고만 답하는 도구는 조언이 아니라 광고니까요.
질문 하나면 거의 다 갈린다
이 파일은 떠나는 중입니까, 아니면 여기 사는 중입니까?
떠나는 파일은 이미 완성된 파일입니다. 메일 첨부, 서랍에 넣어 둘 USB, 한 번 올려 두고 다시 안 건드릴 백업 아카이브, 수리 맡길 노트북 — 내가 통제하지 못하는 경계를 곧 넘어갈 참이고, 그 상태로는 아무도 수정하지 않습니다. 인계는 한 번이고 끝이 있습니다. 암호화가 딱 이 모양에 맞습니다. 병합이 안 된다, 미리보기가 안 된다, 일부만 갱신할 수 없다 — 암호화의 불편한 점들이 전부, 어차피 그 파일에 할 일이 없던 동작들이기 때문입니다.
사는 파일은 반대입니다. 열고, 고치고, 저장하고, 다시 엽니다. 내가 아닐 수도 있고, 기기 세 대일 수도 있습니다. 방금 나열한 동사가 전부 암호화가 없애 버리는 것들입니다. 인계용 도구를 사는 파일에 씌우면 파일이 안전해지기보다 불편해지고, 사람은 불편을 우회합니다. "작업하는 동안만" 복호화한 사본을 옆에 두는 식으로요. 애초에 없애려던 그 평문이 그렇게 다시 생깁니다.
틀린 도구 1 — 계속 고치는 파일을 동기화 폴더에 암호화해 두기
가장 흔하고 가장 눈에 안 띄는 실수입니다. 아무것도 고장 나지 않기 때문입니다. 동기화는 잘 됩니다. 다만 생각보다 훨씬 비싸고, 정작 믿고 있던 안전망을 걷어 갑니다.
암호화를 다시 돌리면 무엇이 나오는지부터 봅시다. NearSeal도, 제대로 만든 다른 파일 암호화 도구도, 암호화할 때마다 새로운 무작위 솔트와 새로운 무작위 초기화 벡터를 만들어 씁니다. 끌 수 있는 옵션이 아니라, 같은 파일을 두 번 암호화한 결과를 서로 비교할 수 없게 만드는 장치입니다. 결과적으로 쉼표 하나만 고쳐도 저장할 때마다 첫 바이트부터 완전히 다른 바이트가 나옵니다.
이제 그게 동기화에 무슨 일을 하는지 봅시다. 드롭박스가 직접 쓴 스트리밍 파일 동기화 설명에 구조가 나와 있습니다. 모든 파일은 4MB 블록으로 쪼개지고, 각 블록을 SHA-256으로 해시해 저장하며, 파일의 내용은 그 해시 목록("블록리스트")으로 식별된다는 것입니다. 이런 설계의 이득은 해시가 그대로인 블록에서 나옵니다. 암호화 파일에는 그런 블록이 하나도 없습니다. 매번 전부 새 블록입니다. 매주 손대는 300MB 암호화 아카이브는 매주 300MB 업로드이고, 다른 기기마다 같은 크기의 다운로드입니다. 같은 자료를 평범한 파일로 뒀다면 몇 MB만 오갔을 자리에서요.
더 아픈 건 안전망 쪽입니다. 평범한 문서라면 클라우드의 버전 기록이 정말 쓸모 있습니다. 화요일 버전을 열어 보고, 사고 나기 직전 버전이라는 걸 확인하고, 되돌리면 됩니다. 암호화된 덩어리의 버전 기록은 미리보기도 안 되고 검색도 안 되는 파일들에 시각만 붙어 있는 목록입니다. 버전은 여전히 남아 있지만, 어느 것을 원하는지 알아낼 방법이 사라진 겁니다.
충돌도 있습니다. 드롭박스는 자기가 대신 풀어 주지 않는다고 분명히 밝힙니다. 여러 사람이 같은 파일을 동시에 고치면 "충돌된 사본"을 만들어 두고, 안내 문서는 "두 버전을 비교해서 직접 병합하는 것이 가장 좋은 해결책"이라고 말합니다. 스프레드시트라면 합리적인 안내입니다. 암호화 컨테이너 둘에게는 안내 자체가 성립하지 않습니다. 둘 다 복호화하기 전에는 비교할 대상이 없고, 비교한 결과를 다시 하나로 합칠 방법도 없습니다. 드롭박스에는 암호화된 파일·폴더가 동기화 충돌에 걸렸을 때를 위한 별도 안내까지 있는데, 사실상 응급 처치입니다. 로컬 버전을 드롭박스 폴더 밖으로 옮겨서 원격 버전이 내려오게 하라는 것. 두 버전 중 하나는 그렇게 옆으로 치워집니다.
정작 데이터를 잃는 사고는 이보다 훨씬 시시합니다. 작업하려고 복호화하면 그 평문 사본이 암호화 파일 바로 옆, 동기화 폴더 안에 떨어집니다. 이제 모든 기기와 모든 백업으로 복제되는 것은 평문입니다. 미국 표준기술연구소(NIST)의 저장 암호화 기술 지침(SP 800-111, 2007년 11월)은 이 문제의 일반형을 짚어 둡니다. 파일·폴더 암호화로 파일을 암호화하고 원본을 지워도, 원래 평문 파일의 잔여 데이터가 저장 매체에 그대로 남아 있을 수 있다는 것입니다.
대신 무엇을 쓸 것인가. 내 기기에 사는 파일이라면 위협에 맞는 도구는 디스크 암호화입니다. macOS는 FileVault, 윈도우는 BitLocker. 기기에 실제로 닥치는 위협(분실·도난)에 대해 기기 전체를 지켜 주면서, 작업 방식은 하나도 바꾸지 않습니다. 재업로드도, 충돌도, 정체불명 덩어리도 없습니다. SP 800-111도 이 조합을 정상적인 실무로 설명합니다. 기기 분실·도난에 대비해 디스크 전체를 암호화하고, 그중 특히 민감한 일부에만 파일 단위 암호화를 추가로 덧대는 방식입니다. 파일 단위 암호화는 그 파일이 떠나는 순간을 위한 것이지, 머무는 몇 년을 위한 것이 아닙니다.
틀린 도구 2 — 팀과 오래 나눠 쓰기
암호는 권한처럼 느껴집니다. 하지만 권한이 아니고, 그 차이가 문제의 전부입니다.
권한에는 주체가 있습니다. 특정인에게 붙고, 화요일에 주고 금요일에 거둘 수 있고, 거두는 행위는 즉시 효력이 생기며 기록으로 남습니다. 암호에는 그런 게 없습니다. 그저 이제 몇 사람이 알게 된 사실일 뿐입니다. 누가 아는지 목록도 없고, 누가 언제 열었는지 기록도 없고, 만료도 없습니다.
담당자가 프로젝트를 떠날 때 무슨 일이 벌어지는지 보세요. 접근을 끊으려면 암호를 바꿔야 하고, 그러려면 파일을 다시 암호화해야 하고, 그러면 남은 사람 전원에게 파일과는 다른 경로로 새 암호를 전달해야 합니다. 다음 사람이 나갈 때 또 처음부터. 그동안 그 사람의 예전 노트북에 있는 예전 암호화 사본은 예전 암호로 여전히 열립니다. 그 파일은 처음부터 그 파일이었으니까요. 회수한 게 아니라 업데이트를 끊었을 뿐입니다. NearSeal만의 문제가 아닙니다. 공유 저장소에 암호화 파일을 두려고 만든 도구인 git-crypt조차 README에 같은 한계를 그대로 적어 둡니다. 한 번 부여한 접근 권한의 회수는 지원하지 않는다고요.
일상의 마찰도 만만치 않습니다. 두 사람이 암호화 컨테이너를 동시에 편집할 수 없으니 결국 채팅에 "저 지금 엽니다"를 올리고 순서를 지키는 방식으로 돌아갑니다. 파일 전체 검색이 안 되고, 특정 문서를 링크로 가리킬 수도 없고, 댓글이나 리뷰 도구도 못 씁니다. 몇 주면 늘 같은 결말입니다. 누군가는 일을 해야 하니 복호화한 사본을 바탕화면에 두게 되고, 그 팀의 실제 보안 수준은 그 사본이 됩니다.
대신 무엇을 쓸 것인가. 계속 함께 쓰는 자료라면, 필요한 것을 표현할 수 있는
접근 모델을 가진 플랫폼 — 사람별 권한, 즉시 회수, 접근 기록 — 을 쓰고, 파일 암호화는 그 플랫폼
밖으로 자료가 나가는 순간에만 씁니다. 외부 자문에게 메일로 보내는 추출본, 고객사로 넘기는 아카이브,
USB에 담아 나가는 사본 같은 것들이요. 사람별 접근에는 암호 대신 각자의 공개키로 암호화하는 방식이라는
진짜 해법도 있습니다. age 형식이 그 방식을 지원합니다. 다만 NearSeal은 그 기능을 제공하지 않습니다.
계정도 서버도 없는 브라우저 도구에는 키 목록을 둘 만한 곳이 마땅치 않아서 의도적으로 암호 방식만
지원합니다. 수신자별 키가 필요하다면 이 웹사이트가 아니라 age 명령줄 도구를 쓰셔야
합니다.
틀린 도구 3 — 암호화한 파일을 Git 저장소에 커밋하기
심정은 이해가 갑니다. 비밀 값은 팀이 찾을 수 있는 곳에 있어야 하고, 팀이 찾는 곳은 저장소이니, 암호화해서 커밋하면 되지 않느냐는 것이죠. 그런데 Git은 암호화된 덩어리가 가장 어울리지 않는 환경입니다.
Git은 파일의 버전마다 별도 객체로 저장하고, 객체들 사이의 유사성을 찾아 히스토리를 줄입니다. 공식 문서 표현으로는 각 객체를 정해진 윈도 안의 다른 객체들과 비교해 델타 압축으로 공간을 아낄 수 있는지 확인합니다. 그런데 암호문은 무작위 데이터와 구별되지 않도록 만들어진 것이라 찾을 유사성이 없습니다. 버전 사이에도, 다른 어디에도요. git-crypt의 README는 이걸 한 줄로 인정합니다. git-crypt로 암호화한 파일은 압축되지 않는다고요. 실제로는 그 파일을 건드리는 커밋마다 파일 크기 전체가 저장소에 영구히 더해지고, 클론하는 모든 사람이 그 무게를 같이 받습니다. GitHub의 대용량 파일 문서는 50MiB에서 경고하고 100MiB를 넘으면 아예 막으며, 저장소를 1GB 미만으로 유지하라고 권합니다. 매주 커밋되는 암호화 아카이브는 그 선을 생각보다 빨리 넘습니다.
Git을 쓰는 이유 자체도 사라집니다. diff에는 base64나 이진 잡음의 벽 두 개가 뜨니 리뷰는 눈을
감고 하는 셈이고 git log -p는 아무것도 알려 주지 않습니다. git blame은
책임을 물을 줄이 없고, 덩어리 안에서 난 병합 충돌은 해결할 수 없고 둘 중 하나를 고를 수만 있습니다.
git-crypt가 NearSeal과 정반대의 설계를 택한 이유가 여기 있습니다. git-crypt는 파일의 HMAC에서
유도한 합성 IV로 AES-256 CTR 모드 암호화를 하는데, Git이 파일 변경 여부를 판단할 수 있도록 일부러
결정적으로 만든 것입니다. 그 결정성에는 문서화된 대가가 따릅니다. 두 파일이 같은지 다른지 이상의
정보는 새지 않는다고 README는 적고 있는데, 뒤집으면 "같은지 다른지"는 샌다는 뜻이고, 버전 관리가
성립하려면 감수할 수밖에 없는 누출입니다. NearSeal은 반대로 매번 무작위 솔트와 IV를 씁니다. 인계에는
맞고 버전 관리에는 틀린 선택입니다.
사람들이 가장 많이 걸리는 함정은 암호화가 너무 늦게 도착한 경우입니다. 평문 비밀 값을 이미 한 번 커밋해서 푸시했다면, 나중 커밋에서 암호화해도 지켜지는 건 없습니다. 앞선 커밋이 히스토리에, 모든 클론에, 모든 포크에 그대로 남아 있기 때문입니다. GitHub의 안내는 순서를 분명히 합니다. 지워야 할 민감 정보가 비밀번호·토큰·자격증명 같은 비밀 값이라면 가장 먼저 그 값을 폐기하거나 교체해야 한다는 것, 그리고 그 커밋이 어느 포크에든 존재한다면 거기서는 계속 접근 가능한 상태로 남는다는 것입니다.
대신 무엇을 쓸 것인가. 자격증명이라면 답은 대개 "애초에 커밋하지 않는다"입니다.
.gitignore로 트리 밖에 두고, 실행 시점에 플랫폼의 비밀 저장소나 환경 설정에서 넘겨
주세요. 설정 파일에 비밀 값이 박혀 있는 경우처럼 정말로 암호화된 자료를 버전 관리해야 한다면,
불투명한 컨테이너를 손으로 저장소에 떨궈 넣는 대신 git-crypt처럼 그 일을 하도록 설계된 도구를
쓰는 편이 낫습니다.
NearSeal이 해 주지 못하는 것
저희가 만드는 도구의 한계를, 최대한 있는 그대로 적습니다.
암호를 잊으면 어떤 방식으로도 복구할 수 없습니다. 재설정 링크도, 고객지원 문의도, 백도어도, 마스터 키도 없고, "거의 맞았다"는 판정도 없습니다. 서버에 저장된 것이 없어서가 아니라 이 부분에 서버 자체가 없기 때문입니다. 키는 입력한 암호와 파일 안에 든 무작위 솔트에서 그때그때 유도되고, 암호가 틀리면 인증 검증이 실패할 뿐입니다. NIST는 이 규칙을 한 문장으로 씁니다. 키가 분실되거나 손상되면 암호화된 데이터를 복구하지 못할 수 있다고요. 암호는 만드는 그 순간에 비밀번호 관리자에 적어 두세요.
접근 권한을 회수하거나 교체하거나 만료시킬 수 없습니다. 사람별 키도 없고, 누가 무엇을 열었는지 기록도 없습니다. 한 번 알려진 암호는 알려진 것입니다.
이미 감염된 기기를 지켜 주지 못합니다. 키로거가 돌고 있으면 입력하는 순간 암호가 새고, 파일에 접근하는 악성코드가 있으면 암호화 전이나 복호화 후의 평문을 읽습니다. SP 800-111의 표현으로는, 사용자 기기가 어느 시점에든 침해되면 그 위의 저장 암호화 기술은 부분적으로 또는 전부 무력해질 수 있습니다.
약한 암호를 대신 구해 주지 못합니다. NearSeal 기본 형식은 암호를 PBKDF2-SHA256으로 220회 반복해 늘린 뒤에야 AES-256-GCM 키로 씁니다. 추측 한 번의 비용을 올려 주는 장치지만, 암호화 파일은 결국 파일일 뿐이라 사본을 가진 사람은 오프라인에서 잠금도 경보도 없이 얼마든지 계속 대입해 볼 수 있습니다. 여기서 효과가 큰 것은 복잡한 기호가 아니라 길이입니다.
파일 이름과 크기는 숨기지 못합니다. NearSeal 형식은 원래 파일 이름을 컨테이너 헤더에 평문으로 담습니다(형식 2판부터는 인증 태그에 묶여 있어 몰래 바꿀 수는 없지만, 비밀은 아닙니다). age 형식에는 파일 이름 항목 자체가 없어서 이름은 파일 바깥, 사용자가 붙여 둔 그 자리에 남습니다. SP 800-111도 정확히 이 점을 지적합니다. 파일 단위 암호화는 파일 이름과 그 밖의 메타데이터의 기밀성을 지켜 주지 못하며, 그 이름 자체가 공격자에게 값진 정보가 될 수 있다는 것입니다(문서가 주민등록번호 같은 식별 번호로 이름 붙어 있는 경우를 생각해 보세요).
그리고 디스크 암호화가 아닙니다. 건네준 사본을 암호화할 뿐, 끌어다 놓은 원본은 원래 있던 자리에 그대로 있고, 나중에 지운다고 해서 드라이브에서 그 바이트가 사라졌다고 보장되지도 않습니다. 그건 웹 페이지가 아니라 FileVault나 BitLocker의 일입니다.
짧게 정리하면
암호화는 인계용 도구입니다. 파일이 내 손을 안전하게 떠나게 만드는 데는 아주 뛰어나고, 파일이
머무는 동안 하는 거의 모든 일에는 서툽니다. 떠나는 파일이라면 — 첨부, 드라이브, 아카이브, 수리
보내는 기기 — 암호화하세요. NearSeal이 브라우저 안에서, 업로드도 계정도 없이 해 줍니다. 자체
AES-256-GCM 형식으로도, 공식 age·rage 도구에서 그대로 열리는 이식성 있는
age 형식으로도 가능합니다. 파일이 여기 사는 중이라면
디스크를 암호화하세요. 여러 사람과 사는 중이라면 권한을 쓰세요. 암호화 도구가 할 수 있는 정직한
권고는 "전부 암호화하라"가 아닙니다. "떠나는 것을 암호화하라, 그리고 암호가 사라지면 파일도 함께
사라진다는 것을 알고 하라"입니다.