forked from elseif/MikroTikPatch
-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathlicense.py
134 lines (116 loc) · 6.15 KB
/
license.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
122
123
124
125
126
127
128
129
130
131
132
133
134
from mikro import *
def generate_eddsa_keypair():
curve = getcurvebyname('Ed25519')
private_key = ECPrivateKey.eddsa_generate(curve)
return private_key.eddsa_encode(), private_key.pubkey.eddsa_encode()
def generate_kcdsa_keypair():
curve = getcurvebyname('Curve25519')
private_key = ECPrivateKey.generate(curve)
return Tools.inttobytes_le(private_key.scalar, 32), Tools.inttobytes_le(int(private_key.pubkey.point.x), 32)
def lic_parse_ros(lic: str, public_key: bytes):
assert (isinstance(public_key, bytes))
slic = lic.replace(MIKRO_LICENSE_HEADER, '').replace(
MIKRO_LICENSE_FOOTER, '').replace('\n', '').replace(' ', '')
lic: bytes = mikro_base64_decode(slic)
licVal = mikro_decode(lic[:16])
software_id = int.from_bytes(licVal[:6], 'little')
print(f"Software ID: {mikro_softwareid_encode(software_id)}({hex(software_id)})")
print(f"RouterOS Version: {licVal[6]}")
print(f"License Level: {licVal[7]}")
nonce_hash = lic[16:32]
print(f"Nonce Hash: {nonce_hash.hex()}")
signature = lic[32:64]
print(f"Signature: {signature.hex()}")
print(f'License valid: {mikro_kcdsa_verify(licVal, nonce_hash+signature, public_key)}')
def lic_parse_chr(lic: str, public_key: bytes):
assert (isinstance(public_key, bytes))
slic = lic.replace(MIKRO_LICENSE_HEADER, '').replace(
MIKRO_LICENSE_FOOTER, '').replace('\n', '').replace(' ', '')
lic: bytes = mikro_base64_decode(slic)
licVal = mikro_decode(lic[:16])
system_id = int.from_bytes(licVal[:8], 'little')
print(f"System ID: {mikro_systemid_encode(system_id)}({hex(system_id)})")
print(f"Deadline: {licVal[11]}")
print(f"Level: {licVal[12]}")
nonce_hash = lic[16:32]
print(f"Nonce Hash: {nonce_hash.hex()}")
signature = lic[32:64]
print(f"Signature: {signature.hex()}")
print(f'License valid: {mikro_kcdsa_verify(licVal, nonce_hash+signature, public_key)}')
def lic_gen_ros(software_id, private_key: bytes):
assert (isinstance(private_key, bytes))
if isinstance(software_id, str):
software_id = mikro_softwareid_decode(software_id)
lic = software_id.to_bytes(6, 'little')
varb7 = 7 # RouterOS Version
varb8 = 22 # Features
lic += varb7.to_bytes(1, 'little')
lic += varb8.to_bytes(1, 'little')
lic += b'\0'*8
sig = mikro_kcdsa_sign(lic, private_key)
lic = mikro_base64_encode(mikro_encode(lic)+sig, True)
return MIKRO_LICENSE_HEADER + '\n' + lic[:len(lic)//2] + '\n' + lic[len(lic)//2:] + '\n' + MIKRO_LICENSE_FOOTER
def lic_gen_chr(system_id, private_key: bytes):
assert (isinstance(private_key, bytes))
if isinstance(system_id, str):
system_id = mikro_systemid_decode(system_id)
lic = system_id.to_bytes(8, 'little')
varb9 = 0 # Unknown Value
varb10 = 87 # Unknown Value
varb11 = 134 # Unknown Value
varb12 = 244 # Renew Date
varb13 = 3 # License Level
lic += varb9.to_bytes(1, 'little')
lic += varb10.to_bytes(1, 'little')
lic += varb11.to_bytes(1, 'little')
lic += varb12.to_bytes(1, 'little')
lic += varb13.to_bytes(1, 'little')
lic += b'\0'*3
sig = mikro_kcdsa_sign(lic, private_key)
lic = mikro_base64_encode(mikro_encode(lic)+sig, True)
return MIKRO_LICENSE_HEADER + '\n' + lic[:len(lic)//2] + '\n' + lic[len(lic)//2:] + '\n' + MIKRO_LICENSE_FOOTER
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='MikroTik License Manager')
subparsers = parser.add_subparsers(dest="command")
genkey_parser = subparsers.add_parser('genkey', help='Generate Keys')
licgenros_parser = subparsers.add_parser(
'licgenros', help='Generate RouterOS License')
licgenros_parser.add_argument('software_id', type=str, help='Software ID')
licgenros_parser.add_argument('private_key', type=str, help='Private Key')
licgenchr_parser = subparsers.add_parser(
'licgenchr', help='Generate CHR License')
licgenchr_parser.add_argument('system_id', type=str, help='System ID')
licgenchr_parser.add_argument('private_key', type=str, help='Private Key')
licparseros_parser = subparsers.add_parser(
'licparseros', help='Parse RouterOS License')
licparseros_parser.add_argument(
'license', type=str, help='License String. Format: 66c1aRpjM52VlmgwPWQv6b6DPwX3vyg+vxlgb+ebXMP2K5A0Ei2mr5m+wHLUqrqmTNz7shFjNJAaMjXK3zXvIA==')
licparseros_parser.add_argument('public_key', type=str, help='Public Key')
licparsechr_parser = subparsers.add_parser(
'licparsechr', help='Parse CHR License')
licparsechr_parser.add_argument(
'license', type=str, help='License String. Format: 66c1aRpjM52VlmgwPWQv6b6DPwX3vyg+vxlgb+ebXMP2K5A0Ei2mr5m+wHLUqrqmTNz7shFjNJAaMjXK3zXvIA==')
licparsechr_parser.add_argument('public_key', type=str, help='Public Key')
args = parser.parse_args()
MIKRO_LICENSE_HEADER = '-----BEGIN MIKROTIK SOFTWARE KEY------------'
MIKRO_LICENSE_FOOTER = '-----END MIKROTIK SOFTWARE KEY--------------'
if args.command == 'genkey':
print('export MIKRO_NPK_SIGN_PUBLIC_KEY="C293CED638A2A33C681FC8DE98EE26C54EADC5390C2DFCE197D35C83C416CF59"')
print('export MIKRO_LICENSE_PUBLIC_KEY="8E1067E4305FCDC0CFBF95C10F96E5DFE8C49AEF486BD1A4E2E96C27F01E3E32"')
eddsa_private_key, eddsa_public_key = generate_eddsa_keypair()
print(f'export CUSTOM_NPK_SIGN_PRIVATE_KEY="{eddsa_private_key.hex().upper()}"')
print(f'export CUSTOM_NPK_SIGN_PUBLIC_KEY="{eddsa_public_key.hex().upper()}"')
kcdsa_private_key, kcdsa_public_key = generate_kcdsa_keypair()
print(f'export CUSTOM_LICENSE_PRIVATE_KEY="{kcdsa_private_key.hex().upper()}"')
print(f'export CUSTOM_LICENSE_PUBLIC_KEY="{kcdsa_public_key.hex().upper()}"')
elif args.command == 'licgenros':
print(lic_gen_ros(args.software_id, bytes.fromhex(args.private_key)))
elif args.command == 'licgenchr':
print(lic_gen_chr(args.system_id, bytes.fromhex(args.private_key)))
elif args.command == 'licparseros':
lic_parse_ros(args.license, bytes.fromhex(args.public_key))
elif args.command == 'licparsechr':
lic_parse_chr(args.license, bytes.fromhex(args.public_key))
else:
parser.print_help()