c - 如何根据字节数组生成随机数?

标签 c random cryptography prng

假设我有一个来自安全 PRNG 的字节数组,我需要使用该数据生成一个介于 1 到 10 之间的数字,我该如何正确地做到这一点?

最佳答案

将数组视为一个大的无符号整数。那么答案很简单:

(Big_Number % 10) + 1

因此,所需要的只是找到大整数的模数 10 的方法。使用modular exponentiation :

#include <limits.h>
#include <stdlib.h>

int ArrayMod10(const unsigned char *a, size_t n) {
  int mod10 = 0;
  int base = (UCHAR_MAX + 1) % 10;
  for (size_t i = n; i-- > 0;  ) {
    mod10 = (base*mod10 + a[i]) % 10;
    base = (base * base) % 10;
  }
  return mod10;
}

void test10(size_t n) {
  unsigned char a[n];

  // fill array with your secure PRNG
  for (size_t i = 0; i<n; i++) a[i] = rand();

  return ArrayMod10(a, n) + 1;
}

由于 256^n 不是 10 的幂,因此会有轻微偏差。对于较大的 n,这将迅速降低重要性。

未经测试的代码:检测是否出现有偏差的结果。调用代码可以使用新的 a 数组值重复调用此函数,以便在出现偏差的极少数情况下获得无偏差的结果。

int ArrayMod10BiasDetect(const unsigned char *a, size_t n, bool *biasptr) {
  bool bias = true;
  int mod10 = 0;
  int base = (UCHAR_MAX + 1) % 10;  // Note base is usually 6: 256%10, 65536%10, etc.
  for (size_t i = n; i-- > 0;  ) {
    mod10 = (base*mod10 + a[i]) % 10;
    if (n > 0) {
      if (a[i] < UCHAR_MAX) bias = false;
    } else {
      if (a[i] < UCHAR_MAX + 1 - base) bias = false;
    }
    base = (base * base) % 10;
  }
  *biaseptr = bias;
  return mod10;
}

关于c - 如何根据字节数组生成随机数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29122111/

相关文章:

c - 如何在 C 中打开和使用套接字?

c - 是否可以从代码中指定链接器选项?

java - java.util.Random.nextInt 的实现

Python numpy 随机数概率

c++ - CryptEncrypt 不加密整个文本

C 中的复合语句表达式

c++ - 非(~)与否定(!)

javascript - 如何在过滤元素期间随机化数组(不过滤数组然后随机化元素)?

objective-c - 将对称 key SecKeyRef 项导出为 CFDataRef

python - 生成 n 个二进制向量,其中每个向量与其他每个向量的汉明距离为 d