이전 포스팅에서는 파이썬에서 NTP 모듈을 이용하여 시간 동기화 서버를 구성하는 방법에 대해 알아보았습니다. 시간 동기화는 서버에게 제공받아야할 서비스 조건으로 클라이언트와 서버 시간이 동일해야할 때 사용됩니다. 만약 서로의 시간이 동일하지 않다면 서비스 이용에 어려움이 있습니다. 바로 이런 제약 기능을 구현하기 위해서 파이썬으로 NTP 서버를 구성합니다. 해당 내용이 궁금하시다면 아래 링크를 참고해주세요.
2024.02.20 - [Python] - [Linux/Python] 파이썬 코딩 NTP 시간 동기화 서버 구축 예제(UDP, pool.ntp.org 연동)
다음으로 이전 포스팅에서는 파이썬 코딩으로 TOTP(시간 기반 일회용 비밀번호)를 생성하는 방법에 대해 다뤘습니다. 이번에는 TOTP 생성을 위해 QR 코드를 생성하고 출력하는 예제를 살펴보겠습니다. QR 코드는 스마트폰 앱 등을 통해 쉽게 스캔할 수 있는 형태로 정보를 인코딩하는데 사용됩니다. 이 예제에서는 서버와 시간을 동기화하여 이 시간 값과 pyotp 모듈을 활용하여 TOTP를 생성하고, qrcode 모듈을 사용하여 해당 TOTP를 QR 코드로 변환하여 출력하는 방법을 설명하겠습니다. QR 코드를 통해 클라이언트가 쉽게 TOTP를 입력할 수 있도록 도움을 줄 수 있습니다.
2024.02.23 - [Python] - [Linux/Python] 파이썬 코딩 TOTP 생성 예제(hmac 키, expire time 설정)
마지막으로 이전에 다뤘던 포스팅에서는 파이썬 코딩으로 Flask 서버에서 SSL 인증서와 키 파일을 설정하는 방법에 대해 다뤘습니다. ssl.SSLContext를 활용하여 Flask 서버에 SSL 인증서와 키 파일을 설정하는 예제를 살펴보았습니다. SSL 인증서와 키 파일을 설정함으로써 서버와 클라이언트 간의 통신을 암호화할 수 있습니다. 이를 통해 데이터의 안전성을 확보하고, 중간자 공격 등의 보안 위협으로부터 안전한 통신을 할 수 있습니다. 만약 Flask 서버의 SSL 설정 방법과 활용 방법을 자세히 알고싶으시다면 아래 링크의 포스팅을 참고하여 학습해주세요.
2023.12.04 - [Python] - [Python/Linux] 파이썬 ssl.SSLContext 활용 예제 - 2(서버 키 패스워드 설정)
아래는 파이썬 NTP 서버에 시간을 요청하고, 클라이언트와의 시간 차이를 계산하는 예제입니다. 서버와 클라이언트 간의 시간 동기화는 네트워크 통신 및 보안 프로토콜에서 중요합니다. 이런 방법을 통해 서버와 클라이언트 간의 시간 차이를 계산할 수 있습니다.
import ntplib
from time import time, ctime, strptime, mktime
from socket import socket, AF_INET, SOCK_DGRAM
# NTP 서버로부터 동기화된 시간을 받아오는 함수
def get_synchronized_time():
server_address = ('localhost', 4646) # NTP 서버의 IP 주소와 포트로 변경해주세요.
client_socket = socket(AF_INET, SOCK_DGRAM)
client_socket.sendto(b'', server_address)
data, _ = client_socket.recvfrom(1024)
client_socket.close()
current_time = data.decode()
return current_time
# 받은 시간과 현재 클라이언트 시간의 차이를 계산하는 함수
def calculate_time_difference(received_time):
server_time = strptime(received_time, "%a %b %d %H:%M:%S %Y") # 받은 시간을 파싱하여 struct_time 형태로 변환
client_time = time()
time_difference = client_time - mktime(server_time)
return time_difference
# 동기화된 시간 받아오기
received_time = get_synchronized_time()
# 시간 차이 계산
time_difference = calculate_time_difference(received_time)
# 결과 출력
print(f"받은 시간: {received_time}")
print(f"클라이언트 시간: {ctime()}")
print(f"시간 차이: {time_difference}초")
아래는 시간 차이를 기반으로 현재 시간으로 TOTP를 생성하는 예제입니다. TOTP는 시간 기반으로 일회용 비밀번호를 생성하는 알고리즘입니다. 이렇게 시간 차이가 반영된 현재 시간을 이용하여 TOTP를 만드는 예제입니다.
import hmac
import hashlib
import ntplib
import struct
import time
from socket import socket, AF_INET, SOCK_DGRAM
# NTP 서버로부터 동기화된 시간을 받아오는 함수
def get_synchronized_time():
server_address = ('localhost', 4646) # NTP 서버의 IP 주소와 포트로 변경해주세요.
client_socket = socket(AF_INET, SOCK_DGRAM)
client_socket.sendto(b'', server_address)
data, _ = client_socket.recvfrom(1024)
client_socket.close()
current_time = data.decode()
return current_time
# 받은 시간과 현재 클라이언트 시간의 차이를 계산하는 함수
def calculate_time_difference(received_time):
server_time = strptime(received_time, "%a %b %d %H:%M:%S %Y") # 받은 시간을 파싱하여 struct_time 형태로 변환
client_time = time.time()
time_difference = client_time - mktime(server_time)
return time_difference
# TOTP 생성 함수
def generate_totp(secret_key, time_difference):
interval = 30 # TOTP 갱신 간격 (초)
counter = int(time.time() + time_difference) // interval
counter_bytes = struct.pack('>Q', counter) # 카운터를 8바이트의 바이너리 데이터로 변환
hmac_obj = hmac.new(secret_key, counter_bytes, hashlib.sha1)
hmac_digest = hmac_obj.digest()
# OTP 값 생성
offset = hmac_digest[-1] & 0x0F
truncated_hash = hmac_digest[offset : offset + 4]
otp = struct.unpack('>I', truncated_hash)[0] & 0x7FFFFFFF
otp %= 1000000 # 6자리로 제한
return otp
# 동기화된 시간 받아오기
received_time = get_synchronized_time()
# 시간 차이 계산
time_difference = calculate_time_difference(received_time)
# 결과 출력
print(f"받은 시간: {received_time}")
print(f"클라이언트 시간: {ctime()}")
print(f"시간 차이: {time_difference}초")
# 시크릿 키
secret_key = b'SECRET_KEY' # 본인의 시크릿 키로 변경해주세요.
current_time = time.time()
# TOTP 생성
otp = generate_totp(secret_key, time_difference)
# 결과 출력
print(f"현재 시간: {time.ctime(current_time)}")
print(f"TOTP: {otp}")