一、前言:
目的:完成已有python图像处理工具的注册功能
功能:用户运行程序后,通过文件自动检测认证状态,如果未经认证,就需要注册。注册过程是用户将程序运行后显示的机器码(c盘的卷序号)发回给管理员,管理员对机器码加密后生成加密文件或字符串返回给用户。每次启动程序,在有注册文件的情况下,程序就会通过des和base64解码,并与此刻获取到的c盘卷序列号比对,如果一致则运行主程序。如果注册文件解码后与卷序号不一致,就要提醒用户输入注册码,如果对新输入的解码后和重新获取的机器码一致,则通过认证,生成新的注册文件后进入主程序。
库和组件:
1、pydes用于加密解密
2、base64,用于pydes加密解密后的二次加密解密
3、win32api,用于获取c盘卷序列号
4、pyinstaller,打包
参考:
1、pydes库 实现python的des加密
http://www.mamicode.com/info-detail-508384.html
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
二、实现
#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盘序号而改变。
#cvolumeserialnumber: 1513085707
#after encryption: ro5rvxzop0kmnogydeepug==
#the harddisknumber: 32535332584e4741343536393237204620202020
#after encryption: mzi1mzuzmzi1odrlndc0mtm0mzuznjm5mziznziwndyymdiwmjayma==
2、除了win32api,wmi也可以用来获取系统信息(比如硬盘号),获取完整硬盘号的过程如下:
#虽然使用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脚本实现软件的注册功能(机器码+注册码机制),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!