一、前言:
目的:完成已有python图像处理工具的注册功能
功能:用户运行程序后,通过文件自动检测认证状态,如果未经认证,就需要注册。注册过程是用户将程序运行后显示的机器码(C盘的卷序号)发回给管理员,管理员对机器码加密后生成加密文件或字符串返回给用户。每次启动程序,在有注册文件的情况下,程序就会通过DES和base64解码,并与此刻获取到的C盘卷序列号比对,如果一致则运行主程序。如果注册文件解码后与卷序号不一致,就要提醒用户输入注册码,如果对新输入的解码后和重新获取的机器码一致,则通过认证,生成新的注册文件后进入主程序。
库和组件:
1、pyDes用于加密解密
2、base64,用于pyDes加密解密后的二次加密解密
3、win32api,用于获取C盘卷序列号
4、pyinstaller,打包
参考:
1、pyDes库 实现python的des加密
http://twhiteman.netfirms.com/des.html
2、win32api.GetVolumeInformation
http://timgolden.me.uk/pywin32-docs/win32api__GetVolumeInformation_meth.html
3、pyinstaller打包文件说明
http://pythonhosted.org/PyInstaller/spec-files.html#using-spec-files
二、实现
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
|
#coding:utf8 #register.py #功能说明:用户运行程序后,自动检测认证状态,如果未经认证,就需要注册。注册过程是用户将程序运行后显示的机器码(卷序号)发回给管理员,管理员通过加密后生成加密文件或字符串给回用户。 #每次登录,在有注册文件或者注册码的情况下,软件就会通过DES和base64解码,如果解码后和重新获取的机器码一致,则通过认证,进入主程序。 import base64 import win32api from pyDes import * #from binascii import a2b_hex #如果需要用二进制编码保存注册码和注册文件可以使用binascii转换 class register: def __init__( self ): self .Des_Key = "BHC#@*UM" # Key self .Des_IV = "\x22\x33\x35\x81\xBC\x38\x5A\xE7" # 自定IV向量 #获取C盘卷序列号 #使用C盘卷序列号的优点是长度短,方便操作,比如1513085707,但是对C盘进行格式化或重装电脑等操作会影响C盘卷序列号。 #win32api.GetVolumeInformation(Volume Name, Volume Serial Number, Maximum Component Length of a file name, Sys Flags, File System Name) #return('', 1513085707, 255, 65470719, 'NTFS'),volume serial number is 1513085707. def getCVolumeSerialNumber( self ): CVolumeSerialNumber = win32api.GetVolumeInformation( "C:\\" )[ 1 ] #print chardet.detect(str(CVolumeSerialNumber)) #print CVolumeSerialNumber if CVolumeSerialNumber: return str (CVolumeSerialNumber) #number is long type,has to be changed to str for comparing to content after. else : return 0 #使用DES加base64的形式加密 #考虑过使用M2Crypto和rsa,但是都因为在windows环境中糟糕的安装配置过程而放弃 def DesEncrypt( self , str ): k = des( self .Des_Key, CBC, self .Des_IV, pad = None , padmode = PAD_PKCS5) EncryptStr = k.encrypt( str ) #EncryptStr = binascii.unhexlify(k.encrypt(str)) return base64.b64encode(EncryptStr) #转base64编码返回 #des解码 def DesDecrypt( self , str ): k = des( self .Des_Key, CBC, self .Des_IV, pad = None , padmode = PAD_PKCS5) DecryptStr = k.decrypt( str ) #DecryptStr = a2b_hex(k.decrypt(str)) print DecryptStr return DecryptStr #获取注册码,验证成功后生成注册文件 def regist( self ): key = raw_input ( 'please input your register code: ' ) #由于输入类似“12”这种不符合base64规则的字符串会引起异常,所以需要增加输入判断 #while key if key: content = self .getCVolumeSerialNumber() / / number has been changed to str type after use str () #print chardet.detect(content) #print type(content) #print content #type(key_decrypted) is str key_decrypted = str ( self .DesDecrypt(base64.b64decode(key))) #print chardet.detect(key_decrypted) #print key_decrypted #type(key_decrypted) is str if content! = 0 and key_decrypted! = 0 : if content ! = key_decrypted: print "wrong register code, please check and input your register code again:" self .regist() elif content = = key_decrypted: print "register succeed." #读写文件要加判断 with open ( './register' , 'w' ) as f: f.write(key) f.close() return True else : return False else : return False else : self .regist() return False def checkAuthored( self ): content = self .getCVolumeSerialNumber() checkAuthoredResult = 0 #读写文件要加判断 try : f = open ( './register' , 'r' ) if f: key = f.read() if key: key_decrypted = self .DesDecrypt(base64.b64decode(key)) if key_decrypted: if key_decrypted = = content: checkAuthoredResult = 1 else : checkAuthoredResult = - 1 else : checkAuthoredResult = - 2 else : checkAuthoredResult = - 3 else : self .regist() except IOError: print IOError print checkAuthoredResult return checkAuthoredResult if __name__ = = '__main__' : reg = register() reg.regist() |
三、备注
1、使用C盘卷序列号而不是硬盘号的原因是:位数短,方便操作。
但是使用硬盘号才是更安全的做法,因为硬盘号不会因重装系统、格式化C盘或修改C盘序号而改变。
1
2
3
4
|
#CVolumeSerialNumber: 1513085707 #after encryption: ro5RVXZoP0KmnogYDeepUg== #the HardDiskNumber: 32535332584e4741343536393237204620202020 #after encryption: MzI1MzUzMzI1ODRlNDc0MTM0MzUzNjM5MzIzNzIwNDYyMDIwMjAyMA== |
2、除了win32api,wmi也可以用来获取系统信息(比如硬盘号),获取完整硬盘号的过程如下:
1
2
3
4
5
6
|
#虽然使用wmi可以获取磁盘序列号,可是磁盘序列号是3253533258**************3237204620202020,加密后太长,不方便操作,所以弃置 import wmi def getHardDiskNumber( self ): c = wmi.WMI() for physical_disk in c.Win32_DiskDrive(): return physical_disk.SerialNumber |
https://pypi.python.org/pypi/WMI/
3、chardet可以用来检验字符串的编码类型,可以用在检测字符串相等上
chardet.detect(str)
4、还存在一些逻辑上的漏洞,比如读写文件时对文件是否存在的判断,读取方式的选择等
5、register.py,供main函数或其他需要获取认证状态的函数调用。
main函数中使用register类的过程是:
创建logIn函数用于获取认证结果-》如果认证结果为假则重新调用register类的regist函数,提醒用户输入注册码,只有成功输入了注册码才能创建新的注册文件-》如果认证结果为真则直接启动主程序。
6、管理员还应该有一个encryption.py,用于使用des+base64算法对用户发过来的C盘卷序列号进行加密,加密以后生成字符串或注册文件,再返还给用户,不再赘述。
以上所述是小编给大家介绍的基于python脚本实现软件的注册功能(机器码+注册码机制),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:http://www.cnblogs.com/cquptzzq/p/5940583.html