AES加密之随机生成IV
前言
在之前的文章中,实现了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
#endifcsprng.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
评论已关闭