Python - 14. 보안과 암호화

2025. 1. 20. 01:00프로그래밍 언어/Python

Python에서는 보안과 암호화를 다루기 위한 다양한 도구와 라이브러리를 제공합니다. 안전한 애플리케이션을 개발하기 위해 필수적인 해시 함수, 암호화와 복호화, 패스워드 처리, 그리고 API 키 관리 방법을 살펴보겠습니다.


14.1 해시 함수

해시 함수란?

해시 함수는 임의의 데이터를 고정된 크기의 고유한 해시 값으로 변환합니다. 해시 함수는 암호화된 데이터 비교, 무결성 검증, 데이터베이스 키 생성 등에 사용됩니다.

주요 해시 알고리즘

  • SHA-256: 강력한 보안 수준을 제공하며, 일반적으로 추천되는 해시 알고리즘
  • MD5: 빠르지만 보안 취약점으로 인해 암호화 용도로는 비추천
  • SHA-1: SHA-256보다 빠르지만, 충돌 공격에 취약

Python의 hashlib 모듈

hashlib 모듈을 사용하여 다양한 해시 알고리즘을 구현할 수 있습니다.

import hashlib

# SHA-256 해시 생성
message = "Secure Message"
hash_object = hashlib.sha256(message.encode())
hash_hex = hash_object.hexdigest()
print(f"SHA-256: {hash_hex}")

# MD5 해시 생성 (사용 비추천: 보안 취약)
hash_object_md5 = hashlib.md5(message.encode())
print(f"MD5: {hash_object_md5.hexdigest()}")

Salt와 Pepper 개념

  • Salt: 각 데이터에 고유의 랜덤 값을 추가하여 동일 데이터의 해시값 충돌을 방지
  • Pepper: 애플리케이션 레벨에서 추가로 사용하는 고정 비밀값

14.2 암호화와 복호화

대칭 키 암호화

대칭 키 암호화는 동일한 키로 데이터를 암호화하고 복호화합니다. Python에서는 cryptography 라이브러리를 활용할 수 있습니다.

설치

pip install cryptography

예제: 대칭 키 암호화

from cryptography.fernet import Fernet

# 키 생성
key = Fernet.generate_key()
cipher = Fernet(key)

# 암호화
plaintext = "Sensitive Data"
encrypted = cipher.encrypt(plaintext.encode())
print(f"Encrypted: {encrypted}")

# 복호화
decrypted = cipher.decrypt(encrypted).decode()
print(f"Decrypted: {decrypted}")

SSL/TLS 기본 사용법

SSL/TLS를 활용하여 데이터 전송 중 보안을 강화할 수 있습니다.

import ssl
import socket

context = ssl.create_default_context()
with socket.create_connection(("www.example.com", 443)) as sock:
    with context.wrap_socket(sock, server_hostname="www.example.com") as ssock:
        print(ssock.version())

14.3 안전한 패스워드 처리

패스워드 해싱

패스워드를 안전하게 저장하기 위해 해싱을 사용합니다. bcrypt 라이브러리는 강력한 패스워드 해싱을 제공합니다.

설치

pip install bcrypt

패스워드 해싱과 검증

import bcrypt

# 패스워드 해싱
password = "my_secure_password".encode()
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
print(f"Hashed: {hashed}")

# 패스워드 검증
is_valid = bcrypt.checkpw(password, hashed)
print(f"Password Valid: {is_valid}")

14.4 API 키와 시크릿 관리

API 키와 시크릿 관리의 중요성

API 키와 시크릿은 외부 서비스와 통신할 때 인증을 위해 사용됩니다. 이를 안전하게 보호해야 합니다.

안전한 관리 방법

  1. 환경 변수 사용
    • os.environ을 사용하여 환경 변수에서 키를 읽어옵니다.
import os

api_key = os.getenv("API_KEY")
print(f"API Key: {api_key}")
  1. .env 파일 관리
    • python-dotenv 라이브러리를 사용하여 .env 파일에서 환경 변수를 로드합니다.

설치

pip install python-dotenv

.env 파일 예제

API_KEY=your_api_key_here

코드에서 사용

from dotenv import load_dotenv
import os

load_dotenv()
api_key = os.getenv("API_KEY")
print(f"Loaded API Key: {api_key}")
  1. Secrets Manager 사용
    • 클라우드 제공자의 Secrets Manager 서비스를 활용하여 키를 안전하게 관리합니다.

14.5 구체적 보안 사례

SQL 인젝션 방지

  • 사용자 입력값을 직접 SQL에 포함하지 않고, 파라미터화된 쿼리를 사용합니다.
import sqlite3

conn = sqlite3.connect('example.db')
cursor = conn.cursor()

username = "admin"
query = "SELECT * FROM users WHERE username = ?"
cursor.execute(query, (username,))

XSS 방지

  • 사용자 입력값을 HTML로 렌더링하기 전에 이스케이프 처리합니다.
from html import escape

user_input = "<script>alert('XSS')</script>"
safe_input = escape(user_input)
print(f"Safe Output: {safe_input}")

CSRF 방지

  • CSRF 토큰을 생성하고, 요청 시 검증합니다.
import secrets

def generate_csrf_token():
    return secrets.token_hex(16)

csrf_token = generate_csrf_token()
print(f"CSRF Token: {csrf_token}")

14.6 모범 사례

보안 체크리스트

  1. 최신 보안 패치 적용
  2. 민감한 데이터 암호화
  3. 강력한 인증 및 접근 제어
  4. 최소 권한 원칙 적용

로깅과 모니터링

  • 중요한 이벤트를 로깅하고 비정상적인 활동을 모니터링합니다.
import logging

logging.basicConfig(level=logging.INFO)
logging.info("Application started")

에러 처리 보안

  • 사용자에게 과도한 오류 정보를 노출하지 않도록 합니다.
try:
    result = 10 / 0
except ZeroDivisionError:
    print("An error occurred. Please try again later.")

이번 섹션에서는 보안과 암호화를 위한 핵심 기법을 다뤘습니다.