OkBublewrap

🔒 암호화 본문

Python/학습용

🔒 암호화

옥뽁뽁 2025. 4. 19. 10:52

정규 표현식

  • 정규표현식은 복잡한 문자열을 처리할 때 사용하는 기법으로 문자열을 처리해야 하는 다양한 상황에서 활용됨
  • 파이썬 정규 표현식은 re 표준 라이브러리를 사용
import re

pattern = r"패턴"
re.search(pattern, string)  # 일치하는 첫 부분을 찾음
re.match(pattern, string)   # 문자열 시작부터 일치하는지 확인
re.findall(pattern, string) # 일치하는 모든 부분을 리스트로 반환
re.sub(pattern, repl, string)  # 일치하는 부분을 치환
패턴 설명 예시
. 임의의 한 문자 a.c → abc, acc
^ 문자열의 시작 ^a → abc에서 a로 시작하는 것
$ 문자열의 끝 z$ → xyz에서 z로 끝나는 것
* 0회 이상 반복 bo* → b, bo, boo, booo
+ 1회 이상 반복 bo+ → bo, boo (b는 X)
? 0회 또는 1회 ab?c → ac, abc
{m} 정확히 m회 반복 a{3} → aaa
{m,n} m~n회 반복 a{2,4} → aa, aaa, aaaa
[] 문자 집합 [abc] → a, b, 또는 c
[^abc] 제외 문자 집합 a, b, c 제외
\d 숫자 [0-9] \d+ → 숫자 하나 이상
\D 숫자가 아닌 것
\w 단어 문자 (알파벳+숫자+_)
\W 단어 문자가 아닌 것
\s 공백 문자
\S 공백이 아닌 문자
` ` OR 조건
() 그룹핑 (ab)+ → ab, abab, ababab

숫자만 추출

numbers = re.findall(r"\\d+", text)  
print(numbers) # ['010', '1234', '5678']

전화번호 패턴 찾기

match = re.search(r"\\d{3}-\\d{4}-\\d{4}", text)

if match:  
print(match.group()) # 010-1234-5678

이메일 치환

email = "[user@example.com](mailto:user@example.com)"  
masked = re.sub(r"@.\*", "@****", email)  
print(masked) # user@****
### 예제2
개인정보가 포함된 문서에서 주민번호 뒷자리를 `*******` 로 마스킹하고자 할 때

