如何在c或c++中循环生成随机的256位十六进制

How to loop generate random 256bit hex in c or c++?

本文关键字:随机 十六进制 256位 循环 c++      更新时间:2023-10-16

在python中我做:

import random
while True:
    x = random.randint(0xF,0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140)
    print hex(x)[2:66].lower()

如何使用C或c++实现

使用GNU MP库,可以这样做:

#include <stdio.h>
#include <ctype.h>
#include <gmp.h>
void randint(mpz_t rop, gmp_randstate_t state, mpz_t from, mpz_t to) {
    mpz_t range;
    mpz_init(range);
    /* range = to - from + 1 */
    mpz_sub(range, to, from);
    mpz_add_ui(range, range, 1);
    /* rop = random number in [0, range) */
    mpz_urandomm(rop, state, range);
    /* rop += from */
    mpz_add(rop, rop, from);
    mpz_clear(range);
}
int main(void) {
    char str[1024]; /* allocate enough memory */
    gmp_randstate_t state;
    mpz_t low, high;
    mpz_t ret;
    gmp_randinit_default(state);
    mpz_init(ret);
    mpz_init_set_str(low, "F", 16);
    mpz_init_set_str(high, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140", 16);
    for(;;) {
        randint(ret, state, low, high);
        str[0]='0'; str[1]='x';
        mpz_get_str(str + 2, 16, ret);
        if (str[0] != '' && str[1] != '') {
            int i;
            for (i = 2; i < 66 && str[i] != ''; i++) putchar(tolower(str[i]));
        }
        putchar('n');
    }
    /* the control won't come here */
#if 0
    mpz_clear(low);
    mpz_clear(high);
    mpz_clear(ret);
    gmp_randclear(state);
    return 0;
#endif
}

一个非常简单的解决方案:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define StringLength    (256/4) // (Bits you want)/4 (Thanks, chux)
int main(void){
    char cStrHex[(StringLength+1)] = {0};
    // Seed random:
    srand((unsigned int) time(0));
    // Fill the char buffer
    int i=0;
    for(; i < StringLength; i++){
        sprintf(cStrHex+i, "%x", rand() % 16);
    }
    // Print hex string:
    printf("%sn", cStrHex);
    return 0;
}

请注意,rand()不被认为是加密安全的,所以如果您想将其用于需要完全不可预测的随机数的任何事情,则用CSPRNG替换对rand()的调用。尽管如此,这是一个简短、简单、有效的解决方案。

这里有一个使用random()的方法。它试图使用尽可能多的数字。在POSIX random()的情况下,这是31位,所以7个完整数字。对于arc4random,您可以使用8。

int max_usable_digits = 7;
uint64_t mask = (1 << (4 * max_usable_digits)) - 1;
const char *hex_digits = "0123456789abcdef";
std::string get_random_hex(int digits) {
    char buffer[65] = {};
    int offset = 0;
    while (offset < sizeof(buffer)) {
        long r = random() & mask;
        offset += snprintf(buffer + offset, sizeof(buffer) - offset,
                           "%0*lx", max_usable_digits, r);
    }
    return std::string(buffer);
}

如果您可以使用Boost库,generating_a_random_password示例可以通过少量修改解决您的问题。


UPDATE:返回64个0到64个F之间的随机字符串。OP问题中的特定限制(0xF和0xFF..140)是有效EDCSA密钥的范围。几乎所有64位字符串都是有效的。您可以使用:

保证一个数字在范围内。
std::string min = "000000000000000000000000000000000000000000000000000000000000000F";
std::string max = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140";
std::string get_random_ecdsa_key() {
  while (true) {
    std::string s = get_random_hex(64);
    if (s >= min && s < max) {
      return s;
    }
  }
}