Ale*_*nor 7 security macos security-framework prng ios
许多用户空间CSPRNG都有一个问题,在fork(2)这之后,两个不同进程可能会返回相同的随机字节流.
从观察来看dtruss,很明显,SecRandomCopyBytes至少是播种/dev/random,但它是否以一种可以安全使用的方式进行fork()?
使用以下源代码:
#include <Security/Security.h>
int main() {
uint8_t data[8];
SecRandomCopyBytes(kSecRandomDefault, 8, data);
SecRandomCopyBytes(kSecRandomDefault, 8, data);
printf("%llu\n", *(uint64_t *)data);
}
Run Code Online (Sandbox Code Playgroud)
我得到以下内容dtruss(删除了无关的内容):
open("/dev/random\0", 0x0, 0x7FFF900D76F5) = 3 0
read(0x3, "\b\2029a6\020+\254\356\256\017\3171\222\376T\300\212\017\213\002\034w\3608\203-\214\373\244\177K\177Y\371\033\243Y\020\030*M\3264\265\027\216r\220\002\361\006\262\326\234\336\357F\035\036o\306\216\227\0", 0x40) = 64 0
read(0x3, "\223??3\263\324\3604\314:+\362c\311\274\326\a_Ga\331\261\022\023\265C\na\211]\356)\0", 0x20) = 32 0
Run Code Online (Sandbox Code Playgroud)
实现实际上是CCRandomCopyBytes():
http://www.opensource.apple.com/source/Security/Security-55471/libsecurity_keychain/lib/SecRandom.c
int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) {
if (rnd != kSecRandomDefault)
return errSecParam;
return CCRandomCopyBytes(kCCRandomDefault, bytes, count);
}
Run Code Online (Sandbox Code Playgroud)
所以实际代码在这里:
http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-60049/lib/CommonRandom.c
CCRandomCopyBytes的include中的注释表明它是fork()安全的:
直接调用系统随机数生成器是不方便的.在调用/ dev/random的简单情况下,调用者必须打开设备并关闭它,并在打开时对其进行管理.该模块具有直接存在的理由,即这样做的不便之处.它管理/ dev/random的文件描述符,包括fork()和exec()中发生的异常处理.调用CCRandomCopyBytes()并为您管理所有繁琐的位.只要继续你真正想做的事情.[...]
在我自己的快速测试中,孩子在调用SecRandomCopyBytes()时会被杀死