本节内容我们将学习混沌序列的随机性测试,那么前面讲了,混沌系统产生的随机序列,它的随机性到底好不好,除了看相图、分岔图、指数图以外,还有一个非常重要的指标,那就是FIPS 140-2测试和SP800-22测试。随机序列需要进行FIPS 140-2测试和SP800-22测试的原因如下:
(1)保证密码学模块的安全性:密码学模块在加密和解密敏感信息时使用随机数生成器来增加对手动解密和猜测攻击的抵抗力。通过进行FIPS 140-2测试,可以验证密码学模块是否符合安全标准,确保其实施和设计的安全性,以有效地保护敏感信息。
(2)确定随机序列的随机性质:随机序列的质量和随机性对于许多应用很重要,例如密码学、模拟、加密算法等。SP800-22测试提供了一系列严格的统计测试和随机性分析,用于评估随机序列的质量。通过这些测试,可以确定随机序列是否具有良好的统计特性、无可预测性和抵抗性,以确保其适用于相应的应用。
(3)防止基于伪随机性的攻击:如果随机数生成器生成的序列存在规律或可预测的模式,攻击者可能会利用这些弱点进行攻击。FIPS 140-2测试和SP800-22测试能够检测并确保随机数生成器生成的序列具有足够的随机性、不可预测性和安全性,以防止基于预测的攻击。
FIPS 140-2测试是由美国国家标准与技术研究院(NIST)所制定的一套密码学模块的安全性标准,适用于用于加密和解密敏感信息的应用程序和设备。主要目的是确保密码学模块的设计和实施符合安全标准,以保护敏感信息不受未经授权的访问和攻击。
FIPS 140-2测试包含四个不同的安全级别(Level 1至Level 4),每个级别有一系列的要求和测试。其中,要求包括随机数生成器(RNG)的要求和随机数生成过程的精确指定,以确保生成的随机数足够随机、不可预测和安全。
下面我们还是用logistic混沌映射为例,迭代20000次,通过python测试出结果如下,可以看出能通过FIPS 140-2测试
SP800-22测试是NIST发布的一项特殊出版物,目的是评估随机数生成器的质量和随机性。这些测试方法可以用于各种各样的随机性检测场景,并且是各种安全标准和规范的基础。
SP800-22测试提供了一系列统计测试和随机性分析,用于检查生成的随机数序列是否具有良好的统计特性和随机性。其中包括频次测试、卡方测试、最长序列测试、游程测试、秩测试等。
由于篇幅有限,FIPS 140-2测试代码在下面已给出,SP800-22测试的随机性测试代码有需要的读者私信我。
import numpy as np
def logistic_map(x0, r, n):
"""Logistic map implementation"""
x = np.zeros(n)
x[0] = x0
for i in range(1, n):
x[i] = r * x[i - 1] * (1 - x[i - 1])
return x
def sequence_map(x0, r, N):
"""Logistic map implementation"""
X = np.zeros(N)
SX = np.zeros(N)
X[0] = x0
for i in range(1, N):
X[i] = r * X[i-1] * (1 - X[i-1])
SX[i-1] = np.mod(np.floor((X[i] + 100) * 2**16), 2)
return SX
def fips_140_2_monobit_test(sequence_output):
"""Perform FIPS 140-2 monobit test"""
k1 = np.sum(sequence_output)
k0 = len(sequence_output) - k1
return k1, k0
def fips_140_2_poker_test(sequence_output):
"""Perform FIPS 140-2 poker test"""
f = np.zeros(16).tolist()
SX = sequence_output
for i in range(1, 5000):
v = int(SX[4 * i - 3 - 1] * 8 + SX[4 * i - 2 - 1] * 4 + SX[4 * i - 1 - 1] * 2 + SX[4 * i - 1])
f[v] = f[v] + 1
for i in range(len(f)):
f[i] = f[i] ** 2
p = sum(f) * 16 / 5000 - 5000
return p
def fips_140_2_runs_test_and_fips_140_2_long_runs_test(sequence_output, N):
SX = sequence_output
run0 = np.zeros(100) # 求得长度为1~100的0游程个数
run1 = np.zeros(100) # 求得长度为1~100的1游程个数
t0 = 0 ; t1 = 0
for i in range(1, N):
if i == 1:
if SX[i-1] == 1:
t1 = 1
else:
t0 = 1
if i == N:
if SX[i-1] == 1 and t1 > 0:
t1 = t1 + 1
run1[t1-1] = run1[t1-1] + 1
if SX[i-1] == 0 and t0 > 0:
t0 = t0 + 1
run0[t0-1] = run0[t0-1] + 1
if SX[i-1] == 1 and t1 == 0:
run1[0] = run1[0] + 1
run0[t0] = run0[t0] + 1
if SX[i-1] == 0 and t0 == 0:
run0[0] = run0[0] + 1
run1[t1-1] = run1[t1-1] + 1
else:
if SX[i-1] == 1 and t1 > 0:
t1 = t1 + 1
if SX[i-1] == 0 and t0 > 0:
t0 = t0 + 1
if SX[i-1] == 1 and t1 == 0:
t1 = 1
run0[t0-1] = run0[t0-1] + 1
t0 = 0
if SX[i-1] == 0 and t0 == 0:
t0 = 1
run1[t1-1] = run1[t1-1] + 1
t1 = 0
return run0, run1
# Parameters for logistic map
x0 = 0.1 # Initial value
r = 4 # Control parameter
n = 800 # Number of iterations
N = 20000 # Number of iterations
# Generate logistic map output
logistic_output = logistic_map(x0, r, n)
X0 = logistic_output[-1]
sequence_output = sequence_map(X0, r, N)
# Perform FIPS 140-2 tests
monobit_test_result_k1, monobit_test_result_k0 = fips_140_2_monobit_test(sequence_output)
poker_test_result = fips_140_2_poker_test(sequence_output)
run_test_result_0, run_test_result_1 = fips_140_2_runs_test_and_fips_140_2_long_runs_test(sequence_output, N)
print(f"单位比特测试1的个数为: {monobit_test_result_k1}")
print(f"单位比特测试0的个数为: {monobit_test_result_k0}")
print(f"扑克测试为: {poker_test_result}")
print(f"0游程测试长度1为: {run_test_result_0[0]}")
print(f"0游程测试长度2为: {run_test_result_0[1]}")
print(f"0游程测试长度3为: {run_test_result_0[2]}")
print(f"0游程测试长度4为: {run_test_result_0[3]}")
print(f"0游程测试长度5为: {run_test_result_0[4]}")
print(f"0游程测试长度大于等于6为: {sum(run_test_result_0[5:99])}")
print(f"0长游程测试为: {sum(run_test_result_0[25:99])}")
print(f"1游程测试长度1为: {run_test_result_1[0]}")
print(f"1游程测试长度2为: {run_test_result_1[1]}")
print(f"1游程测试长度3为: {run_test_result_1[2]}")
print(f"1游程测试长度4为: {run_test_result_1[3]}")
print(f"1游程测试长度5为: {run_test_result_1[4]}")
print(f"1游程测试长度大于等于6为: {sum(run_test_result_1[5:99])}")
print(f"1长游程测试为: {sum(run_test_result_1[25:99])}")