소개
다중 인증 (Multi-factor authentication, MFA) 은 두 가지 이상의 증명 방식을 요구함으로써 계정 탈취 위험을 줄여줍니다. 비밀번호는 사용자가 '알고 있는 것'에 해당합니다. 두 번째 요소는 별도의 장치, 앱, 파일 또는 하드웨어 토큰에서 생성된 코드일 수 있습니다.
이 실습에서는 비밀번호만 사용하는 Python 로그인 스크립트로 시작하여 간단한 두 번째 인증 요소를 추가해 봅니다. 실습을 초보자도 이해하기 쉽고 결과가 명확하도록 만들기 위해, 두 번째 요소로는 보호된 비밀 파일에서 생성된 HMAC 기반 코드를 사용합니다.
비밀번호 전용 로그인 테스트
이 단계에서는 시작용 로그인 스크립트를 실행합니다. 이 스크립트는 사용자 이름과 비밀번호만 확인하는데, 이는 사용자가 알고 있는 정보만 증명으로 사용하므로 단일 요소 인증에 해당합니다.
프로젝트 디렉토리로 이동합니다:
cd /home/labex/project
준비된 파일들을 확인합니다:
ls -l
사용자 데이터베이스를 확인합니다:
cat users.json
비밀번호 전용 로그인을 성공적으로 수행합니다:
python3 login.py alice wonderland
출력 결과는 다음과 같아야 합니다:
login ok
이제 잘못된 비밀번호를 입력해 봅니다:
python3 login.py alice wrong
이 명령은 login failed를 출력해야 합니다. 로그인 실패 시 0 이 아닌 상태 코드로 종료되는데, 이는 이 테스트에서 정상적인 동작입니다.
시작 상태에 대한 검사기를 실행합니다:
python3 mfa-check.py password-only
예상 결과는 다음과 같습니다:
password-only: complete
2 단계 인증 비밀값 생성
이 단계에서는 두 번째 인증 요소를 위한 별도의 비밀값을 생성합니다. 실제 MFA 시스템에서는 이 비밀값이 인증 앱이나 하드웨어 토큰에 저장될 수 있습니다. 이 실습에서는 동작을 쉽게 확인하고 검증할 수 있도록 로컬 파일로 저장합니다.
비밀값을 생성합니다:
printf 'labex-mfa-secret-2026\n' > mfa_secret.txt
소유자만 읽고 쓸 수 있도록 파일 권한을 제한합니다:
chmod 600 mfa_secret.txt
권한을 확인합니다:
ls -l mfa_secret.txt
권한 비트가 -rw-------로 시작해야 합니다:
-rw------- ... mfa_secret.txt
비밀값에 대한 검사기를 실행합니다:
python3 mfa-check.py secret
예상 결과는 다음과 같습니다:
secret: complete
로그인 코드 생성
이 단계에서는 간단한 코드 생성기를 만듭니다. HMAC-SHA256 을 사용하여 비밀 파일과 사용자 이름을 결합합니다. HMAC 을 사용하는 이유는 동일한 입력과 비밀값으로 동일한 짧은 코드를 생성할 수 있으면서도, 비밀값을 모르는 사람은 코드를 쉽게 생성할 수 없기 때문입니다.
generate-code.py를 생성합니다:
cat > generate-code.py <<'PY'
#!/usr/bin/env python3
import hmac
import hashlib
import sys
from pathlib import Path
if len(sys.argv) != 2:
print("usage: generate-code.py USERNAME")
raise SystemExit(2)
username = sys.argv[1]
secret = Path("mfa_secret.txt").read_text().strip().encode()
digest = hmac.new(secret, username.encode(), hashlib.sha256).hexdigest()
print(digest[:6])
PY
실행 권한을 부여합니다:
chmod +x generate-code.py
alice에 대한 코드를 생성합니다:
python3 generate-code.py alice
다음과 같은 6 자리 코드가 출력되어야 합니다:
21f18f
생성기에 대한 검사기를 실행합니다:
python3 mfa-check.py generator
예상 결과는 다음과 같습니다:
generator: complete
2 단계 인증 적용
이 단계에서는 로그인 스크립트를 교체하여 비밀번호와 생성된 코드를 모두 요구하도록 변경합니다. 이것이 MFA 의 핵심 변경 사항입니다. 이제 비밀번호만으로는 로그인이 불가능합니다.
login.py를 MFA 가 적용된 버전으로 교체합니다:
cat > login.py <<'PY'
#!/usr/bin/env python3
import hmac
import hashlib
import json
import sys
from pathlib import Path
USERS = Path("users.json")
SECRET = Path("mfa_secret.txt")
def expected_code(username):
secret = SECRET.read_text().strip().encode()
digest = hmac.new(secret, username.encode(), hashlib.sha256).hexdigest()
return digest[:6]
def main():
if len(sys.argv) != 4:
print("usage: login.py USERNAME PASSWORD MFA_CODE")
return 2
username, password, code = sys.argv[1], sys.argv[2], sys.argv[3]
users = json.loads(USERS.read_text())
if users.get(username, {}).get("password") != password:
print("login failed")
return 1
if not hmac.compare_digest(code, expected_code(username)):
print("mfa failed")
return 1
print("login ok")
return 0
if __name__ == "__main__":
raise SystemExit(main())
PY
스크립트에 실행 권한이 있는지 확인합니다:
chmod +x login.py
새로운 코드를 생성하여 셸 변수에 저장합니다:
CODE="$(python3 generate-code.py alice)"
올바른 비밀번호와 코드를 함께 사용하여 로그인합니다:
python3 login.py alice wonderland "$CODE"
출력 결과는 다음과 같아야 합니다:
login ok
MFA 적용 여부를 확인하는 검사기를 실행합니다:
python3 mfa-check.py enforced
예상 결과는 다음과 같습니다:
enforced: complete
MFA 실패 및 성공 테스트
이 단계에서는 최종 로그인 동작을 테스트합니다. 두 번째 요소 없이 올바른 비밀번호만 입력하면 실패해야 하고, 잘못된 코드를 입력해도 실패해야 하며, 올바른 비밀번호와 코드를 모두 입력해야만 성공해야 합니다.
먼저, 이전의 비밀번호 전용 명령을 시도해 봅니다:
python3 login.py alice wonderland || true
MFA 코드가 누락되었으므로 새로운 사용법 메시지가 출력되어야 합니다:
usage: login.py USERNAME PASSWORD MFA_CODE
잘못된 코드를 입력해 봅니다:
python3 login.py alice wonderland 000000 || true
출력 결과는 다음과 같아야 합니다:
mfa failed
올바른 코드를 생성하여 로그인합니다:
CODE="$(python3 generate-code.py alice)"
python3 login.py alice wonderland "$CODE"
출력 결과는 다음과 같아야 합니다:
login ok
전체 검사기를 실행합니다:
python3 mfa-check.py all
최종 출력은 모든 MFA 구성 요소가 완료되었음을 보여주어야 합니다:
secret: complete
generator: complete
enforced: complete
요약
비밀번호 전용 로그인 스크립트를 간단한 다중 인증 로그인 흐름으로 변경했습니다. 별도의 MFA 비밀값을 생성하고, HMAC 기반 코드를 생성하며, 로그인 스크립트에서 해당 코드를 요구하도록 설정하고, 실패 및 성공 사례를 모두 테스트했습니다.
보안의 핵심은 독립적인 두 번째 증명이 요구될 때, 비밀번호가 탈취되더라도 그것만으로는 충분하지 않게 만드는 것입니다.



