Python 实战:如何给你的程序添加授权码机制_使用软件,作者要mac地址后给授权-程序员宅基地

技术标签: python  授权码  编程语言  

大家好,我是机灵鹤。

前几天有个粉丝问我说,他写了一个蛮有意思的小程序,准备在网上发布,但是又担心程序在不受控制的情况下传播。想问我有没有办法整一个授权码机制,只有输入授权码才能使用软件,授权码过期或者更换机器都需要重新授权。

真是蛮有意思又非常实用的一个小需求,以后如果想要分享自己的程序但又不希望自己的程序被随意传播的,都可以用得上。

这里给大家简单分享一下我的实现方法,感兴趣的同学可以学起来。

如果你有其它比较好的思路,也欢迎跟我一起交流。


一、总体思路

软件授权方案大概分成两个部分:程序本体注册机

当用户启动程序时,程序会检验本地的 授权文件 是否合法,若验证通过,则直接进入程序,若未找到授权文件或者授权文件校验失败,则进入重新授权流程。进入授权流程时,程序先扫描本机运行环境,生成 机器码 ,然后提示用户找管理员获取授权码;用户将机器码发送给管理员,管理员将机器码输入 注册机 中,生成与该机器码唯一绑定的 授权码 后,发送给用户;用户在程序中输入授权码,验证通过后正式进入程序,并在本地生成授权文件。

下面是我的软件授权方案的流程图。

授权流程图

以上便是我这套软件授权方案的总体思路,接下来,我会教大家如何用 python 来实现它。

二、实现过程

实现这套授权机制,我们需要解决以下几个小问题。

  1. 如何使授权码与机器唯一绑定,仅在本台机器上有效?
  2. 如何生成验证码,以及如何验证授权码是否有效?
  3. 如何保护自己的授权码不那么容易被人破解?

带着这些问题,我们继续往下看。

2.1 获取机器信息

要回答第一个问题,首先要搞明白,软件如何判断自己运行在哪一台机器上?

我们知道,每一台机器都会有一个唯一 Mac 地址,我们可以用它来作为机器的唯一标识。

此外为了保险,我们还可以获取机器的 CPU 序列号硬盘序列号主板序列号 等等数据,与 Mac 地址 共同作为一台机器的唯一标识。

windows 系统下,我们可以使用 wmi 的库来获取机器的硬件信息。

没有安装 wmi 库的,可以运行下面的命令行来安装。

pip install wmi
2.1.1 获取 CPU 序列号
import wmi

m_wmi = wmi.WMI()
cpu_info = m_wmi.Win32_Processor()
if len(cpu_info) > 0:
	serial_number = cpu_info[0].ProcessorId
    print(serial_number)
2.1.2 获取 MAC 地址
import wmi

m_wmi = wmi.WMI()
for network in m_wmi.Win32_NetworkAdapterConfiguration():
    mac_address = network.MacAddress
    if mac_address != None:
        print(mac_address)
2.1.3 获取硬盘序列号
import wmi

m_wmi = wmi.WMI()
disk_info = m_wmi.Win32_PhysicalMedia()
if len(disk_info) > 0:
    serial_number = disk_info[0].SerialNumber.strip()
    print(serial_number)
2.1.4 获取主板序列号
import wmi

m_wmi = wmi.WMI()
board_info = self.m_wmi.Win32_BaseBoard()
if len(board_info) > 0:
    board_id = board_info[0].SerialNumber.strip().strip('.')
    print(board_id)

2.2 生成机器码

使用上述方法,我们可以获取到机器的 CPU 序列号硬盘序列号主板序列号Mac 地址 信息,通过这些信息,我们便可以生成唯一标识一台机器的 机器码

理论上,我们将这些数据直接进行字符串拼接,便可作为机器码使用,但是实际上,这样做存在一些问题。

  1. 机器码过长,使用体验不太友好。
  2. 直接暴露机器的硬件数据,有信息安全隐患。

所以我们需要对机器的这些硬件数据进行一些处理,生成一个长度适中的,既可以作为机器的唯一标识,又不会暴露机器硬件数据的机器码。

