python授權加密的幾種常見方案
要讓軟件授權碼(License Key)更安全,并能限定服務器和使用時間,通??梢越Y合加密、硬件綁定和時間限制等方式來增強安全性。以下是幾種常見的方案:
1. 采用非對稱加密(RSA、ECC)
使用非對稱加密(如 RSA、ECC)來生成和驗證授權碼,避免私鑰泄露:
- 生成授權碼時:服務器用私鑰加密生成帶有使用時間和設備信息的授權碼;
- 客戶端驗證:客戶端軟件用公鑰解密并校驗授權碼的有效性。
示例
- 授權碼內容:
- 用 RSA 私鑰加密并生成授權碼
- 客戶端用 RSA 公鑰解密并驗證有效性
2. 綁定服務器(機器)信息
防止授權碼在多個設備上使用,可以綁定 硬件 ID(如 CPU ID、MAC 地址、硬盤序列號等)。
- 生成授權碼時,記錄服務器的唯一硬件標識
- 客戶端運行時校驗當前設備信息是否匹配授權碼
實現(xiàn)方法
- 獲取設備唯一 ID,例如:
- Windows:
wmic cpu get ProcessorId
- Linux:
cat /etc/machine-id
- Windows:
- 生成授權碼時,把硬件 ID加入授權信息
- 在客戶端解密授權碼后比對當前設備 ID
3. 設置時間限制(防止永久使用)
授權碼應包含有效期,并防止用戶篡改系統(tǒng)時間:
- 在授權碼中嵌入到期時間,如
expire: "2025-12-31"
- 服務器定期驗證授權碼,或者客戶端檢查到期時間
- 防止修改系統(tǒng)時間:
- 可使用 NTP 服務器獲取時間
- 記錄本地第一次使用的時間戳,并在下次啟動時對比是否倒退
4. 使用 HMAC 或對稱加密(AES)防篡改
為了防止授權碼被篡改,可以使用 HMAC(哈希消息認證碼) 或 AES 加密:
- HMAC 方式(SHA256):服務器用密鑰簽名授權碼,客戶端驗證簽名
- AES 方式:用對稱密鑰加密整個授權碼,客戶端解密后校驗
驗證授權碼時,客戶端用相同的 secret_key
計算簽名并校驗。
5. 結合在線授權服務器
為了更安全,可以使用在線授權服務器,客戶端每次啟動時需向服務器驗證:
- 授權服務器存儲授權碼和綁定的設備信息
- 客戶端每次啟動時請求服務器驗證授權碼
- 服務器返回結果,是否授權、是否過期、是否被盜用
額外措施:
- 允許離線模式(如本地緩存授權信息)
- 服務器可吊銷授權碼(如檢測到異常使用)
最佳方案推薦
- 本地校驗:使用RSA(公私鑰加密)+ HMAC(防篡改)
- 綁定設備:獲取 CPU ID 或 MAC 地址,存入授權碼
- 限制時間:內嵌到期時間,并校驗系統(tǒng)時間防修改
- 服務器驗證(可選):定期檢查授權碼狀態(tài),支持遠程吊銷
如果是企業(yè)級產(chǎn)品,建議采用服務器+本地加密結合的方式,避免破解和濫用。
上代碼
管理員:
1.生成公鑰私鑰
import rsa # 生成 2048 位密鑰 (public_key, private_key) = rsa.newkeys(2048) # 保存私鑰(供授權中心使用) with open("private.pem", "wb") as priv_file: priv_file.write(private_key.save_pkcs1()) # 保存公鑰(供客戶端使用) with open("public.pem", "wb") as pub_file: pub_file.write(public_key.save_pkcs1()) print("RSA 密鑰對已生成:private.pem(私鑰) 和 public.pem(公鑰)")
2.生成授權文件
import rsa import json import base64 import os from datetime import datetime # 讀取私鑰 with open("private.pem", "rb") as priv_file: private_key = rsa.PrivateKey.load_pkcs1(priv_file.read()) # 獲取目標設備的 CPU ID # def get_machine_id(): # try: # if os.name == 'nt': # machine_id = os.popen("wmic cpu get ProcessorId").read().split()[1] # print('授權設備的唯一標識:'+machine_id) # else: # return os.popen("cat /etc/machine-id").read().strip() # except: # return "UNKNOWN" # 生成授權文件 def generate_license(user, expire_date, machine_id): license_data = { "user": user, "expire": expire_date, "machine_id": machine_id } print(license_data) # 簽名授權數(shù)據(jù) data_str = f"{user}|{expire_date}|{machine_id}".encode() signature = rsa.sign(data_str, private_key, 'SHA-256') # 添加簽名并保存 JSON license_data["signature"] = base64.b64encode(signature).decode() with open("license.json", "w") as license_file: json.dump(license_data, license_file, indent=4) print("? 授權文件 license.json 生成成功!") # 示例:為某個客戶生成授權 generate_license(user="client1", expire_date="2025-12-31", machine_id="機器碼")
3.授權文件格式
{ "user": "client1", "expire": "2025-12-31", "machine_id": "BFE***ED", "signature": "R62******8/w==" }
4.要被授權控制的軟件
import os import time import threading import json import tkinter as tk from tkinter import messagebox, ttk from datetime import datetime import boto3 import configparser from elasticsearch import Elasticsearch from urllib3.exceptions import InsecureRequestWarning import warnings import base64 import logging # 添加 logging 模塊 import rsa import hashlib from botocore.exceptions import ClientError, EndpointConnectionError warnings.filterwarnings("ignore", category=InsecureRequestWarning) # ==================== 配置日志 ==================== logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', filename=f'logs/file_search_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log', filemode='w' ) logger = logging.getLogger(__name__) # ==================== 授權管理 ==================== LICENSE_FILE = "license.json" PUBLIC_KEY_FILE = "public.pem" def get_machine_id(): """ 獲取當前設備的唯一標識(CPU ID)""" try: if os.name == 'nt': machine_id = os.popen("wmic cpu get ProcessorId").read().split()[1] print('獲取當前設備的唯一標識:'+machine_id) return machine_id else: return os.popen("cat /etc/machine-id").read().strip() except: return "UNKNOWN" def load_rsa_public_key(): """ 加載 RSA 公鑰 """ try: with open(PUBLIC_KEY_FILE, "rb") as f: return rsa.PublicKey.load_pkcs1(f.read()) except Exception as e: logger.error(f"無法加載公鑰: {e}") messagebox.showerror("授權錯誤", "授權系統(tǒng)異常,無法加載公鑰") exit(1) def verify_license(): """ 驗證授權碼 """ if not os.path.exists(LICENSE_FILE): messagebox.showerror("授權錯誤", "未找到授權文件,請聯(lián)系管理員") exit(1) try: with open(LICENSE_FILE, "r") as f: license_data = json.load(f) user = license_data.get("user") expire = license_data.get("expire") machine_id = license_data.get("machine_id") signature = base64.b64decode(license_data.get("signature")) if not all([user, expire, machine_id, signature]): messagebox.showerror("授權錯誤", "授權文件損壞") exit(1) # 校驗過期時間 if datetime.strptime(expire, "%Y-%m-%d") < datetime.now(): messagebox.showerror("授權錯誤", "授權已過期,請聯(lián)系管理員續(xù)費") exit(1) # 校驗機器碼 if machine_id != get_machine_id(): print(machine_id) print(get_machine_id()) messagebox.showerror("授權錯誤", "設備不匹配,授權無效") exit(1) # 驗證簽名 public_key = load_rsa_public_key() data_str = f"{user}|{expire}|{machine_id}".encode() try: rsa.verify(data_str, signature, public_key) except rsa.VerificationError: messagebox.showerror("授權錯誤", "授權碼無效或被篡改") exit(1) logger.info("授權驗證成功") except Exception as e: logger.error(f"授權驗證失敗: {e}") messagebox.showerror("授權錯誤", "授權文件無效") exit(1)
5.將公鑰和授權json文件放在要授權的程序下
6.運行效果
python main.py
獲取當前設備的唯一標識:178B****F10
7.修改授權文件任性信息授權報錯
到此這篇關于python授權加密的文章就介紹到這了,更多相關python授權加密內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
WxPython開發(fā)之實現(xiàn)表格數(shù)據(jù)導出到Excel并打開
在 Python 中使用 wxPython 導出實體類列表數(shù)據(jù)到 Excel,通常可以借助 openpyxl 或 pandas 庫來實現(xiàn),下面就跟隨小編一起來了解下具體操作吧2024-12-12Python 實現(xiàn)數(shù)據(jù)結構中的的棧隊列
這篇文章主要介紹了Python 實現(xiàn)數(shù)據(jù)結構中的的棧,隊列,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05python?pandas分割DataFrame中的字符串及元組的方法實現(xiàn)
本文主要介紹了python?pandas分割DataFrame中的字符串及元組的方法實現(xiàn),主要介紹了3種方法,具有一定的參考價值,感興趣的可以了解一下2022-03-03Python中unittest的數(shù)據(jù)驅動詳解
這篇文章主要介紹了Python中unittest的數(shù)據(jù)驅動詳解,數(shù)據(jù)驅動測試,是一種單元測試框架,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08python的xpath獲取div標簽內html內容,實現(xiàn)innerhtml功能的方法
今天小編就為大家分享一篇python的xpath獲取div標簽內html內容,實現(xiàn)innerhtml功能的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-01-01