C语言 使用AES作为具有真正随机种子的便携式RNG?

ojsjcaue  于 2023-03-22  发布在  其他
关注(0)|答案(4)|浏览(205)

我正在编写一个服务,其中需要跨不共享代码库的多个平台的确定性RNG(可能C除外)。随机数需要正好是128位长。给定一个预先协商的真正随机数,如果我使用AES来生成随机数序列,可以吗?它的工作原理是我将加密种子以获得第一个随机数,加密第一随机数以得到第二随机数,等等。
基本上:

rand[0] = truly_random_number;
rand[1] = AES(truly_random_number);
rand[2] = AES(AES(truly_random_number));
rand[n] = AES(AES(AES...AES(truly_random_number...))) //n times

这里的一个参数AES被定义为始终为全零的明文。
客户端将在通信时共享它们的序列号,因此它们中的任何一个都应该可以确定性地重建所需的结果。
这是AES的正确使用吗?我可以使用更快的东西来实现这一点,比如SHA-256并截断结果吗?我应该找到一些RNG的C实现并使用它吗?我倾向于AES,因为我的目标平台有AES加速器,所以速度应该不是问题。

cgh8pdjw

cgh8pdjw1#

我认为这样做最多是一次黑客攻击。
AES是一种加密算法,而不是一种随机数生成算法。我不指望一遍又一遍地应用AES来产生像样的随机性。
您提到您担心性能问题,希望使用AES硬件。AES硬件加速的原因是AES相当复杂。例如,xorshift只是几个xor和shift操作,你还需要依赖于你的目标硬件有AES加速器。
从某个地方获得一个像样的C PRNG库(它们不难找到),用你的共享随机数作为种子,然后就这样了。

ykejflvf

ykejflvf2#

你没有说明你的安全需求。如果你想要一个加密安全的解决方案,那么你的问题就不简单了。请参阅A Block Cipher based Pseudo Random Number Generator Secure Against Side-Channel Key Recovery以获得一个可能的解决方案。
由于安全要求,这样的RNG会很慢。正如32上校所说,你的问题可能会通过非加密RNG更好地解决,它会更快,可能更容易维护。

anauzrmj

anauzrmj3#

给定一个预先协商好的真随机数,我是否可以使用AES生成一个随机数序列?
是的,这正是对称密码学的核心。
但是,使用这样的自定义结构是不合适的:

rand[n] = AES(AES(AES...AES(truly_random_number...))) //n times

相反,只需使用已建立的构造,如计数器模式。

AES_ctr128_encrypt(all_zeroes, rand+n, 16, truly_random_number, &n, ecount_buf, 1)

(The上面的代码片段省略了some serious detail。我不知道你实际上使用的是什么库。在C中手动启动AES并不容易。)
在计数器模式下使用AES作为RNG的Python示例:

import Crypto.Cipher.AES

def rand_block(key: bytes, offset: int, *, nonce=b''):
    c = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_CTR, nonce=nonce, initial_value=offset)
    return c.encrypt(bytes(Crypto.Cipher.AES.block_size))

# test value:
assert int.to_bytes(179565763088325722286336838177169761478, 16, 'little') == \
       rand_block(bytes.fromhex('000102030405060708090A0B0C0D0E0F'), 99)
velaa5lx

velaa5lx4#

你应该读一下下面的内容,它有到PRNG的其他参考资料的链接
http://c-faq.com/lib/rand.html
不要做你正在做的事情,除非你在同行评议的文献中找到一些东西,这将工作,即使这样,我也会谨慎对待它。

#define a 48271
#define m 2147483647
#define q (m / a)
#define r (m % a)

static long int seed = 1;

long int PMrand()
{
    long int hi = seed / q;
    long int lo = seed % q;
    long int test = a * lo - r * hi;
    if(test > 0)
        seed = test;
    else    seed = test + m;
    return seed;
}

请注意文档底部附近的a的更改。您也应该不相信我刚才写的内容,即做好功课,并确保上述或其他PRNG适用于您的应用程序。

相关问题