# 获取机器的 Mac地址、CPU序列号、硬盘序列号、主板序列号
mac_address = get_mac_address()
cpu_serial = get_cpu_serial()
disk_serial = get_disk_serial()
board_serial = get_board_serial()

# 将机器的硬件数据字符串拼接
combine_str =  mac_address + cpu_serial + disk_serial + board_serial
combine_byte = combine_str.encode("utf-8")

# 进行 MD5 编码
machine_code = hashlib.md5(combine_byte).hexdigest()
print(machine_code.upper())

众所周知,MD5 是一种常用的不可逆的数据加密算法,我们用它对机器硬件数据进行加密,一方面它加密后的结果长度固定(32个字符),另一方面也可以在一定程度上保护数据安全。

2.3 授权验证逻辑

想要在离线的情况下实现 授权码机器码 唯一绑定,意味着授权码是由机器码经过一系列复杂的加密算法处理后得到的。

授权码验证的逻辑也比较简单,大概有三种思路:

  1. 将机器码使用相同的加密算法处理,得到的结果与验证码进行比较。
  2. 将验证码使用对应的解密算法处理,得到的结果与机器码进行比较。
  3. 使用特定的算法分别处理机器码和授权码,将得到的结果进行比较。

一般来讲,第一种思路实现起来会比较简单一些,因为它只需要写一套加密算法即可(软件验证部分跟授权码生成部分用的是同一套加密算法),而且无需考虑解密的问题,安全性会更高(因为可以使用不可逆的加密算法)

大概的验证逻辑如下:

# 获取机器码
machine_code = getMachineCode()
# 自己定义 Encrypted 函数进行加密处理
encrypt_code = Encrypted(machine_code.encode("utf-8"))

# 读取本地的授权文件
if os.path.exists("register.bin"):
    with open("register.bin", "r") as f:
        key_code = f.read()
        # 如果机器码经过加密后的值,等于授权码的值,则验证通过,否则验证失败
        if key_code == encrypt_code:
            print("验证通过")
        else:
            print("验证失败")
else:
    print("验证失败")

2.3 生成授权码

如何将机器码加密生成授权码,可以使用的加密算法其实五花八门,每个人都可以自己研究一套自己独有的加密方法,尤其是不需要考虑解密,不要求算法可逆的情况下,问题就更简单了。

比如:

  • 你可以提取机器码的奇数位或偶数位,或者自己定义的任意位置的字符出来,组合成授权码。
  • 可以将指定位置的字符进行交换,得到的字符串作为授权码。
  • 可以将其中的某些字符替换成其它字符,得到的字符串作为授权码。
  • 甚至可以直接再进行一次 MD5 加密,结果作为授权码。

总之,方法是非常多样化的,只要你生成的授权码可以正常使用,并且没那么容易让别人猜出你授权码生成的规律即可。

作为示例,我演示一下我 Demo 中的加密方法。

import base64
import hashlib
from pyDes import *

def Encrypted(self, code):
	# 使用 DES-CBC加密算法加密机器码
    Des_key = "posdvsgt" 				#自定义 Key,需八位
    Des_IV = "\x11\2\x2a\3\1\x27\2\0"  	# 自定IV向量
    k = des(Des_key, CBC, Des_IV, pad=None, padmode=PAD_PKCS5)
    EncryptStr = k.encrypt(code)
    # 加密结果转 base64 编码
    base64_code = base64.b32encode(EncryptStr)
	# 编码结果使用 MD5 加密
    md5_code = hashlib.md5(base64_code).hexdigest().upper()
    return md5_code

通过上述加密算法,我们可以通过机器码生成授权码,并且通过一系列加密算法的组合加密,基本上很难观察出机器码和授权码之间的关系,更没办法推算出你具体用了什么加密方法。

需要说明的是,

不管使用什么算法,凡离线方式的加密必然是可以被破解的,只是破解的时间和成本问题,所以上述的加密只是提高了破解门槛,防小白不防大神。

想要万无一失,还得是在线授权验证。

2.5 打包测试

核心算法搞定以后,整理一下代码就可以打包测试了。


