前言

在之前的文章中,实现了PKCS7填充,但是IV是固定的,从安全的角度来说,每经过一次加密和解密后IV应当重新随机生成。通过搜索,得知了一个概念:密码学安全伪随机数生成器(亦作密码学伪随机数生成器,英文:Cryptographically secure pseudo-random number generator,通称CSPRNG),之后在Github上找了一个C语言实现的库:CSPRNG

CSPRNG

这个库很简单,调用操作系统自己的CSPRNG来生成随机数。

#include <stdio.h>
#include <csprng.h>
#include <stdint.h>

int main()
{
  CSPRNG rng = csprng_create();        // Constructor
  if (!rng)
  {
    fprintf( stderr, "%s\n", "No CSPRNG! Fooey!" );
    return 1;
  }
  
  long n = csprng_get_int( rng );           // Get an int
  
  double f;                                 // Get a double
  csprng_get( rng, &f, sizeof(f) );
  
  int xs[ 20 ];                             // Get an array
  csprng_get( rng, xs, sizeof(xs) );
  
  void* p = malloc(20);                     // et cetera
  csprng_get( rng, p, 20 );
  free( p );
  
  rng = csprng_destroy( rng );              // Destructor
  return 0;
}

在我的AES加密中只需要随机产生16字节的IV就可以了:

uint8_t iv[16];
csprng_get( rng, iv, sizeof(iv) );

相关源码:
csprng.h

/*
// Interface to the OS Cryptographically-Secure Pseudo-Random Number Generator

// Copyright 2017 Michael Thomas Greer
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file ../../LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt )
*/

#pragma once
#ifndef DUTHOMHAS_CSPRNG_H
#define DUTHOMHAS_CSPRNG_H

/* ------------------------------------------------------------------------------------------------
 * CSPRNG
 */
typedef void* CSPRNG;

#ifdef __cplusplus
extern "C" {
#endif

CSPRNG csprng_create();
/* Returns a new CSPRNG object, 0 on error.
 */

int csprng_get( CSPRNG, void* dest, unsigned long long size );
/* Fills $dest with $size bytes worth of random data.
 * Returns 1 on succes, 0 on failure.
 */

long csprng_get_int( CSPRNG );
/* Return a random value
 * There is no way to know if it failed.
 * (If it did fail, the result will be 0, which is fairly unlikely
 *  to occur multiple times in sequence.
 *  It is also unlikely to fail at all if csprng_create() succeeded.)
 */

CSPRNG csprng_destroy( CSPRNG );
/* Destroy an existing CSPRNG object. Returns 0.
 * Use it as:
 *   v = csprng_destroy( v );
 */

#ifdef __cplusplus
}
#endif

#endif

csprng.c

/*
// Source for the OS Cryptographically-Secure Pseudo-Random Number Generator

// Copyright 2017 Michael Thomas Greer
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file ../LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt )
*/

#include <csprng.h>

/* ///////////////////////////////////////////////////////////////////////////////////////////// */
#ifdef _WIN32
/* ///////////////////////////////////////////////////////////////////////////////////////////// */

  #include <windows.h>
  #include <wincrypt.h>

  #ifdef _MSC_VER
  #pragma comment(lib, "advapi32.lib")
  #endif
  
  #ifdef __cplusplus
  extern "C" {
  #endif

  /* ------------------------------------------------------------------------------------------- */
  typedef union
  {
    CSPRNG     object;
    HCRYPTPROV hCryptProv;
  }
  CSPRNG_TYPE;

  /* ------------------------------------------------------------------------------------------- */
  CSPRNG csprng_create()
  {
    CSPRNG_TYPE csprng;
    if (!CryptAcquireContextA( &csprng.hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT ))
      csprng.hCryptProv = 0;
    return csprng.object;
  }

  /* ------------------------------------------------------------------------------------------- */
  int csprng_get( CSPRNG object, void* dest, unsigned long long size )
  {
    // Alas, we have to be pedantic here. csprng_get().size is a 64-bit entity.
    // However, CryptGenRandom().size is only a 32-bit DWORD. So we have to make sure failure 
    // isn't from providing less random data than requested, even if absurd.
    unsigned long long n;
    
    CSPRNG_TYPE csprng;
    csprng.object = object;
    if (!csprng.hCryptProv) return 0;
    
    n = size >> 30;
    while (n--)
      if (!CryptGenRandom( csprng.hCryptProv, 1UL << 30, (BYTE*)dest )) return 0;
      
    return !!CryptGenRandom( csprng.hCryptProv, size & ((1ULL << 30) - 1), (BYTE*)dest );
  }

  /* ------------------------------------------------------------------------------------------- */
  long csprng_get_int( CSPRNG object )
  {
    long result;
    return csprng_get( object, &result, sizeof(result) ) ? result : 0;
  }

  /* ------------------------------------------------------------------------------------------- */
  CSPRNG csprng_destroy( CSPRNG object )
  {
    CSPRNG_TYPE csprng;
    csprng.object = object;
    if (csprng.hCryptProv) CryptReleaseContext( csprng.hCryptProv, 0 );
    return 0;
  }

  #ifdef __cplusplus
  }
  #endif

/* ///////////////////////////////////////////////////////////////////////////////////////////// */
#else  /* Using /dev/urandom                                                                     */
/* ///////////////////////////////////////////////////////////////////////////////////////////// */

  #include <stdio.h>

  #ifdef __cplusplus
  extern "C" {
  #endif

  /* ------------------------------------------------------------------------------------------- */
  typedef union
  {
    CSPRNG object;
    FILE*  urandom;
  }
  CSPRNG_TYPE;

  /* ------------------------------------------------------------------------------------------- */
  CSPRNG csprng_create()
  {
    CSPRNG_TYPE csprng;
    csprng.urandom = fopen( "/dev/urandom", "rb" );
    return csprng.object;
  }

  /* ------------------------------------------------------------------------------------------- */
  int csprng_get( CSPRNG object, void* dest, unsigned long long size )
  {
    CSPRNG_TYPE csprng;
    csprng.object = object;
    return (csprng.urandom) && (fread( (char*)dest, 1, size, csprng.urandom ) == size);
  }

  /* ------------------------------------------------------------------------------------------- */
  long csprng_get_int( CSPRNG object )
  {
    long result;
    return csprng_get( object, &result, sizeof(result) ) ? result : 0;
  }

  /* ------------------------------------------------------------------------------------------- */
  CSPRNG csprng_destroy( CSPRNG object )
  {
    CSPRNG_TYPE csprng;
    csprng.object = object;
    if (csprng.urandom) fclose( csprng.urandom );
    return 0;
  }
  
  #ifdef __cplusplus
  }
  #endif

#endif

标签: none

评论已关闭