完成软件开发后,将软件给到用户使用,但是你只希望给固定的用户或固定的电脑使用,这时license就上场了,本文介绍license的生成与调用。

前言

MAC地址是计算机的物理地址,它一般由网卡设备决定,用来表示互联网上不同的站点相关的标识符,而且每一台计算机都拥有不同的物理地址。MAC地址由计算机的网卡决定,而且它是固定的,一般不会被更改。因此将电脑的mac地址是作为电脑的标识。

获取mac地址后,通过一套加密算法将地址生成license,并给出license失效时间。然后每次运行软件前,需读取license进行解密,并与当前电脑的mac地址对比。如果相等,则授权成功,成功运行软件;否则授权失败。

实现方式

使用hash算法对mac地址加密,hash算法的特点是正向快速、逆向困难、输入敏感、冲突避免

加密过程

1
2
3
4
5
6
7
8
9
# 首先获取license字典,包含mac地址,license失效时间,和mac加密结果
psw = Utils().hash_msg('jerry' + str(self.mac_addr)) # 将mac地址加个字符串进行编译,增加破解难度,字符串自定义

license = {}
license['mac'] = self.mac_addr
license['license_time'] = self.license_time
license['psw'] = psw
print('license:', license)
# license: {'mac': 'f0:2f:74:f3:9e:9e', 'license_time': '2022-09-11T10:03:15.447229', 'psw': '1860d86e80d9d1a80c330e0b22e66def40aa22c79d3bc4412b7537eb7c6c8fe5'}
1
2
3
4
5
6
7
# 上述license还是很容易看出的,需要进一步加密。
from utils import PrpCrypt, Utils
pc = PrpCrypt('keyskeyskeyskeys') # 初始化密钥,可以为16位,32位,以及更长,一般为16位,加密解密都需要这个,字符串自定义
encrypted_license = pc.encrypt(str(license)) # 加密 <class 'bytes'>
encrypted_license = str(encrypted_license, encoding = "utf-8") # bytes to str
print(encrypted_license)
# encrypted_license = ba00b17adf2f10d8274b9a59ec71287cb633acd1b69905875602dd0bc4c1903c6926a3272e199fb65eaaafdfb85eae4c3d0d4063abaf4792a603f0eb38691fce3a436071c694d64b2825a385e3c81a70dd9af5eebebdbfa975ff5d97a5a03ffa1b46d41b91f857e11b894faf9c0cbe180e956c8e163964a14eeacf17fb8436f8719021dfe3dfcaf81c0f1fd029ef509c0dc3b3031da38d84e7a2e20fd742fb6d
1
2
3
4
5
6
7
# 将生成的encrypted_license写入特定文件中,完成license生成。
def write_license(self, file_path, s_encrypt):
with open(file_path, 'w', encoding='utf-8') as lic:
lic.write(str(s_encrypt))
lic.close()

Utils().write_license(file_path, str(encrypted_license))

解密过程

1
2
3
4
5
6
7
8
9
# 解密过程需要用到两个字符串,分别是加密过程中,mac地址前加的jerry和初始化密钥keyskeyskeyskeys
def lic_decrypt(self, lic_path):
encrpted_content = Utils().get_license_lic(lic_path)
pc = PrpCrypt('keyskeyskeyskeys')
d = pc.decrypt(encrpted_content)
lic = ast.literal_eval(d)
# print(lic)
return lic
# 然后将生成的license与已有的mac地址,或者加密的mac地址进行对比即可

一些工具类函数

1
2
3
4
5
6
7
8
9
10
11
# 获取mac地址,win和linux通用
def get_mac_address(self):
mac = uuid.UUID(int = uuid.getnode()).hex[-12:]
return ":".join([mac[e:e+2] for e in range(0,11,2)])

# 进行hash计算加密
def hash_msg(self, msg):
sha256 = hashlib.sha256()
sha256.update(msg.encode('utf-8'))
res = sha256.hexdigest()
return res

程序打包

此时,即可将你生成的license许可放到你的python脚本中,从你的主函数中进行调用。python打包教程可以参照笔者博客,传送门

小结

  1. 首先,代码使用aes对称加密,密钥是保存在客户端的,包括生成的hash值也是存在客户端,这是危险的。如果客户端被逆向,可能会反推出加密算法。使用rsa做授权码生成比较安全,公钥加密,私钥解密,至少可以保证授权码很难被逆推出来。
  2. 授权过期时间读取本地系统时间,使用授权截止日期减去当前日期。如果黑客在自己电脑上修改系统时间,将会非常容易绕过授权验证。可以改成远端获取实际时间的方式,起码可以避免修改系统时间导致的绕过问题
  3. 本文提供了一种加密的思路,当然也可以将任何可以从电脑传出来的唯一参数作为加密的参数都可以。
  4. 如果大家需要源代码进行调试或有更好的思路,欢迎留言。

本文在原有技术上进行修改,尊重原创,放原文博客链接