본문 바로가기
C.W.K.
Stream
Lesson 06 of 06 · published

random·secrets·hashlib·uuid — 우연과 식별의 경계

~18 min · random, hashlib, uuid, secrets

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

예측돼도 되는 난수와 안 되는 난수

random은 게임·모의실험·표본에 맞고 seed로 재현할 수 있어. 토큰·비밀번호 재설정·CSRF처럼 공격자가 예측하면 안 되는 값은 운영체제 난수를 쓰는 secrets로 만들어.

해시는 bytes의 지문이야

문자열은 먼저 인코딩하고 보통 SHA-256을 써. MD5와 SHA-1은 충돌 저항이 필요한 보안 경계에 쓰지 마. 해시는 암호화가 아니어서 원문 비밀을 보장하지 않아.

UUID는 충돌 가능성이 매우 낮은 식별자

일반적인 무작위 식별에는 UUID4를 써. UUID1은 시간과 MAC 정보를 담아 노출할 수 있으므로 특별한 이유가 없다면 피해.

Code

모의실험에 쓰는 random·python
import random

random.seed(42)                       # 재현 가능
print(random.random())                # 0.6394...
print(random.randint(1, 100))         # 71

fruits = ["apple", "banana", "cherry", "date"]
print(random.choice(fruits))          # 'apple' (seed 42)
print(random.sample(fruits, 2))       # ['banana', 'cherry']
random.shuffle(fruits)
print(fruits)                         # 랜덤 순서

# 분포
print(random.gauss(0, 1))             # 정규분포
print(random.uniform(10, 20))         # 균등분포
보안 경계의 secrets·python
import secrets

# 토큰 생성
print(secrets.token_hex(16))          # 32-글자 hex (16 바이트)
print(secrets.token_urlsafe(32))      # URL-safe base64
print(secrets.token_bytes(8))         # 8 랜덤 바이트

# 랜덤 선택 (cryptographically)
print(secrets.choice(["a", "b", "c"]))

# 비교 — 같은 모양에 random vs secrets
import random
print("random:", random.randint(1, 100))      # seed 알면 예측 가능
print("secrets:", secrets.randbelow(100))     # 예측 불가

# secrets 사용처 — 세션 토큰, 비밀번호 reset, API 키.
# random 사용처 — 테스트 데이터 셔플, 샘플 뽑기, 시뮬레이션.
bytes를 SHA-256으로 해시하기·python
import hashlib

# SHA-256 이 일상 디폴트
data = b"hello world"
h = hashlib.sha256(data)
print(h.hexdigest())                  # 'b94d27b9934d3e08a52e52d7da7dab...'
print(h.digest())                     # raw bytes

# chunk 로 파일 해싱 (큰 파일 streaming)
import pathlib
p = pathlib.Path("/etc/hostname")
h = hashlib.sha256()
with p.open("rb") as f:
    while chunk := f.read(8192):
        h.update(chunk)
print(h.hexdigest())

# 문자열 해싱 — bytes 로 인코드 먼저
h = hashlib.sha256("안녕".encode("utf-8")).hexdigest()
print(h)
UUID4 식별자 만들기·python
import uuid

# uuid4 — 랜덤, 일상 선택
print(uuid.uuid4())                   # ad8a0a2c-...
print(str(uuid.uuid4()))              # 표준 hyphen 문자열

# uuid1 — MAC + 시간 기반 (둘 다 leak — 보통 안 원함)
# uuid3, uuid5 — namespaced (같은 이름이면 deterministic)

# 흔한 사용 — 데이터베이스 랜덤 ID
records = [{"id": str(uuid.uuid4()), "data": x} for x in ["a", "b", "c"]]
for r in records:
    print(r)
shutil로 고수준 파일 작업하기·python
import shutil
import tempfile
from pathlib import Path

# 복사
src = Path("/etc/hostname")
dst = Path("/tmp/hostname-copy")
shutil.copy(src, dst)
print(dst.read_text(encoding="utf-8"))
dst.unlink()

# 이동 (rename)
f = Path("/tmp/source.txt")
f.write_text("hi", encoding="utf-8")
shutil.move(str(f), "/tmp/dest.txt")
Path("/tmp/dest.txt").unlink()

# 디렉토리 트리 제거 (재귀)
with tempfile.TemporaryDirectory() as td:
    sub = Path(td) / "nested" / "deeper"
    sub.mkdir(parents=True)
    (sub / "file.txt").write_text("hi", encoding="utf-8")
    # shutil.rmtree(td)  — 어쨌든 컨텍스트 종료 시 일어남

# 터미널 크기, 빈 디스크 공간
print(shutil.get_terminal_size())
print(shutil.disk_usage("/"))

External links

Exercise

token_urlsafe(24)로 세 토큰을 만들고, '피파, 안녕'을 UTF-8 bytes로 바꿔 SHA-256을 계산해. UUID4를 임시 파일 이름 뒤에 붙이고 shutil.disk_usage('/')의 빈 공간을 GB로 표시해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.