가이드

developer

Base64는 암호화가 아니다: 인코딩, 해시, 암호화의 차이

Base64로 바꾼 비밀번호는 누구나 되돌릴 수 있습니다. Base64와 SHA-256 해시, 암호화가 각각 무엇을 위한 도구인지 한글 예시와 함께 정리합니다.

modu.tools Editorial · ·

비밀번호나 API 키를 Base64로 바꿔 저장해 놓고 “암호화했다”고 적어 둔 코드를 가끔 봅니다. 결과가 알아볼 수 없는 문자열이라 안전해 보이지만, Base64는 누구나 같은 방법으로 즉시 되돌릴 수 있는 변환입니다. 이 글은 겉보기에 비슷한 인코딩, 해시, 암호화가 무엇이 다른지, 각각 언제 써야 하는지 정리합니다.

한눈에 비교

구분 되돌릴 수 있나 열쇠가 필요한가 목적
인코딩(Base64) 예, 누구나 아니요 데이터를 다른 형식으로 옮기기
해시(SHA-256) 아니요 아니요 같은 데이터인지 확인하기
암호화(AES 등) 예, 열쇠가 있으면 예 허락된 사람만 읽게 하기

Base64: 바이너리를 글자로 옮기기

Base64는 RFC 4648에 정의된 인코딩으로, 임의의 바이트를 영문 대소문자, 숫자, +, /의 64개 문자로 표현합니다. 이메일 첨부 파일, 데이터 URL 속 이미지, JSON 안의 바이너리처럼 텍스트만 다룰 수 있는 곳에 바이너리를 싣기 위해 만들어졌습니다.

3바이트(24비트)를 6비트씩 네 덩어리로 나눠 각각을 한 문자로 바꾸기 때문에 결과는 원본보다 약 33% 커집니다. 길이가 3의 배수가 아니면 끝에 =를 붙여 맞춥니다.

  • modu → bW9kdQ== (4바이트라 = 두 개)
  • 한글 → 7ZWc6riA (UTF-8로 6바이트라 패딩 없음)

’한글’은 두 글자지만 UTF-8에서 6바이트라 결과가 8글자입니다. 같은 ’한글’을 CP949 바이트로 바꾸면 전혀 다른 결과가 나오므로, 한글을 Base64로 바꿀 때는 어떤 인코딩으로 바이트를 만들었는지가 중요합니다. 자세한 차이는 한글 바이트 가이드에 있습니다.

URL에는 base64url

표준 Base64의 +와 /는 URL에서 특별한 의미가 있습니다. 그래서 RFC 4648은 이 둘을 -와 _로 바꾼 base64url 변형도 정의합니다. JWT가 이 방식을 씁니다. 표준 Base64를 URL에 그대로 넣으면 +가 공백으로 해석될 수 있으니 주의하세요. URL 인코딩 가이드에서 이 문제를 더 다룹니다.

해시: 되돌릴 수 없는 지문

해시 함수는 어떤 길이의 데이터든 정해진 길이의 값으로 바꿉니다. NIST FIPS 180-4에 정의된 SHA-256은 결과가 항상 256비트, 16진수 64글자입니다.

  • modu → 4de5202b10845b93ab7b3c3782cbe719713d2b60113a0390b78ed73ebbed1de1
  • modv → 81b4031909a37bcdc6b9ba2eacc6075ff4967c70ac681aa675fa49fa0f4a6340

한 글자만 달라도 결과가 완전히 바뀌고, 결과에서 입력을 거꾸로 계산할 수 없습니다. 그래서 해시는 이런 데 씁니다.

  • 무결성 확인: 내려받은 파일의 SHA-256이 배포처가 공개한 값과 같으면 파일이 바뀌지 않은 것입니다.
  • 중복 찾기: 내용이 같으면 해시도 같으니, 큰 파일 대신 해시만 비교합니다.
  • 캐시 관리: 정적 파일 이름에 내용 해시를 붙이면 내용이 바뀔 때 이름도 바뀝니다.

MD5와 SHA-1은 보안 용도에서 빼기

MD5는 서로 다른 두 입력이 같은 해시를 갖게 만드는 충돌 공격이 실제로 가능합니다. RFC 6151은 디지털 서명처럼 충돌 저항성이 필요한 곳에 MD5를 쓰지 말라고 권고합니다. SHA-1도 같은 이유로 보안 용도에서 물러나는 추세입니다. 단순한 오류 검출에는 아직 쓰이지만, 위조를 막아야 하는 곳에서는 SHA-256 이상을 쓰세요.

비밀번호를 SHA-256만으로 저장하면 안 되는 이유

SHA-256은 빠르도록 설계되었습니다. 공격자가 흔한 비밀번호 수십억 개의 해시를 미리 계산해 두면 저장된 해시와 비교만 해도 비밀번호를 알아낼 수 있습니다. 그래서 비밀번호는 사용자마다 다른 무작위 값(솔트)을 섞고, 일부러 느리게 만든 전용 함수인 bcrypt, scrypt, Argon2 같은 것으로 저장하는 것이 표준입니다.

암호화: 열쇠가 있어야 읽힌다

암호화는 열쇠를 가진 사람만 원래 데이터를 되돌릴 수 있게 합니다. 같은 열쇠로 잠그고 여는 대칭키 방식(AES 등)과, 공개키로 잠그고 개인키로 여는 공개키 방식이 있습니다. API 키나 개인정보처럼 나중에 원래 값이 필요하지만 아무나 읽으면 안 되는 데이터에 씁니다.

