我遇到个需求:需要给离线程序加一道锁,防门外汉的那种。因为离线程序遇到高手,肯定是会被破解的。像IntelliJ全家桶这样超大型软件,都无法防止用户的暴力破解。何况我这小打小闹的玩意。所以,目的就是防止一些普通的程序员也能轻易破解软件。

实现效果

假设已经开发了一个桌面应用“test.exe”(该软件不联网),那么每次安装程序的时候,都需要输入验证码(激活码)才能安装,该激活码需要向软件所有者索要。从而达到了防止程序被随意拷贝安装使用的目的。

那么验证码如何才能实现实时更新且由软件所有者提供呢?

实现方法

我想到的方法是根据时间,来生成一个验证码。为什么要根据时间呢?因为离线程序和软件所有者,所拥有的相同的元素,可能就是时间了。

当然验证码校验的方式肯定是:离线程序和软件所有者拥有一样的验证码生成算法,这样才能保证验证码能通过验证。
所以这种方案的缺陷便是:只要验证码生成算法被破解,那么防御就失效。而破解这个算法难度也不会很大,只要对程序代码进行分析,找到加密所在的代码,即可破解。毕竟离线程序的代码都在计算机本地,高手自然有手段对代码进行逆向,再分析。

不过程序员都知道,分析别人写的代码是一件很恶心的事,特别是拿到的还不是源码(没有注释,可能变量名也被混淆了),只是逆向出来的代码。可读性很差。所以破解离线程序的代价也是很大的。所以稍微加一点防御措施,也能让不少人望而却步。

好了,目的和意义交代完了,进入主题。

验证码生成算法

验证码有以下特点:

  1. 无规律
  2. 有时效性

上面说到,我能想到的离线程序和软件所有者之间的共有要素只能想到“时间”。时间是随时在变化的。对时间加以处理,便可以得到无规律的验证码。

验证码生成的时间点

我们时间常用的精度是秒。如果我们每秒都生成一个验证码的话,那么验证码的量很大,且时效性太短,没有意义,所以我选择以分钟为单位来生成验证码。当然,也可以根据需要,以小时,天为单位生成验证码。

import time
timeStamp = int(time.time())  # 取时间戳,并转化为整数
minTime = timeStamp - timeStamp % 60  # 取余60得到当前秒数,减去秒数即得到分钟级别的时间戳

python默认获取的时间戳是秒级,且后面带有小数点,所以这两行就是先取整,然后把秒去掉,保留分钟级别的时间戳。

验证码的时效性

通常我们收到验证码时,都会提示验证码的有效时间为10分钟。
我为了实现类似的效果(总之就是保证验证码是在一段时间内有效的),想到了一个蠢办法:

将当前时间的前后15分钟范围内的验证码都生成出来,与软件所有者提供的验证码比对,只要有一个比对成功,就认为验证码正确。

这样做的目的是因为不联网的电脑的时间经常不准,差个几分钟很正常,所以我取正负15分钟,在大多数情况下确保软件所有者提供的验证码包含在这个范围内。

理解了这个思路,那么就可以根据自己的实际情况调整验证码的有效期。

for j in range(-15, 15):minTimeRange = minTime + 60 * j  # 加60秒即一分钟,每次加一分钟

保证验证码无规律

为了无规律,可以以时间戳为seed,生成随机数,这样基本也无规律,但是它有一个问题,它不能跨编程语言,也就是相同的seed,不能保证python和java生成的随机数相同。这就会为以后验证码校验制造困难。

你想想,软件所有者难道时时刻刻坐在电脑面前?索要验证码的人可不管你在不在电脑面前,他也不想等你回到电脑面前。这种时候,搞个app在手机上,用同样的算法实现,那么生成的验证码也能保证一致。安卓平台使用java开发的,桌面软件通常不用java,所以用随机函数不靠谱。

我就想到一个方法:

  1. 将前面获取的分钟级的时间戳转化为list,每个数字一个坑(这个时候注意最后一位数始终是0,所以实际处理时可以把尾数忽略掉)
  2. 初始化result=0,再初始化seed=131073(为保证验证码的位数为6位数,所以取刚迈进6位数的二进制数“100000000000000001”,换成别的数也可以达到一样的效果,只是获取的验证码位数不固定而已)
  3. 每次循环从list取一位数,将seed用位运算符“<<”移位list[i],然后再与result做异或运算。最终输出result

完整代码如下:

import timecheckCode = 530915 # 实际由软件所有者提供输入
flag = False
timeStamp = int(time.time())  # 取时间戳,并转化为整数
minTime = timeStamp - timeStamp % 60  # 取余60得到当前秒数,减去秒数即得到分钟级别的时间戳
seed = 131073  # 二进制100000000000000001 #为保证验证码的位数为6位数,所以取刚迈进6位数的二进制数,换成别的数也可以达到一样的效果。
# 由于正式环境的机子时间不一定准确,但也不考虑非常不准确的情况,通常与准确时间的差值不会超过10分钟
# 取[-15,15)范围是因为保证验证码是在一定范围内都是有效的。即正式环境的当前时间的正负15分钟涵盖了验证码生成的那个时间,验证码即可校验正确
for j in range(-15, 15):minTimeRange = minTime + 60 * j  # 加60秒即一分钟,每次加一分钟numList = list(map(int, str(minTimeRange))) # 将时间戳每一位数转化为listresult = 0for i in range(0, len(numList) - 1): # 末尾数都为0,所以我不处理他result = result ^ (seed << numList[i])if result % 1000000 == checkCode: # 取结果的末六位数与验证码比对flag = Truebreakprint(flag)

