2009-12-20 17 views
5

vi algo de código como¿Cómo genera RFC2898DeriveBytes una clave AES?

string password = "11111111"; 
byte[] salt = Encoding.ASCII.GetBytes("22222222"); 
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt); 
RijndaelAlg.Key = key.GetBytes(RijndaelAlg.KeySize/8); 

puedo ver la clave es generada por Rfc2898DeriveBytes con frase de contraseña y la sal. Entonces AES recupera la clave por GetBytes.

Pero la pregunta es, ¿qué hace RFC2898DeriveBytes y qué clave.GetBytes (cb) hacer? ¿Podría alguien elaborar esto? No pude obtenerlo de la documentación.

Respuesta

10

RFC2898 se refiere a una especificación de criptografía basada en contraseñas publicada en septiembre de 2000. Efectivamente, Rfc2898DeriveBytes toma una contraseña y una sal para generar claves. El método que utiliza se conoce como PBKDF2 (Función de derivación de clave basada en contraseña n. ° 2) y se define en la sección 5.2 de RFC2898. Desde la sección 5.2:

PBKDF2 aplica una función pseudoaleatoria (consulte el Apéndice B.1 para obtener un ejemplo) para derivar claves. La longitud de la clave derivada es esencialmente ilimitada. (Sin embargo, el máximo espacio efectivo de búsqueda para la clave derivada puede estar limitado por la estructura de la función pseudoaleatoria subyacente. Consulte el Apéndice B.1 para obtener más información.) Se recomienda PBKDF2 para nuevas aplicaciones.

Para obtener más información, consulte RFC2898.

En cuanto a lo que Rfc2898DeriveBytes.GetBytes hace, devuelve una clave diferente en cada invocación; efectivamente solo aplica PBKDF2 repetidamente con la misma contraseña y sal pero también un recuento de iteraciones.

Esto se describe en el RFC doc donde PBKDF2 se define como

PBKDF2 (P, S, c, dkLen) 

donde P es la contraseña, S es la sal, c es el recuento de iteración y dkLen es la longitud de la tecla deseada.

En general, el RFCs es muy interesante e históricamente bastante importante. RFC 1149 es bastante importante, como es RFC 2324.

+0

devuelve una clave diferente en cada invocación Pero descubrí las teclas devueltos son todos iguales – Kelvin

+0

@Kelvin: ¿Estás seguro de que eres usándolo en la misma instancia de 'Rfc2898DeriveBytes'? Es efectivamente imposible ver los mismos bytes devueltos en las invocaciones sucesivas de 'Rfc2898DeriveBytes.GetBytes' en la misma instancia de' Rfc2898DeriveBytes'. – jason

+0

RijndaelManaged RijndaelAlg = new RijndaelManaged(); string password = "11111111"; Rfc2898DeriveBytes clave = new Rfc2898DeriveBytes (contraseña, Encoding.ASCII.GetBytes ("22222222")); RijndaelAlg.Key = key.GetBytes (RijndaelAlg.KeySize/8); byte [] a = clave.GetBytes (32); para (int i = 0; i Kelvin

4

De su análisis de la implementación de reflector:

public Rfc2898DeriveBytes(string password, byte[] salt) : this(password, salt, 0x3e8) 
{ 
} 

public Rfc2898DeriveBytes(string password, int saltSize, int iterations) 
{ 
    if (saltSize < 0) 
    { 
     throw new ArgumentOutOfRangeException("saltSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 
    } 
    byte[] data = new byte[saltSize]; 
    Utils.StaticRandomNumberGenerator.GetBytes(data); 
    this.Salt = data; 
    this.IterationCount = iterations; 
    this.m_hmacsha1 = new HMACSHA1(new UTF8Encoding(false).GetBytes(password)); 
    this.Initialize(); 
} 


public override byte[] GetBytes(int cb) 
{ 
    if (cb <= 0) 
    { 
     throw new ArgumentOutOfRangeException("cb", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 
    } 
    byte[] dst = new byte[cb]; 
    int dstOffset = 0; 
    int count = this.m_endIndex - this.m_startIndex; 
    if (count > 0) 
    { 
     if (cb < count) 
     { 
      Buffer.InternalBlockCopy(this.m_buffer, this.m_startIndex, dst, 0, cb); 
      this.m_startIndex += cb; 
      return dst; 
     } 
     Buffer.InternalBlockCopy(this.m_buffer, this.m_startIndex, dst, 0, count); 
     this.m_startIndex = this.m_endIndex = 0; 
     dstOffset += count; 
    } 
    while (dstOffset < cb) 
    { 
     byte[] src = this.Func(); 
     int num3 = cb - dstOffset; 
     if (num3 > 20) 
     { 
      Buffer.InternalBlockCopy(src, 0, dst, dstOffset, 20); 
      dstOffset += 20; 
     } 
     else 
     { 
      Buffer.InternalBlockCopy(src, 0, dst, dstOffset, num3); 
      dstOffset += num3; 
      Buffer.InternalBlockCopy(src, num3, this.m_buffer, this.m_startIndex, 20 - num3); 
      this.m_endIndex += 20 - num3; 
      return dst; 
     } 
    } 
    return dst; 
} 
+0

Si aún lo tiene, sería útil ver las funciones privadas de esta clase, particularmente la parte que realiza la iteración. – Phil

+0

Usa algo como http://ilspy.net/ y revisa el código tú mismo :) Uso Reflector, pero debería ser el mismo. –

+1

@ Phil_1984_ Puede encontrar la fuente de referencia en el sitio de origen de referencia de Microsoft, en este caso [enlace] (http://referencesource.microsoft.com/#mscorlib/system/security/cryptography/rfc2898derivebytes.cs) http: // referencesource .microsoft.com/# mscorlib/system/security/cryptography/rfc2898derivebytes.cs. –

Cuestiones relacionadas