# 개인 정보 목록
personal_info = '''
김미키 010-3344-5566 Mike@google.com 800905-1033451
김소은 010-5032-1111 Soeun@naver.com 700905-2134567
유한슬 010-2789-1476 Lyu@school.ac.com 931222-1234567
박민철 010 4040 1313 Zoe@school.ac.com 830810-1234567
이민아 010-7777-2222 Kate@google.com 960711-2434567

방법1: 정규 표현식을 사용하지 않을 경우

  1. 공백 문자를 기준으로 전체 텍스트를 나눈다(split() 함수 사용)
  2. 나눈 단어가 주민 등록 번호 형식인지 조사한다.
  3. 주민 등록 번호 형식이라면 뒷자리를 ***로 마스킹한다
  4. 나눈 단어를 다시 조립한다.
result = []
for line in personal_info.split("\n"):            # 텍스트를 줄 단위로 분리
    word_result = []

    for word in line.split(" "):                  # 각 줄을 단어 단위로 분리
        if len(word) == 14 and word[:6].isdigit() and word[7:].isdigit():
            # 조건: 총 14자이고, 앞 6자리 숫자 + 뒤 7자리 숫자인 경우 (00000000000000)
            word = word[:6] + "-" + "*******"     # → 000000-*******
        word_result.append(word)

    result.append(" ".join(word_result))          # 마스킹한 단어들 다시 줄로 합침

print("\n".join(result))                          # 전체 줄 출력

방법2: 정규 표현식을 사용할 경우

import re
pat = re.compile("(\d{6})[-]\d{7}")
print(pat.sub("\g<1>-*******", personal_info)) # g<1> : 주민번호 앞부분 그룹을 의미

비밀번호 감추기

getpass

  • getpass는 사용자가 비밀번호를 입력할 때 이를 화면에 노출하지 않도록 해주는 모듈

비밀번호 잠금 해제 예제

# 원본 비밀번호
passwd = 'abcdefg1234'

# 사용자 입력 비밀번호
user_input = input("비밀번호를 입력하세요 >>> ")

while user_input != passwd:
    # 비밀번호 불일치 메세지
    user_input = input("잘못된 비밀번호 입니다! 다시 입력해주세요 >>>")

print('잠금이 해제되었습니다 !')
print('''
▒▒▒▒▒▒▒▒▒▒▒▒
▒▒▒▒▓▒▒▓▒▒▒▒
▒▒▒▒▓▒▒▓▒▒▒▒
▒▒▒▒▒▒▒▒▒▒▒▒
▒▓▒▒▒▒▒▒▒▒▓▒
▒▒▓▓▓▓▓▓▓▓▒▒
▒▒▒▒▒▒▒▒▒▒▒▒''')

비밀번호 감추기

import getpass

# 사용자 입력 비밀번호
user_input = getpass.getpass("비밀번호를 입력하세요 >> ")

while user_input != passwd:
    # 비밀번호 불일치 메세지
    user_input = getpass.getpass("잘못된 비밀번호입니다! 다시 입력해주세요 >>>")

print("잠금이 해제되었습니다!")

비밀번호 암호화

hashlib

  • hashlib은 문자열을 해싱할 때 사용하는 모듈이다.
  • 해싱이란 원본 문자열을 알아볼 수 없는 난해한 문자열로 정의하는 방법으로
  • 해시값을 조사하여 데이터 변조 여부를 확인하는 것이 주된 목적
  • 단방향 해시 함수는 수학적 연산에 의해 원본 데이터를 완전히 다른 암호화된 데이터로 변환
  • 변환된 데이터는 다시 원본 데이터로 복호화가 불가능
  • 안전하게 관리되어야 하는 정보를 암호화 할 때 주로 사용

예제

import hashlib
import getpass

# 원본 비밀번호
passwd = 'fastcampus123!'

# 비밀번호 해싱
h = hashlib.sha256()
h.update(passwd.encode('utf-8'))

# 해싱된 비밀번호
h_passwd = h.digest()
print(h_passwd)
# b'T\xec\x92\x01P\x7f\xd6\xd9\xd0h\x9a<]\x83\xc59\xd2\xdd\x84\x06\x84\xa6\x11\xd1\x9b\xb9\x85\xf7\xc2:U\x9e'

방법1: 해싱을 사용하지 않은 경우

# 사용자 입력 비밀번호
user_input = getpass.getpass("비밀번호를 입력하세요 >>> ")

while user_input != passwd:
    # 비밀번호 불일치 메세지
    user_input = getpass.getpass("잘못된 비밀번호입니다! 다시 입력해주세요 >>>")
    print("방금 입력하신 비밀번호는 ...: {}".format(user_input))

print("잠금이 해제되었습니다 !")
# 비밀번호를 입력하세요 >>> ········
# 잘못된 비밀번호입니다! 다시 입력해주세요 >>> ········
# 방금 입력하신 비밀번호는 ... : fastcampus!
# 잘못된 비밀번호입니다! 다시 입력해주세요 >>> ········
# 방금 입력하신 비밀번호는 ... : fastcampus123!
# 잠금이 해제되었습니다 !

방법2: 해싱을 사용한 경우

# 비밀번호 해싱 함수
def passwd_hash(original_passwd):
    h = hashlib.sha256()
    h.update(original_passwd.encode('utf-8'))
    hashed_passwd = h.digest()
    return hashed_passwd

# 사용자 입력 비밀번호
user_input = passwd_hash(getpass.getpass("비밀번호를 입력하세요 >>> "))

while user_input != h_passwd:
    # 비밀번호 불일치 메세지
    user_input = passwd_hash(getpass.getpass("잘못된 비밀번호입니다! 다시 입력해주세요 >>> "))
    print("방금 입력하신 비밀번호는 ...: {}".format(user_input))

print('잠금이 해제되었습니다 !')

메세지 변조 확인

hmac

  • hmac 은 비밀 키와 해싱 기술을 사용하여 송수신자 간 메세지 변조를 확인할 수 있도록 하는 모듈
  • 송수신자 간 약속한 비밀키를 사용해서 해싱된 데이터 내용이 같은지 대조하는 원리
  • 만약 해커 등 제 3자가 메세지를 변조했을 경우, 비밀키로 해싱한 결과가 달라짐
# 비밀 키 설정
SECRET_KEY = 'FASTCAMPUS'

import hmac
import hashlib

# 송신 메세지 입력
important_message = '아주 중요한 메시지'

# 원본 파일
with open('message.txt', 'w') as f:
    f.write(important_message)

# 비밀 키 암호화 파일

with open('message_encrypted.txt', 'w') as f:
    m = hmac.new(SECRET_KEY.encode('utf-8'), iportant_message.encode('utf-8'), hashlib.sha256)
    f.write(m.hexdigest())

[수신] 복호화 및 변조 확인

with open('message_encrypted.txt') as f:
    message_encrypted = f.read()

with open('message.txt') as f:
    message = f.read()
    m = hmac.new(SECRET_KEY.encode('utf-8'), message.encocde('utf-8'),
                hashlib.sha256)
    if m.hexidigest() == message_encrypted:
        print("메세지가 변조되지 않았습니다! 안전합니다.")
    else:
        print("변조된 메세지 입니다! 위헙합니다.")

난수 생성

secrets

  • 난수란 정의된 범위 내에서 무작위로 추출된 수
  • 가장 널리 사용되는 난수 생성 함수인 random은 보안이나 암호를 목적으로 사용되기에 위험함
  • secrets.token-hex(nbytes): nbytes는 바이트 수
import secrets

# 8 바이트 난수 (16자리)
rand8 = secrets.token_hex(8)
print(rand8)

# 16 바이트 난수 (32자리)
rnad16 = secrets.token_hex(16)
print(rand16)

OTP 비밀번호 생성기

import secrets
import string

string.digits
# '0123456789'

OTP = ''
digit = string.digits
for i in range(6):
    OTP += str(''.join(secrets.choice(digit)))

print(OTP)

비밀번호 일치 여부 확인 (내부 해싱)

  • 타이밍 공격을 방지할 수 있는 기능
  • print(secrets.compare_digest('password123', 'password123'))

보안 URL 생성

url = 'https://mywebsite.com/reset=' + secrets.token_urlsafe(7)
print(url)

'Python > 학습용' 카테고리의 다른 글

📅 달력 만들기  (0) 2025.04.13
🐍 Python 파일 및 디렉터리 처리 완전 정복  (0) 2025.04.12
LLM - Fine-Tuning  (0) 2025.03.21
추천시스템 (3): 협업필터링 실습  (0) 2025.03.21
추천시스템 (2): 협업필터링  (0) 2025.03.21