ANSI_X_9.17的伪随机数产生器

ANSI_X_9.17的伪随机数产生器

第5章密钥分配与管理.ppt 下载

代码用到了三重DES加密,正好之前写分组时写完了DES,直接导来用了。

DES加解密基础实现 | mednight4

原理

可以简单理解为不用random来实现随机数的生成。

关键点

64位日期的生成。由于之前写DES时底层的0和1用的是字符而不是位运算,所以在此日期转64位bit只能转为字符串了。

64位日期格式,我想到了np.datetime.now()

1
2
3
4
5
6
7
from datetime import datetime
import numpy as np
now = datetime.now()
now=np.datetime64(now)
print(now,type(now))
# 2020-12-02T20:06:20.571603 <class 'numpy.datetime64'>
# 是numpy的64位日期对象哦。

然后既然要字符串,就把对象序列化好了:

1
2
3
import pickle
print(pickle.dumps(now))
# b'\x80\x03cnumpy.core.multiarray\nscalar\nq\x00cnumpy\ndtype\nq\x01X\x02\x00\x00\x00M8q\x02\x89\x88\x87q\x03Rq\x04(K\x04X\x01\x00\x00\x00<q\x05NNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK\x00}q\x06(C\x02usq\x07K\x01K\x01K\x01tq\x08\x86q\ttq\nbC\x08\xd3\x1f\xe0\xc6\x80\xb5\x05\x00q\x0b\x86q\x0cRq\r.'

出来了一坨神奇的东西。。。暂定这种办法是无效的,但似乎也没有直接生成64位日期的函数,无奈之下,只有自己转了。

python的time.time()来生成一个当下的时间戳,时间应该是精确到秒以下的,能保证每一轮取时间参数时它的值都不一样。格式大概这个样子:

1606909814.5311575

去掉标点符号后15-17位不等,4位bin表示一个hex,64的话我们需要16个数,我直接将dec当成hex了,问题不大。位数不够的话右边填个零补齐,list.ljust(16,'0'))

原理要求每次从初态读取数据,结合当下的时间与密钥K1,K2,经过异或,DES等操作,得到一个伪随机数。这样的话哪怕知道了初态和生成时间,不知道K1和K2,所以随机数是很难破解的。

那么为了保证每次的初态不同,干脆把每次运行完的末态存进文件,下一次运行直接从文件读取上次运行的状态作为初态。

代码

ANSI_X9_17.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
"""ANSI X 9.17的伪随机数产生器"""
import time
import yaml
from DES.function import xor
from DES.function import hex2bin
from DES.function import bin2hex
from DES.en_for3 import en_for3


def TD(DT, K1, K2):
"""三重DES"""
return en_for3(DT, K1, K2)


def DTi(present):
"""DTi(64):当前日期与时间, 每产生一个Ri后,自动更新一次"""
# 这64位时间的生成应该也是仅此一家了
now = list(str(present).ljust(16, '0'))
now.remove('.')
return "".join([hex(int(i))[2:] for i in (now[:16])])


def one_circle(present, K1, K2, Vi):
"""一轮加密"""
print("present,Vi,K1,K2\n", present, Vi, K1, K2)
value1 = TD(DTi(present), K1, K2)
value2 = bin2hex("".join(xor(hex2bin(Vi), hex2bin(value1))))
Ri = TD(value2, K1, K2)
value4 = bin2hex("".join(xor(hex2bin(value1), hex2bin(Ri))))
Vi_next = TD(value4, K1, K2)
# 生成随机数
print("种子:", Ri, "\tVi+1:", Vi_next)
return Ri, Vi_next


def init(from_file=False):
Vi = "AAAAAAAAAAAAAAAA"
K1 = "AAAAAAAAAAAAAAAA"
K2 = "AAAAAAAAAAAAAAAA"
if from_file:
try:
with open("init.yaml", "r") as f:
params = yaml.load(f.read(), Loader=yaml.SafeLoader)
Vi, K1, K2 = params['Vi'], params['K1'], params['K2']
except:
pass
return Vi, K1, K2


def generation(num_circle):
Vi, K1, K2 = init(True)
result = []
for num in range(num_circle):
present = time.time()
Ri, Vi = one_circle(present, K1, K2, Vi)
result.append(Ri)
params = {
"Vi": Vi,
"K1": K1,
"K2": K2,
}
with open("init.yaml", "w") as f:
f.write(yaml.dump(params))
return result


print(generation(1))