如何从OpenSSL获取随机盐作为std :: string

时间:2016-01-30 13:28:49

标签: c++ c++11 random openssl salt

我想用OpenSSL生成一个随机字符串,然后在散列函数中将它用作盐(将是Argon2)。目前,我以这种方式生成随机数据:

if(length < CryptConfig::sMinSaltLen){        
    return 1;
}
if (!sInitialized){
    RAND_poll();
    sInitialized = true;
}

unsigned char * buf = new unsigned char[length];
if (!sInitialized || !RAND_bytes(buf, length)) {      
    return 1;
}

salt = std::string (reinterpret_cast<char*>(buf));
delete buf;

return 0;

但是std::cout盐似乎不是一个合适的字符串(包含控制符号和其他东西)。这很可能只是我的错。

我是否使用OpenSSL的错误功能来生成随机数据?

或者是我从buf转换为字符串错误?

1 个答案:

答案 0 :(得分:2)

随机数据是随机数据。这就是你所要求的,而这正是你所得到的。您的salt变量是恰当的字符串,恰好包含不可打印的字符。如果你想拥有可打印的字符,实现这一目的的一种方法是使用base64编码,但这会炸掉它的长度。另一个选择是以某种方式丢弃不可打印的字符,但我没有看到任何强制RAND_bytes执行此操作的机制。我想你可以简单地在循环中获取随机字节,直到你得到length可打印字符。

如果您可以接受编码base64,下面是一个如何使用从Joe Linoff Cipher library中提取的OpenSSL base64编码器的示例:

string Cipher::encode_base64(uchar* ciphertext,
                 uint   ciphertext_len) const
{
  DBG_FCT("encode_base64");
  BIO* b64 = BIO_new(BIO_f_base64());
  BIO* bm  = BIO_new(BIO_s_mem());
  b64 = BIO_push(b64,bm);
  if (BIO_write(b64,ciphertext,ciphertext_len)<2) {
    throw runtime_error("BIO_write() failed");
  }
  if (BIO_flush(b64)<1) {
    throw runtime_error("BIO_flush() failed");
  }
  BUF_MEM *bptr=0;
  BIO_get_mem_ptr(b64,&bptr);
  uint len=bptr->length;
  char* mimetext = new char[len+1];
  memcpy(mimetext, bptr->data, bptr->length-1);
  mimetext[bptr->length-1]=0;
  BIO_free_all(b64);

  string ret = mimetext;
  delete [] mimetext;
  return ret;
}

对于此代码,我建议添加BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL),否则您将在每64个字符后插入一个新行字符。有关详细信息,请参阅OpenSSL的-A开关。