C语言rand()获取随机数和windows下的CryptGenRandom

是在弄即将发布的一篇博客时顺便弄的,还是先写这个。

rand()函数已经被说烂了,包括这里写的,返回一个0到RAND_MAX(在我的电脑上是32767)的整数。srand(unsigned int)可以设置随机种子,默认为1。设定了初始的随机种子后,以后再重复调用rand()所生成的随机数是确定的。

代码如下

#include 
#include 
#include 

int main() {
    int i;
    printf("%d\n\n", RAND_MAX);
    for (i = 0; i < 10; i++)
        printf("%d ", rand());
    puts("");

    srand(1);
    for (i = 0; i < 10; i++)
        printf("%d ", rand());
    puts("");

    srand(time(NULL));
    for (i = 0; i < 10; i++)
        printf("%d ", rand());
    puts("");

    for (i = 0; i < 10; i++) {
        srand(time(NULL));
        printf("%d ", rand());
    }
    return 0;
}

运行结果:

32767

41 18467 6334 26500 19169 15724 11478 29358 26962 24464
41 18467 6334 26500 19169 15724 11478 29358 26962 24464
23940 10437 3649 15425 14939 32113 15093 28994 14396 16990
23940 23940 23940 23940 23940 23940 23940 23940 23940 23940

第一行是还没有设置随机种子的结果,与第二行将随机种子设置为1后的结果完全相同。第三行是正常情况,第四行是我曾经犯过的一个错误(所以才有了这篇博客),由于time()函数返回的是从1970.1.1 0:00起到调用时经过的秒数,而两次调用之间的时间间隔又很短,所以每次都设置了相同的随机种子,生成的随机数也因此完全相同。此外我还试过用clock()函数的返回值(程序启动开始经过的毫秒数)作为随机种子,后来想想还是不太好,毕竟这个返回值可能会比较有规律,而且通常取值范围较小,而time()的返回值可以保证基本不会重复(除非把unsigned int溢出了……)。

当然本身rand()函数就不是太靠谱,我又想起了之前一篇讲加盐哈希的文章里面提到过的windows下提供的很多语言都可以使用的CryptGenRandom函数,于是从官网复制了下来试了一下,虽然写着C++但是C语言也可以运行,不过懒得仔细看,能用就算了……

#include 
#include 
#include 

int main() {
    int a = 0;
    HCRYPTPROV Rnd;
    LPCSTR UserName = "MyKeyContainer";
    if(CryptAcquireContext(&Rnd, UserName, NULL, PROV_RSA_FULL, 0)) {
        printf("A cryptographic context with the %s key container ",
        UserName);
        printf("has been acquired.\n\n");
    } else {
        if (GetLastError() == NTE_BAD_KEYSET) {
            if(CryptAcquireContext(
                &Rnd,
                UserName,
                NULL,
                PROV_RSA_FULL,
                CRYPT_NEWKEYSET)) {
                printf("A new key container has been created.\n");
            } else {
                printf("Could not create a new key container.\n");
                exit(1);
            }
        } else {
            printf("A cryptographic service handle could not be "
            "acquired.\n");
            exit(1);
        }
    }

    if (CryptGenRandom(Rnd, 4, (BYTE*)(&a)))
        printf("%d\n\n", a);
    else
        puts("failed\n");

    if (CryptReleaseContext(Rnd,0)) {
      printf("The handle has been released.\n\n");
    } else {
      printf("The handle could not be released.\n\n");
    }

    return 0;
}

你可能感兴趣的:(C/C++,随机数,CryptGenRandom)