-
Notifications
You must be signed in to change notification settings - Fork 5
/
cryptos.py
121 lines (101 loc) · 3.78 KB
/
cryptos.py
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
120
121
# This file is part of twnhi-smartcard-agent.
#
# twnhi-smartcard-agent is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# twnhi-smartcard-agent is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with twnhi-smartcard-agent.
# If not, see <https://www.gnu.org/licenses/>.
import os
import datetime
import hashlib
from Cryptodome.Cipher import DES, DES3
bKEY = b'12345678123456780' * 10
K_BOX = [
0x56, 0x28, 0x34, 0x2E, 0x78, 0x5, 0xF, 0x5A,
0x36, 0x44, 0x42, 0x19, 0x26, 0x95, 0x26, 0x4D,
0x3, 0x10, 0x15, 0x58, 0x3, 0x40, 0x5A, 0x72,
0x1E, 0xB, 0x49, 0x69, 0x4B, 0x15, 0x29, 0x6
]
K_BOX1 = [
0x56, 0x28, 0x34, 0x2E, 0x78, 0x5, 0xF, 0x5A,
0x36, 0x44, 0x42, 0x19, 0x26, 0x95, 0x26, 0x4D,
0x2D, 0x41, 0x4D, 0x1F, 0x41, 0x62, 0x15, 0x2F
]
L_KEY = bytes(bKEY[K_BOX[i]] for i in range(16)) + b'\0' * 8
L_KEY1 = bytes(bKEY[K_BOX1[i]] for i in range(24))
KEY_SUFFIX = b'\x27\x06\x58\x66'
TDesLKey = DES3.new(L_KEY, DES3.MODE_ECB)
TDesLKey1 = DES3.new(L_KEY1, DES3.MODE_ECB)
def iv_pad(d):
def rand_byte():
return os.urandom(1)
bcount = len(d) // 7
if len(d) % 7:
bcount += 1
blocks = [ d[i*7:i*7 + 7].ljust(7, b'\0') + rand_byte() for i in range(bcount) ]
return b''.join(blocks)
def iv_remove(d, flag=True):
c = b''.join(d[i*8:i*8+7] for i in range(len(d) // 8))
if flag:
unpad_size = (len(c) // 8) * 8
return c[:unpad_size]
return c
def pkcs5_tail(n):
return bytes([n]) * n
def pkcs5_pad(data):
padding_size = 8 - len(data) % 8
return data + pkcs5_tail(padding_size)
def pkcs5_unpad(data):
last_byte = data[-1]
tail = data[-last_byte:]
if last_byte > 8 or bytes(tail) != pkcs5_tail(last_byte):
raise ValueError('Inalid PKCS5 padding')
return data[:-last_byte]
def card_encrypt(data, cardid):
t = datetime.date.today().strftime('%Y%m%d')
tdeskey = hashlib.sha1((cardid + t).encode('ascii')).digest() + KEY_SUFFIX
cipher = DES3.new(tdeskey, DES3.MODE_ECB)
data = cipher.encrypt(pkcs5_pad(data))
return TDesLKey1.encrypt(iv_pad(data))
def card_decrypt(data, cardid):
t = datetime.date.today().strftime('%Y%m%d')
tdeskey = hashlib.sha1((cardid + t).encode('ascii')).digest() + KEY_SUFFIX
cipher = DES3.new(tdeskey, DES3.MODE_ECB)
data = TDesLKey1.decrypt(data)
data = iv_remove(data)
data = cipher.decrypt(data)
return pkcs5_unpad(data)
def basic_encrypt(data):
key = datetime.date.today().strftime('%m%d%Y').encode('ascii')
cipher = DES.new(key, DES.MODE_ECB)
return cipher.encrypt(iv_pad(data))
def basic_decrypt(data):
key = datetime.date.today().strftime('%m%d%Y').encode('ascii')
cipher = DES.new(key, DES.MODE_ECB)
decrypted = cipher.decrypt(data)
return iv_remove(decrypted, False)
if __name__ == '__main__':
data, card_id = b'123456123456', '000000000001'
if card_decrypt(card_encrypt(data, card_id), card_id) == data:
print('card_* : Pass')
else:
print('card_* : Failed')
for i in range(40, 40+2*6):
test_data = bytes(range(i))
if basic_decrypt(basic_encrypt(test_data + b'\xff')).split(b'\xff')[0] != test_data:
print('basic_* : Failed')
break
else:
print('basic_* : Pass')
import sys
if len(sys.argv) > 1:
data = bytes.fromhex(sys.argv[1])
print(basic_decrypt(data).decode('big5-hkscs'))