动态密码设计

一、需求

我们一开始构想动态密码的使用场景是这样的:

(1)现场人员查看设备ID,把ID发给设备管理人员。

(2)设备管理人员登录平台,用设备ID换取动态密码,并把动态密码发给现场人员。

(3)现场人员把密码输入仪器,使用最高权限。

这样的流程是比较安全的,唯一的缺陷是现场人员每次使用都要找设备管理人员,人力成本极高。正是这个缺陷,导致这一方案直接推翻。

 

我们考虑另外一个使用场景:

(1)设备管理人员为现场人员登记信息(一次性)。

(2)现场人员在需要使用最高权限时,自己登录平台,获取动态密码。

(3)操作过后,仪器记录现场人员的信息。

在这个场景之下,设备管理人员人力成本得以降下,但也引出了一些安全性问题。在这个场景之下,现场人员希望什么时候使用最高权限就什么时候使用,没有人可以管。两个场景都有缺陷,综合考虑,选择后者。

在第二个场景之下,我们发现,让现场人员输入设备ID是没有意义的。他想操作多个设备,只需要获取多次动态密码即可。所以我们取消输入设备ID这个步骤。

 

动态密码需要满足这些需求:

(1)足够简单,用阿拉伯数字,最初考虑使用6个数字,明显无法实现,考虑使用8个数字。

(2)密码中包含用户信息。

(3)为防止被旁人窃取密码,每个密码只能使用一次。

(4)密码有有效时间,考虑在同一天内有效。

(5)第2点同时也引出了这个需求:密码每次都不一样。

(6)密码被篡改后,判定为非法密码。

 

二、设计

从第2点需求和第4点需求可以看出,密码中必须包含用户信息和时间信息,而从第6点又可以看出,密码需要有校验信息。这么多的信息需要在8个阿拉伯数字里表现,是设计的难点。

 

为了节省空间,我们把信息精确到二进制位。首先我们需要明确我们的目标:8个阿拉伯数字,能表示的最大的数就是2的26次方(67108864),也就是说,26位是我们的上限。

使用12位代表4096个不同的用户,基本满足需求。只剩下14位可用了。

时间信息需要保存年月日,如果使用一个字节保存一个数字(例如BCD码),共需要24位(3个字节),一下子就超了。把它们拆分,精确到位,最省的情况如下表所示:

信息

所需位

6

4

5

这样的话,我们省了很多,但仍然用掉了15位,超出了我们的限额。我们希望在时间信息上挤出空间来。

 

我们假设有这样一个函数f(y,m,d),它把时间信息转化成一个数,不同的日期对应不同的值,不会重复。考虑最简单的情况,我们把函数定义成如下形式:

f(y,m,d)=ay+bm+cd

那么,另外一个日期对应的值为:

f(y’,m’,d’)=ay’+bm’+cd’

只要在y!=y’,m!=m’,d!=d’的情况下,f(y,m,d)!=f(y’,m’,d’)即满足需求。

f(y,m,d)-f(y’,m’,d’)=(ay+bm+cd)-(ay’+bm’+cd’)

              =a(y-y’)+b(m-m’)+c(d-d’)

由于年的变化是很缓慢的,我们考虑在一年内,都没有重复的值。也就是

b(m-m’)+c(d-d’)=bΔm+cΔd!=0

即bΔm!=-cΔd

我们知道,月的变化取值为1-12,日的变化取值为1-31,那么Δm的取值为-11~11,Δd的取值为-30~30。考虑到有负数的存在,上式我们直接可以写成:

b/c!=Δd/Δm

我们可以看出,只要b取31,上式两边就永远不会相等。也就是说,

f(y,m,d)=y+31m+d

在一年内也不会有重复的值。

这样的话,此式最大的值为31*12+31+99(考虑年用到2099)=502,我们用9位(512)即能表示。

 

经过上面的时间信息缩减之后,我们剩下5位来存放校验信息。常见的一些校验算法根本是无法使用的(MD5要16字节,而且计算复杂,CRC两个字节,最简单的算LRC也要一个字节8位)。如果单纯用5位做校验和,重复的概率是1/32,感觉不够安全。

我们已经没办法再缩减时间信息使用的位数,只能考虑对用户ID开刀。用户ID使用12位存放4096个用户的信息,这是我们考虑极限的用户数。在一开始,或许512个用户就能满足。于是,我们采取这样的折中方案:

(1)用户ID使用9位,把3位让给校验和,这样重复的概率是1/256,应该是可以使用的。

(2)当用户增长超过512时,我们增加数字位数。如果使用9位阿拉伯数字,我们可以存放29位的信息,多出3位,增加在用户ID上,一共可存放4096个用户。

 

上面的设计,还没有满足需求里的第3、5点。要让密码每次都不一样,其实我们只需要增加几位,放一个随机数就行。但偏偏我们已经没有空间去放这个随机数了。

在这里,我们需要先说明使用何种加密方法。为了足够的简单(保证仪器能快速计算),又不失安全性,我们使用异或的加密方法。只要用户猜不到跟明文异或的密码,数据就是安全的。

我们回到上面的问题。如果我们使用不同的密码去对明文进行异或,得到的结果就是不一样的。所以我们有一种这样的方案:存放N条用于异或的密码,每次用不同的密码去异或,就会产生不同的结果。解密的时候,我们寻回原先异或的密码,就能成功解密。

但是我们马上会发现问题:我们如何知道明文是使用了哪个密码去异或的呢?用户ID和时间信息都是固定的,我们无法从这些信息里面提取出一个索引。那我们可以使用当前时间作为一个索引。假如我们有24个密码,各对应24个小时。这样的话,我们在使用动态密码时,会多出一条限制:从平台上获取密码之后,必须在一个小时内使用。这样的限制并不影响,可行。

在我们使用多个密码去异或时,原来的校验和算法会出现问题。我们必须找出24个异或码,经过跟明文异或之后,不影响原文的校验和。这样的异或码可以使用以下方法得到:

(1)因为我们使用8位校验和,所以我们把数据分成8位一段,不够的使用0补齐。

(2)把(总位数-8)个位随机填充0或1。

(3)求出(总位数-8)个位的校验和。

(4)把这个校验和填充到剩下的8位里面。

 

三、最终方案

动态密码的设计如下:

8位阿拉伯数字

信息

时间

校验和

用户ID

位数

9

8

9

 

9位阿拉伯数字

信息

时间

校验和

用户ID

位数

9

8

12

 

时间=(年-2018)+31*月+日

校验和为8位一段异或。

加密方法是将整个明文跟密钥进行异或。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值