python實現軟件的注冊功能(機器碼+注冊碼機制)


一、前言:
目的:完成已有python圖像處理工具的注冊功能
功能:用戶運行程序后,通過文件自動檢測認證狀態,如果未經認證,就需要注冊。注冊過程是用戶將程序運行后顯示的機器碼(C盤的卷序號)發回給管理員,管理員對機器碼加密后生成加密文件或字符串返回給用戶。每次啟動程序,在有注冊文件的情況下,程序就會通過DES和base64解碼,並與此刻獲取到的C盤卷序列號比對,如果一致則運行主程序。如果注冊文件解碼后與卷序號不一致,就要提醒用戶輸入注冊碼,如果對新輸入的解碼后和重新獲取的機器碼一致,則通過認證,生成新的注冊文件后進入主程序。
庫和組件:
1、pyDes用於加密解密
2、base64,用於pyDes加密解密后的二次加密解密
3、win32api,用於獲取C盤卷序列號
4、pyinstaller,打包
參考:
1、pyDes庫 實現python的des加密
2、 win32api.GetVolumeInformation
3、pyinstaller打包文件說明
 
二、實現
#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盤卷序列號進行加密,加密以后生成字符串或注冊文件,再返還給用戶,不再贅述。

 

轉載請注明出處:

http://www.cnblogs.com/cquptzzq/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM