-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsmartcard_handler.py
More file actions
119 lines (101 loc) · 4.35 KB
/
Copy pathsmartcard_handler.py
File metadata and controls
119 lines (101 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# smartcard_handler.py
import subprocess
import os
from PyQt6.QtCore import QThread, pyqtSignal
from smartcard.System import readers
from smartcard.Exceptions import NoCardException
from logging_handler import logger
from config import APPLET_SELECT_APDU, APPLET_CAP_PATH, GP_JAR_PATH
from settings_manager import SettingsManager
class CardMonitorThread(QThread):
"""백그라운드에서 카드 삽입을 감지하는 스레드"""
card_detected = pyqtSignal()
no_reader = pyqtSignal()
_running = True
def run(self):
self._running = True
logger.info("카드 모니터링 스레드 시작.")
while self._running:
try:
reader_list = readers()
if not reader_list:
self.no_reader.emit()
break
connection = reader_list[0].createConnection()
connection.connect()
logger.info("리더기에 카드가 연결됨.")
self.card_detected.emit()
break
except NoCardException:
self.msleep(500)
except Exception as e:
logger.error(f"리더기 연결 중 알 수 없는 오류 발생: {e}", exc_info=True)
self.msleep(1000)
logger.info("카드 모니터링 스레드 종료.")
def stop(self):
self._running = False
logger.info("카드 모니터링 스레드 중지 요청됨.")
def check_applet():
"""카드에 애플릿이 설치되어 있는지 확인"""
logger.info("카드 내 애플릿 설치 여부 확인 시작.")
try:
reader_list = readers()
if not reader_list:
raise RuntimeError("리더기가 연결되지 않았습니다.")
connection = reader_list[0].createConnection()
connection.connect()
logger.info(f"APDU 전송 (SELECT): {bytes(APPLET_SELECT_APDU).hex().upper()}")
data, sw1, sw2 = connection.transmit(APPLET_SELECT_APDU)
if sw1 == 0x90 and sw2 == 0x00:
logger.info(f"애플릿 확인 성공 (SW: {sw1:02X}{sw2:02X}).")
return True
else:
logger.warning(f"애플릿을 찾을 수 없음 (SW: {sw1:02X}{sw2:02X}).")
return False
except Exception as e:
logger.error(f"애플릿 확인 중 오류 발생: {e}", exc_info=True)
return False
def install_applet(emp_no: str):
"""gp.jar를 사용하여 애플릿을 설치"""
gp_jar_path = GP_JAR_PATH
applet_cap_path = APPLET_CAP_PATH
settings_manager = SettingsManager()
logger.info(f"사번 '{emp_no}'에 대한 애플릿 설치 시작.")
if not os.path.exists(gp_jar_path) or not os.path.exists(applet_cap_path):
message = f"{gp_jar_path} 또는 {applet_cap_path} 파일을 찾을 수 없습니다."
logger.error(message)
return False, message
try:
emp_no_hex = emp_no.encode('ascii').hex()
params = f"{len(emp_no_hex)//2:02x}{emp_no_hex}"
# GP 키 설정값 가져오기
key_dek = settings_manager.get_key("key_dek")
key_enc = settings_manager.get_key("key_enc")
key_mac = settings_manager.get_key("key_mac")
command = [
"java", "-jar", gp_jar_path,
"--install", applet_cap_path,
"--key-dek", key_dek,
"--key-enc", key_enc,
"--key-mac", key_mac,
"--params", params
]
logger.info(f"gp.jar 실행 명령어: {' '.join(command)}")
process = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
encoding='utf-8'
)
stdout, stderr = process.communicate()
logger.info(f"gp.jar stdout:\n{stdout}")
if process.returncode == 0 and ("INSTALL for load" in stdout or "Application installed" in stdout):
logger.info("gp.jar 실행 성공, 애플릿 설치 완료.")
return True, stdout
else:
logger.error(f"gp.jar 실행 실패 (Return Code: {process.returncode}). stderr:\n{stderr}")
return False, stderr if stderr else stdout
except Exception as e:
logger.critical(f"gp.jar 실행 중 예외 발생: {e}", exc_info=True)
return False, str(e)