암호화 결과는 바이너리라서 JSON이나 설정 파일에 넣을 때 다시 Base64로 인코딩하는 경우가 많습니다. “암호화 후 Base64”는 맞는 조합이고, “Base64만”은 암호화가 아닙니다.

상황별 선택

하고 싶은 일 알맞은 도구
이미지를 JSON에 넣어 보내기 Base64
다운로드 파일 변조 확인 SHA-256
사용자 비밀번호 저장 bcrypt, scrypt, Argon2
API 키 보관 암호화 또는 비밀 관리 서비스
URL에 짧은 토큰 넣기 base64url

실제로 자주 보는 실수

설정 파일의 Base64 “비밀”. 쿠버네티스 시크릿처럼 값을 Base64로 적는 형식이 있습니다. 이건 YAML에 바이너리를 안전하게 담으려는 것이지 숨기려는 것이 아닙니다. 그 파일을 읽을 수 있는 사람은 값도 읽을 수 있다고 생각해야 합니다.

해시를 비교할 때 줄바꿈. 터미널에서 echo로 문자열을 넘기면 끝에 줄바꿈이 붙어서 해시가 달라집니다. 웹 도구와 터미널 결과가 다르면 먼저 줄바꿈을 의심하세요.

토큰 길이 계산. 32바이트 무작위 값을 Base64로 바꾸면 44글자(패딩 포함), 16진수로 바꾸면 64글자입니다. 데이터베이스 컬럼 길이를 정할 때 원본 바이트가 아니라 인코딩 후 길이를 기준으로 해야 합니다.

modu.tools의 데이터 워크벤치에서 Base64와 SHA-256을 브라우저 안에서 바로 확인할 수 있습니다. 입력값은 서버로 전송되지 않지만, 실제 비밀번호나 운영 키는 어떤 온라인 도구에도 붙여 넣지 않는 습관을 권합니다.

같은 입력으로 직접 비교해 보기

같은 문자열 modu를 세 방식으로 처리하면 성격 차이가 한눈에 드러납니다.

방식 결과(요약) 되돌리기 길이 변화
Base64 bW9kdQ== 가능(디코딩) 3바이트 → 4글자(+패딩)
SHA-256(16진수) 64글자 고정 불가능 입력이 짧아도 출력 길이 고정
AES 같은 암호화 키에 따라 달라짐 키 있으면 가능 블록·IV에 따라 늘어남

Base64는 표현만 바꾼 것이고, 해시는 요약한 지문이며, 암호화는 비밀을 유지한 채 보관하는 도구입니다. ’난독화’라는 말로 셋을 섞어 부르면 설계 사고가 납니다.

Base64 길이 계산식

입력이 (n)바이트일 때 패딩 포함 Base64 길이는 (4 \times \lceil n/3 \rceil)입니다.

원본 바이트 Base64 길이 예
1 4 (xx==) YQ== ← a
2 4 (xxx=) YWI= ← ab
3 4 YWJj ← abc
16 24 짧은 API 토큰 원본
32 44 흔한 랜덤 시크릿

한글 모듈은 UTF-8로 6바이트라 Base64로 8글자(66y47J6s)가 됩니다. 데이터베이스 컬럼을 VARCHAR(32)로 잡았다면 원본 24바이트까지만 안전합니다.

해시 값을 비교할 때 체크리스트

  1. 인코딩을 맞춘다. 같은 한글이라도 UTF-8과 CP949의 바이트가 다르면 해시가 다릅니다.
  2. 줄바꿈을 확인한다. echo는 기본적으로 LF를 붙이고, echo -n은 붙이지 않습니다.
  3. 대소문자 정규화. 16진수는 대·소문자만 다른 경우가 많습니다. 비교 전에 소문자로 통일하세요.
  4. 알고리즘 이름을 적는다. sha256:…처럼 접두를 두면 MD5 결과와 섞이지 않습니다.
  5. 보안 비교는 상수 시간. 비밀번호 검증처럼 공격 표면이 있는 비교는 단순 문자열 ===보다 상수 시간 비교를 씁니다.

언제 워크벤치를 쓰고, 언제 쓰면 안 되나

브라우저 안 도구는 공개해도 되는 샘플, 문서화용 예시, 파일 무결성 확인용 해시 재현에 적합합니다. 운영 중인 비밀번호, 결제 키, 고객 개인정보가 들어간 문자열은 붙여 넣지 마세요. 로컬이라도 화면 공유·브라우저 확장·히스토리에 남을 수 있습니다.

파일 다운로드 페이지가 SHA-256을 공개했다면, 받은 파일을 로컬에서 해시한 뒤 공개 값과 비교하는 것이 정상 절차입니다. 값이 다르면 다시 받거나 미러를 바꾸세요.

자주 묻는 질문

Base64 끝의 =는 지워도 되나요? RFC 4648은 패딩을 기본으로 하되, 길이를 따로 알 수 있으면 생략을 허용합니다. JWT는 패딩을 생략합니다.

해시가 대문자와 소문자로 다르게 나와요. 16진수 표기 차이일 뿐 같은 값입니다.

같은 문자열인데 해시가 달라요. 끝의 줄바꿈이나 공백, 또는 UTF-8과 CP949 같은 인코딩 차이가 원인인 경우가 대부분입니다.