可以使用 pyinstaller 库来把代码打包成 .exe 程序。

没有安装 pyinstaller 库的,可以运行下面的命令行来安装。

pip install pyinstaller

使用 pyinstaller 库打包的命令如下:

pyinstaller -F xxx.py

打包完成以后,会在当前目录下的 dist 文件夹中,生成 xxx.exe 可执行程序。


首次启动程序时(无授权文件),会提示输入激活码,即授权码。

随便输入错误的授权码,会验证失败,提示重新输入。

image-20221110185635873

此时我们启动注册机,根据提示复制机器码 BD1F7DF8646CD3A101C3DA8610672ED1 到注册机中,生成激活码。

image-20221110190013275

复制并输入激活码,此时授权验证成功,程序可以正常使用,输出了 Hello World! 字样。

image-20221110190611432

后续再次启动程序时,由于已有授权文件,所以可以直接进入。

image-20221111100332284

2.6 源码分享

为了方便大家学习交流,我将代码整理打包上传,并附上了一个 Demo 程序。

关注公众号 机灵鹤 并回复文字 授权码 ,即可获取。

感兴趣的同学可以自行下载,大家一起交流学习。

四、改进措施

当然,作为 V1.0 版本的授权码机制,其实还是有很多值得改进的地方,比如:

  • 设置授权有效期,过期则需要重新授权

  • 授权方式改成在线,安全性更高的同时也可以进行更加精细化的授权管理。

  • 授权后台管理系统,更加方便地管理自己的软件授权。

如果后续大家有需求,我也有精力的话,可以把它做的更加完善一些。


如果文章中有哪里没有讲明白,或者讲解有误的地方,欢迎在评论区批评指正,大家一起学习交流,共同进步。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wenxuhonghe/article/details/127880072

智能推荐

未来计算机发展应向着,计算机的发展、特点、分类及应用领域。-程序员宅基地

文章浏览阅读2.1k次。计算机的发展趋势,未来计算机性能应向着微型化、网络化、智能化和巨型化的方向发展。主要特点1.运算速度快:计算机内部电路组成,可以高速准确地完成各种算术运算。2.计算精确度高:科学技术的发展特别是尖端科学技术的发展,需要高度精确的计算。3.存储容量大:计算机内部的存储器具有记忆特性,可以存储大量的信息。4.自动化程度高:计算机具有存储记忆能力和逻辑判断能力,所以人们可以预先编好程序组然后纳入计算机内..._未来计算机都有哪些种类?有什么特点?

完美解决ASP.NET无法上传大文件方法-程序员宅基地

文章浏览阅读802次,点赞10次,收藏16次。需要提供前端源码,后端源码,控件源码,公司自己的项目,也有自己的产品,后续需要集成使用,提供7*24小时技术支持服务,提供文档教程,视频教程,远程技术指导,1对1技术支持服务,提供手机,微信,QQ,邮箱,企业微信等联系方式。要求支持断点续传,支持进度信息离线存储,用户可能传一半没有传完,下班了,明天上班后继续上传,电脑晚上到点需要关机,支持加密传输,支持国密加密算法SM4,要求能够在网页上面上传文件夹,文件夹里面大约有1万多个文件,有大有小,大的有1G~10G,小的有几MB,使用IIS Express。

可能是目前最全的《Android面试题大全》(中高级)(4),2024年最新android界面布局实验报告-程序员宅基地

文章浏览阅读657次,点赞12次,收藏19次。那我们该怎么做才能做到年薪60万+呢,对于程序员来说,只有不断学习,不断提升自己的实力。我之前有篇文章提到过,感兴趣的可以看看,到底要学习哪些知识才能达到年薪60万+。通过职友集数据可以查看,以北京 Android 相关岗位为例,其中 【20k-30k】 薪酬的 Android 工程师,占到了整体从业者的 30.8%!北京 Android 工程师「工资收入水平 」今天重点内容是怎么去学,怎么提高自己的技术。1.合理安排时间2.找对好的系统的学习资料3.有老师带,可以随时解决问题。

安装群晖系统入门图文教程-程序员宅基地

