2010-04-12 19 views
9

¿Alguien puede recomendar una biblioteca de generador de números pseudoaleatorios de seguridad criptográfica para Delphi (Win32)?¿Hay alguna biblioteca PRNG criptográficamente segura para Delphi?

Puede ser gratis o comercial, pero idealmente será un proyecto activo. Me gustaría que incluya el código fuente.

+0

Revisa http://blog.synopse.info/post/AES-CSPRNG - es un sólido generador de números pseudoaleatorios criptográficamente seguro basado en AES-256, con mayor seguridad que la caja negra de CryptoAPI (solo utiliza CryptGenRandom como fuente de entropía). –

Respuesta

8

Puede usar Windows CryptoAPI:

uses Wcrypt2; 

function GenerateRandom(Len: Cardinal): TBytes; 
var 
    hProv : HCRYPTPROV; 
begin 
    if not CryptAcquireContext(@hProv, 
          nil, 
          MS_ENHANCED_PROV, 
          PROV_RSA_FULL, 
          CRYPT_VERIFYCONTEXT) then 
    CryptAcquireContext(@hProv, 
         nil, 
         MS_ENHANCED_PROV, 
         PROV_RSA_FULL, 
         CRYPT_NEWKEYSET + CRYPT_VERIFYCONTEXT); 

    if hProv > 0 then 
    try 
    SetLength(Result,Len); 
    CryptGenRandom(hProv,Len,@Result[0]); 
    finally 
    CryptReleaseContext(hProv,0); 
    end; 
end; 

Ejemplo de utilización del código anterior:

function BytesToHex(const Bytes: TBytes): string; 
var 
    i : integer; 
begin 
    for i := 0 to Length(Bytes)-1 do 
    Result := Result + IntToHex(Bytes[i],2); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    ShowMessage(BytesToHex(GenerateRandom(16))); 
end; 
+2

El segundo CryptAcquireContext debe ejecutarse solo si GetLastError = NTE_BAD_KEYSET. De lo contrario, el código debería elevar la excepción (RaiseLastOSError) o devolver una matriz vacía. Origen de MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85).aspx –

+0

El CryptGenRandom tiene debilidades conocidas. Consulte http://eprint.iacr.org/2007/419.pdf. Considere usarlo solo como fuente de entropía de un CSPRNG comprobado, p. como http://blog.synopse.info/post/AES-CSPRNG –

0

OpenSSL sería una posibilidad. La fuente está disponible aunque no sé si hay disponible una versión de Delphi. Incluye un cryptographically secure prng. Es un proyecto activo, pero puede ser excesivo para lo que estás buscando.

5

El Delphi Encryption Compendium (que es famoso-ish en la comunidad de habla Delphi alemán, pero en ninguna otra parte - presumiblemente ya que no se promueve oficialmente) contiene un Yarrow RNG criptográficamente seguro.

basta con incluir la unidad DECRandom (y tal vez DECUtils) y utilizarlo como esto (este ejemplo utiliza IInteger pero eso no es obligatorio):

function generateRandomNumber: IInteger; 
var 
    A: IInteger; 
begin 
    NRnd(A, 512); // generate 512 Bit random number, 2^512 <= A < 2^513 
    Result := A; 
end; 

initialization 
    // Method 1: uses system timer to initialize the RNG (seed) 
    RandomSeed; 
    // Method 2: use own seed 
    randomSeed(Data, SizeOf(Data)); 
+0

que escanea la generación aleatoria de semillas, que es un gran problema en sí mismo. Uno puede usar CryptoAPI (como se muestra en otras respuestas) para generar semillas y luego DEC para generar el azar. – gabr

+0

@gabr: La generación de semillas es, por supuesto, un problema, pero el dommer no lo solicitó. Si alimenta el Delphi PRNG con una buena semilla, aún no se considera criptográficamente seguro http: //en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator ... – Leo

+0

De acuerdo, pero aún debe señalarse, especialmente como su código muestra dos ejemplos no muy buenos de inicialización de la semilla. – gabr

0

Yo también iba a sugerir la OpenSSL libraries. Y también incluye cifrado, SSL, hash, etc.
Indy ha convertido muchos de los encabezados e incluye RAND_screen, pero eso no se puede/no se puede usar, al parecer, en programas sin una IU. Desafortunadamente, se pierde la mayoría de los RAND_ *, pero son muy fáciles de importar y usar.
por ejemplo:

function RAND_load_file(const filename: PAnsiChar; max_bytes: longint): integer; cdecl; external 'libeay32.dll'; 
function RAND_bytes(buf: PByte; num: integer): integer; cdecl; external 'libeay32.dll'; 
function RAND_pseudo_bytes(buf: PByte; num: integer): integer; cdecl; external 'libeay32.dll'; 

a continuación en el código:

RAND_load_file(PAnsiChar(AnsiString('name-of-seed-file')), 512); 
    //or 
    //RAND_screen; 
    ... 
    ... 
    const 
    PKCS5_SALT_LEN = 8; 
    var 
    salt: TBytes; 
    begin 
    SetLength(salt, PKCS5_SALT_LEN); 
    RAND_pseudo_bytes(@salt[0], PKCS5_SALT_LEN); 
    ... 
    end; 

Las mismas cuestiones de semillas como se explica todavía aplican, por supuesto.

2

Salida ISAAC (Indirección, Shift, se acumulan, Agregar, y el Conde), un PRNG rápido y también criptográficamente seguro (burtleburtle.net/bob/rand/isaacafa.html). Probablemente ISAAC es tan rápido como el famoso Mersenne Twister PRNG.

Wolfgang Ehrhardt ha hecho el puerto Pascal/Delphi para ISAAC y está disponible en http://www.wolfgang-ehrhardt.de/misc_en.html#prng (libre y de código disponible). También hay un enlace a otro puerto delphi proporcionado en el sitio del autor, pero me gustaría ir con la versión de "Wolfgang Ehrhardt". Conozco su sitio (http://www.wolfgang-ehrhardt.de/index.html) desde hace muchos años, y ha estado actualizando con las rutinas pascal/delphi desde entonces. ¡Seguramente debería ser un experto en esto!

Cuestiones relacionadas