我打算使用/ dev / random输出作为openssl密钥生成的种子,然后我写这个小程序只是为了检查我要做什么:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define LEN 128
void uc2hex(char* hex, unsigned char* uc, unsigned short uc_len)
{
FILE* bp=fmemopen(hex,2*uc_len+1,"w");
unsigned short i;
for(i=0;i<uc_len;i++)
{
fprintf(bp,"%02x",uc[i]);
//printf("%02x\n",uc[i]);
//fprintf(bp,"%d-",i);
}
fprintf(bp,"%c",'\0');
fclose(bp);
}
int main()
{
unsigned char buf[LEN];
char str[2*LEN+1];
int fd=open("/dev/random",O_RDONLY);
read(fd,buf,LEN);
uc2hex(str,buf,LEN);
printf("%s\n",str);
close(fd);
return 0;
}
我运行程序一两次,一切似乎工作正常,但后来我再次按顺序运行了四次,这就是输出:
[walter@eM350 ~]$ ./random
0ee08c942ddf901af1278ba8f335b5df8db7cf18e5de2a67ac200f320a7a20e84866f533667a7e66a4572b3bf83d458e6f71f325783f2e3f921868328051f8f296800352cabeaf00000000000000000001000000000000005d08400000000000c080300e00000000000000000000000010084000000000000006400000000000
[walter@eM350 ~]$ ./random
1f69a0b931c16f796bbb1345b3f58f17f74e3df600000000bb03400000000000ffffffff00000000880e648aff7f0000a88103b4d67f000000305cb4d67f000030415fb4d67f0000000000000000000001000000000000005d08400000000000c080300e00000000000000000000000010084000000000000006400000000000
[walter@eM350 ~]$ ./random
4e8a1715238644a840eb66d9ff7f00002e4e3df600000000bb03400000000000ffffffff00000000a8ec66d9ff7f0000a871a37ad97f00000020fc7ad97f00003031ff7ad97f0000000000000000000001000000000000005d08400000000000c080300e00000000000000000000000010084000000000000006400000000000
[walter@eM350 ~]$ ./random
598c57563e8951e6f0173f0cff7f00002e4e3df600000000bb03400000000000ffffffff0000000058193f0cff7f0000a8e1cbda257f0000009024db257f000030a127db257f0000000000000000000001000000000000005d08400000000000c080300e00000000000000000000000010084000000000000006400000000000
除了128字节的随机字符串之外,Theese似乎对我来说很重要,因为它们大多是相同的。然后,排除NSA篡改linux内核随机数生成器的可能性,我只能猜测这与我的机器中的可用熵有关,当我在序列中询问太多字节时,它会耗尽。我的问题是:
1)这个猜测是否正确?
2)假设1)是正确的,我怎么知道是否有足够的熵来生成真正的随机字节序列?
答案 0 :(得分:13)
从阅读的手册页:
Upon successful completion, read(), readv(), and pread() return the number of bytes actually read and placed in the buffer. The system guarantees to read the number of bytes requested if the descriptor references a normal file that has that many bytes left before the end-of-file, but in no other case.
底线:检查read
的返回值并查看实际读取的字节数 - 可能没有足够的熵来生成您请求的字节数。
int len = read(fd, buf, LEN);
printf("read() returned %d bytes: ", len);
if (len > 0)
{
uc2hex(str, buf, len);
printf("%s\n", str);
}
测试:
$ ./a.out
read() returned 16 bytes: c3d5f6a8ee11ddc16f00a0dea4ef237a
$ ./a.out
read() returned 8 bytes: 24e23c57852a36bb
$ ./a.out
read() returned 16 bytes: 4ead04d1eedb54ee99ab1b25a41e735b
$
答案 1 :(得分:2)
正如其他人建议的那样,您需要检查读取的字节数的返回值。
如果/ dev / random没有足够的可用字节,它将返回更少的字节。
但是,您仍然在以下调用中使用预期的长度:
uc2hex(str,buf,LEN);
printf("%s\n",str);
因此,您正在转换和打印未初始化的内存。后来的调用显示相同的值并不奇怪 - 因为如果没有在调用之间写入内存,则值不会改变。
编辑:更好的是:
int nBytes=read(fd,buf,LEN);
uc2hex(str,buf,nBytes);
printf("%s\n",str);