文章浏览阅读7.3k次。本教程基于Proxmox VE(PVE)7.1虚拟机环境下安装群晖,兼容这块简单说明:Intel酷睿四代以下或者志强处理器建议安装Ds3615-3617-3266等版本,四代以上可以安装918-920等版本,如果你``啥都不知道,安装Ds3615就对了。1.先删除删除local-lvm分区, 具体教程https://blog.csdn.net/u012514495/article/details/127318440。10.网络这里,因为引导包含虚拟机的驱动,所以不需要在进行额外设置,默认即可,继续下一步。_群晖系统

FreeMarker 自定义 TemplateDirectiveModel(一)-程序员宅基地

文章浏览阅读259次。FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等。一、Freemarker 的介绍​ Freemarker 是一款模板引擎,是一种基于模版生成静态文件的..._freemarker templatedirectivemodel 例子

微信小程序request请求封装,session封装,会话超时处理_微信小程序 请求封装 超时-程序员宅基地

文章浏览阅读544次。微信小程序request请求封装,session封装,会话超时处理直接上代码,代码中写了很详细的注释// 同时发送异步代码的次数let ajaxTimes = 0;export const request = (params, method) => { let header = { ...params.header, "Cookie": getApp().globalData.cookieStr, 'loc':'ajax' };//头部,小程序的头部是默认的 _微信小程序 请求封装 超时

随便推点

发作性睡病是否会遗传?-程序员宅基地

文章浏览阅读13次。研究还发现,发作性睡病患者的家族中,常常存在多个成员患有相同的疾病,这进一步表明了遗传因素在发作性睡病的发病中的重要性。因此,对于具有发作性睡病遗传倾向的人群,应该注意保持健康的生活方式和良好的心理状态,以降低患上发作性睡病的风险。但是,需要指出的是,虽然遗传因素在发作性睡病的发病中起到了重要的作用,但并不是所有具有遗传易感性的人都会患上发作性睡病。因此,即使具有发作性睡病的遗传倾向,通过保持健康的生活方式和良好的心理状态,也可以降低患上发作性睡病的风险。

node.js调用C++的一种方案_js调用c++库-程序员宅基地

文章浏览阅读3.6k次,点赞3次,收藏10次。nodejs官方维护了一套ABI(应用二进制接口),用于完成nodejs和C++的通信。官网介绍的是C API,对应的是它的C++版本,更容易使用,本文介绍的也是这个C++的版本。通过一个示例来说明如何使用node-addon-api。_js调用c++库

EMQX 5.0 全新网关框架:轻松实现多物联网协议接入_emqx连接对调物联网设备-程序员宅基地

文章浏览阅读1.4k次。本文将对EMQX全新的网关框架及功能使用进行详细解读,帮助读者更好地利用EMQX的多协议接入能力连接各类设备,满足更多物联网场景的数据接入需求。_emqx连接对调物联网设备

python并发与网络编程_python中for循环联网请求参数-程序员宅基地

文章浏览阅读475次。python并发与网络编程Linux 操作系统及其组成1.操作系统的作用​ 操作系统 : 与硬件交互​ 应用程序 --> 请求调用操作系统功能 --> 硬件调用(cpu,内存)​ 操作系统(OS)是管理计算机硬件与软件资源的计算机程序,同时也是计算机系统的内核与基石。操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入设备与输出设备、操作网络与管理文件系统等基本事务。操作系统也提供一个让用户与系统交互的操作界面。2.Linux 操作系统组成一个典型的 Linu_python中for循环联网请求参数

自定义注解+POI实现流式数据导入,支持各数据类型转换_poi 流式处理原理-程序员宅基地

文章浏览阅读7.1k次。自定义注解+POI实现流式数据导入,支持各数据类型转换_poi 流式处理原理

计算机组成原理【2022-10-24】_指令可以表示为二进制代码串-程序员宅基地

文章浏览阅读2.8k次,点赞2次,收藏5次。计算机组成原理是计算机的核心,主要包括计算机基本组件的构造、组织方式和设计思想,以及基本运算的操作原理。_指令可以表示为二进制代码串

推荐文章

热门文章

相关标签