해시와 암호화와 인코딩은 서로 다른 것이다
인코딩은 데이터가 어딘가를 지나갈 수 있게 모양을 바꾸는 것이다. 키가 없고 누구나 되돌릴 수 있다. 암호화는 키를 가진 사람만 읽을 수 있게 바꾸는 것이다. 그 사람이 되돌리라고 만든 것이다. 해시는 되돌릴 수 없는 고정 길이의 지문을 만드는 것이다. 만든 사람도 되돌릴 수 없다. 셋이 헷갈리는 이유는 전부 읽히는 글자를 안 읽히는 글자로 바꾸기 때문이다 — 하지만 그중 무언가를 보호하는 것은 하나뿐이고, 되돌리라고 만든 것도 하나뿐이다.
인코딩 — 모양을 바꾸는 일
Base64, URL 퍼센트 인코딩, 16진수가 인코딩이다. 제한된 문자만 받는 통로 — 이메일 본문, URL, HTTP 헤더 — 로 임의의 바이트를 지나가게 하는 것이 일이다. 키가 없고, 변환 방식이 공개돼 있고, 되돌리는 것은 함수 호출 한 번이다.
그래서 Base64 를 "암호화"라고 부르는 것은 살짝 부정확한 게 아니라 사실의 반대다. 그 문자열을 본 사람은 누구나 읽는다. Base64 로 저장한 비밀번호는 단계만 하나 더 있는 평문 비밀번호이고, 데이터베이스를 처음 들여다본 사람이 읽는다.
암호화 — 키를 가진 사람만 되돌린다
암호화는 맞는 키를 가진 사람만 되찾을 수 있게 데이터를 바꾼다. 그게 요점 전부다 — 데이터가 나중에, 맞는 사람에게, 돌아오라고 만든 것이다. 저장된 파일을 지키는 AES 도, 오가는 요청을 지키는 TLS 도 이것이다.
설계부터 되돌릴 수 있으므로, 데이터가 다시 읽혀야 하는 자리에는 암호화가 맞다. 나중에 보낼 액세스 토큰, 내일 사용자가 열 문서, 보여주려면 풀어야 하는 필드.
해시 — 한 방향의 지문
해시 함수는 어떤 입력이든 고정된 크기의 값으로 바꾼다. 결과 안에 입력이 들어 있지 않으므로 되돌릴 대상이 없다 — 키로도, 계산을 더 해서도, 함수를 만든 사람도 못 한다. SHA-256 은 입력이 한 글자든 1기가바이트든 32바이트를 준다.
그 성질이 해시를 실제 쓰임 두 가지에 맞게 만든다. 데이터가 바뀌지 않고 도착했는지 확인하는 것, 그리고 두 값을 저장하지 않고 비교하는 것. 비밀번호 확인이 그렇게 동작한다 — 시스템은 해시를 저장하고, 입력받은 것을 해시해서, 비교한다.
해시를 "복호화"해 준다는 사이트는 이미 계산해 둔 입력들의 표에서 값을 찾는 것이다. 흔한 비밀번호에는 통하고 무작위 값에는 결코 통하지 않는다. 솔트를 쓰는 이유가 정확히 이것이다 — 솔트가 붙으면 저장된 해시마다 입력이 달라져서 미리 만든 표가 쓸모없어진다.
셋이 뒤섞이는 자리
JWT 가 가장 분명한 예다. 헤더와 페이로드는 Base64url 로 인코딩된 것이지 암호화된 것이 아니라, 토큰을 가진 사람은 누구나 안의 모든 클레임을 읽는다. 서명은 키를 쓴 해시라서 토큰이 바뀌지 않았음을 증명할 뿐 아무것도 감추지 않는다. "암호화된 것처럼 보인다"는 이유로 개인정보를 JWT 페이로드에 넣으면 그 토큰을 받는 모두에게 그것을 공개하는 것이다.
또 하나 잦은 혼동은 비밀번호에 빠른 해시를 쓰는 것이다. SHA-256 은 좋은 해시이고 나쁜 비밀번호 저장소다. 체크섬에 쓸모 있게 만드는 그 속도가, 공격자가 수십억 번 시도하게 해 주는 바로 그 성질이기 때문이다. 비밀번호 해시는 일부러 느리다 — Argon2id·scrypt·bcrypt.
관련 도구
이 도구가 따르는 규격
- RFC 4648 — Base16·Base32·Base64 데이터 인코딩 — 이 인코딩들을 정의하고, 보호가 아니라 인코딩이라고 적어 둔 곳.
- RFC 7519 §11 — JWT 보안 고려사항 — 서명된 JWT 가 가진 사람에게 아무것도 감추지 않는 이유.
- OWASP — 비밀번호 저장 치트시트 — 빠른 해시가 비밀번호에 틀린 연장인 이유와 대신 쓸 것.
- NIST FIPS 180-4 — 안전 해시 표준 — SHA 계열의 정의와 단방향 성질.
고친 날 2026-09-05