代码很短。主要是提供个思路。
上面还得注意一点,用seed=131073可以保证result>100000(即保证有6位数及以上),但是 result % 1000000却不能保证得到的验证码一定是6位数,因为如果末六位的前几位数为0,则取余的结果就不是6位数了。要想保持6位数,需要在前面补0。或者干脆转换成字符串再去取末六位。比对的时候也拿字符串进行比对就没问题。我这里对验证码位数没要求,所以就无所谓了。

PS:对于代码中的seed=131073的设计是否是最优的,我觉得不是,只是这个数达到了我想要的效果,所以我就用它了。

让离线程序也需要输入校验码(激活码)才可使用(python实现)相关推荐

  1. 杀毒软件 杀毒软件授权码/激活码

    防火墙,杀毒软件授权吗/激活码等等 授权码激活码一般都在1~3天更新一次 一般不会拉黑 www.zhangqaz0122.id666.com

  2. Python 实现 优惠码/激活码/邀请码 生成器

    Python 练习册 的第0001题 描述:做为 Apple Store App 独立开发者,你要搞限时促销,为你的应用生成激活码(或者优惠券),使用 Python 如何生成 200 个激活码(或者优 ...

  3. Axure rp9 3658可用注册码 授权码 激活码 key 亲测可用

    axure rp9 官网正式版,3658版本以上注册码,激活码,key值. axure rp9 官网正式版,3658版本以上注册码,激活码,key值. 本人亲测可用.请查看截图. 激活码见附件.

  4. MacBooster 7 mac 破解版永久激活方法无需激活码

    还在嫌弃自己的Mac电脑运行慢?那就快来下载MacBooster 7 for Mac这款软件,这是是一款专为Mac用户设计的系统优化和清理软件,功能强大,支持快速释放内存,卸载应用.查找重复文件.管理 ...

  5. MacBook PyCharm激活码

    关注我的微信公众号:pythonislover,领取python,大数据,SQL优化相关视频资料!~ Python大数据与SQL优化笔 QQ群:771686295 永久激活 1.下载补丁 注意下载后不 ...

  6. MacBook IDEA激活码

    关注我的微信公众号:pythonislover,领取python,大数据,SQL优化相关视频资料!~ Python大数据与SQL优化笔 QQ群:771686295 永久激活 1.下载补丁 注意下载后不 ...

  7. 点盾云输入激活码激活视频时,显示鉴权失败无效激活码怎么办?

    如今许多培训机构或者经营网课视频的商家,都会选择使用点盾云视频加密软件来保护自己的视频不被随意传播泄漏传播.那么在使用过程中或多或少会遇到一些不明白的问题,遇到不明白不知道怎样处理的问题应该怎么办呢? ...

  8. 编写一个程序,要求输入一个ASCII码值(如66),然后输入相应的字符`

    编写一个程序,要求输入一个ASCII码值(如66),然后输入相应的字符` #include <stdio.h>int main(void) {int ch;scanf("%d&q ...

  9. 编写一个程序,要求输入一个ASCII码值(如66), 然后输出相应的字符。

    编写一个程序,要求输入一个ASCII码值(如66), 然后输出相应的字符. /**编写一个程序,要求输入一个ASCII码值(如66), 然后输出相应的字符.** */#include <stdi ...

最新文章

  1. ZABBIX(八) Zabbix 通知媒介
  2. python中国大学排名爬虫写明详细步骤-【Python爬虫】从html里爬取中国大学排名...
  3. 大学计算机等级培训卷子,大学计算机期中考试试卷示例.doc
  4. 二分图的最大匹配 匈牙利算法
  5. python 创建空的numpy数组_Numpy入门教程:01. 数组的创建与属性
  6. 我的领域驱动设计运用实例 - 领域啊领域
  7. notebook打开外部文件_CAD外部参照真是个好东西!
  8. 数据结构-图及其遍历
  9. 网站转移服务器,网站转移云服务器
  10. 有趣!让你的桌面独一无二——iWall for Mac2.1.1破解版可以交互的动态桌面壁纸!
  11. ios12越狱自签需要联网_从越狱的iOS切换到Android? 这是你需要知道的
  12. 用移动硬盘当系统盘,即插即用
  13. 为防止程序员猝死,这家公司想出了一个好办法
  14. 2018 蓝桥杯省赛 B 组模拟赛(一)青出于蓝胜于蓝(DFS序+树状数组)
  15. 阿里云前端周刊 - 第 13 期 1
  16. liunx更改root@后面的主机名
  17. 计算机老师开学第一堂课,开学第一堂课作文
  18. 利用autossh反向代理实现内网穿透
  19. 统计数据自动补全不存在日期 天
  20. XStream分析(2)

热门文章

  1. opencv图像特效之油画特效
  2. 招商引资迎来开门红,长沙望城拼经济起步就起势
  3. 文明6怎么修改计算机用户名,文明6领袖特性修改教程 文明6怎么修改领袖特性...
  4. fiddler导致浏览器不是私密连接
  5. 基于Voronoi图的自定义轮廓内的随机纹路生成
  6. MQ消息队列的重复消费问题的通用解决办法以及幂等性的原理
  7. 47页电子书!全面了解3D打印塑料材料种类、属性和应用
  8. 小区业主入户安检小程序开发
  9. 【Web】JavaScript实现九九乘法表格
  10. 一号店java面试题