我需要一个混洗函数,使用CSPRNG (加密安全伪随机数生成器),可以手动播种相同的种子相同的输出。
内置的random.shuffle() in Python可以手动设定种子,但它是not suitable for cryptographic use,将在Python3.11版本中删除。
据我所知,Crypto.Random.random.shuffle() from PyCryptodome不接受种子。
目前,我已经满足于由内置的random.shuffle()函数使用的Mersenne Twister来处理数字列表,但这远远不是理想的。作为内置的numpy.random.shuffle is not suitable for cryptographic purposes,混洗numpy数组也很受欢迎。数组/列表可能包含超过100亿个元素,因此性能和随机性是关键。
创可贴代码如下。
import numpy as np
from random import seed, shuffle
array = np.arange(10) # [0 1 2 3 4 5 6 7 8 9]
print(array)
seed(1)
shuffle(array)
print(array) # [6 8 9 7 5 3 0 4 1 2]发布于 2021-03-14 09:06:50
CSPRNG通常在重新播种等方面存在问题,在操作期间从操作系统内的熵池中提取熵。因此,最好使用流密码,例如计数器模式下的AES。
那么同样重要的是,始终以相同的方式执行混洗操作。类似地,生成的比特流中的数字应该始终以相同的方式操作。如果对这些进行了优化或更改,结果将是不同的洗牌,从而破坏方案。
最后,您最好自己对此进行编程,这样就可以确保方法契约背后的代码不会更改。
这样做的要求是:
如果大小不符合流密码,则可以对种子进行散列并获取最左边的字节。
该想法的演示(未经过充分测试或精心设计):
import numpy as np
from Crypto.Cipher import ChaCha20
from Crypto.Random import get_random_bytes
array = np.arange(100) # [0 1 2 3 4 5 6 7 8 9]
seed = bytes([0x00]) * 32 # use SHA-256 to hash different size seeds
nonce_rfc7539 = bytes([0x00]) * 12
cipher = ChaCha20.new(key=seed, nonce=nonce_rfc7539)
zerobuf = bytes([0x00]) * 5
def sample(max):
# rejection sampling using rand(0..n * max) % max
# the value 2 is in there to make sure the number of bits is at least
# two higher than max, so that the chance of each candicate succeeding
# is higher
stream_size = (max.bit_length() + 2 + 7) // 8
max_stream_value = 1 << (stream_size * 8)
max_candidate = max_stream_value - max_stream_value % max
while True:
stream = cipher.encrypt(zerobuf[0:stream_size])
candidate = int.from_bytes(stream, "big")
if (candidate < max_candidate):
break
return candidate % max
def shuffle(list):
# do the Fisher-Yates shuffle
for i in range(len(list) - 1, 0, -1):
j = sample(i + 1)
list[i],list[j] = list[j],list[i]
# test only
print(array)
for i in range(0, 100):
shuffle(array)
print(array)https://stackoverflow.com/questions/66528995
复制相似问题