標籤:odi error 類型 hosted read mil mode nas 讀寫檔案
http://www.cnblogs.com/cquptzzq/p/5940583.html
一、前言:目的:完成已有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.htmlhttp://twhiteman.netfirms.com/des.html2、win32api.GetVolumeInformationhttp://timgolden.me.uk/pywin32-docs/win32api__GetVolumeInformation_meth.html3、pyinstaller打包檔案說明http://pythonhosted.org/PyInstaller/spec-files.html#using-spec-files 二、實現
#coding:utf8#register.py#功能說明:使用者運行程式後,自動檢測認證狀態,如果未經認證,就需要註冊。註冊過程是使用者將程式運行後顯示的機器碼(卷序號)發回給管理員,管理員通過加密後產生加密檔案或字串給回使用者。#每次登入,在有註冊檔案或者註冊碼的情況下,軟體就會通過DES和base64解碼,如果解碼後和重新擷取的機器碼一致,則通過認證,進入主程式。import base64import win32apifrom 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 checkAuthoredResultif __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 wmidef 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盤卷序號進行加密,加密以後產生字串或註冊檔案,再返還給使用者,不再贅述。
轉載請註明出處:
http://www.cnblogs.com/cquptzzq/
python實現軟體的註冊功能(機器碼+註冊碼機制)