2009-05-23 22 views
5

Busco a una clase general de cifrado de cadena en .NET. (No debe confundirse con la clase 'SecureString'.)general cadena de cifrado

Empecé a crear mi propia clase, pero pensé que debe haber una clase .NET que ya le permita encriptar/desencriptar cadenas de cualquier codificación con cualquier proveedor de servicios criptográficos.

Public Class SecureString 

     Private key() As Byte 
     Private iv() As Byte 
     Private m_SecureString As String 

     Public ReadOnly Property Encrypted() As String 
      Get 
       Return m_SecureString 
      End Get 
     End Property 

     Public ReadOnly Property Decrypted() As String 
      Get 
       Return Decrypt(m_SecureString) 
      End Get 
     End Property 

     Public Sub New(ByVal StringToSecure As String) 
      If StringToSecure Is Nothing Then StringToSecure = "" 
      m_SecureString = Encrypt(StringToSecure) 
     End Sub 

     Private Function Encrypt(ByVal StringToEncrypt As String) As String 

      Dim result As String = "" 
      Dim bytes() As Byte = Text.Encoding.UTF8.GetBytes(StringToEncrypt) 

      Using provider As New AesCryptoServiceProvider() 

       With provider 
        .Mode = CipherMode.CBC     
        .GenerateKey() 
        .GenerateIV() 
        key = .Key 
        iv = .IV 
       End With 

       Using ms As New IO.MemoryStream 
        Using cs As New CryptoStream(ms, provider.CreateEncryptor(), CryptoStreamMode.Write) 
         cs.Write(bytes, 0, bytes.Length) 
         cs.FlushFinalBlock() 
        End Using 
        result = Convert.ToBase64String(ms.ToArray()) 
       End Using 

      End Using 

      Return result 

     End Function 

     Private Function Decrypt(ByVal StringToDecrypt As String) As String 

      Dim result As String = "" 
      Dim bytes() As Byte = Convert.FromBase64String(StringToDecrypt) 

      Using provider As New AesCryptoServiceProvider() 

       Using ms As New IO.MemoryStream 
        Using cs As New CryptoStream(ms, provider.CreateDecryptor(key, iv), CryptoStreamMode.Write) 
         cs.Write(bytes, 0, bytes.Length) 
         cs.FlushFinalBlock() 
        End Using 
        result = Text.Encoding.UTF8.GetString(ms.ToArray()) 
       End Using 

      End Using 

      Return result 

     End Function 

    End Class 
+0

Uhm, necesita pasar IV para el descifrado. – Migol

+0

@Migol - ¿Podría aclarar aún más su comentario? – user111370

+0

IV se puede enviar a través de texto operativo y contiene algunos datos distintos de la clave para descifrar la cadena. – Migol

Respuesta

4

AES El algoritmo para el cifrado simétrico es generalmente el camino a seguir para la codificación genérica de cadenas. Sin embargo, me temo que .NET BCL no simplifica más las cosas para usted ya que proporciona las clases y funciones básicas de cifrado/descifrado.

Puede encontrar un buen ejemplo de cómo usar las clases criográficas específicamente para el cifrado de cadenas en this page. Parece ser muy completo y bien comentado, incluso puede descubrir que puede usarlo sin modificaciones adicionales. Nota: Rijndael es el mismo algoritmo que AES. (. Técnicamente, el primero se refiere al nombre real del algoritmo, y el segundo el Advanced Encryption Standard)

+0

@Noldorin - ¡Gracias por el enlace! ¿Hay alguna función genérica que pueda pasar una cadena de cualquier codificación y usar cualquiera de los proveedores de servicios criptográficos? – user111370

+0

@cryptospin: No hay problema. Me acabo de dar cuenta de que malinterpreté ligeramente su pregunta original. Acabo de actualizar la publicación con un poco más de información, de todos modos. Definitivamente no hay clases/métodos de ayuda en el marco .NET para hacer esto por usted. Me temo, aunque el código en la página enlazada debería proporcionarle un buen punto de partida. Una buena forma de hacerlo podría ser usar métodos de extensión aquí. – Noldorin

3

Si usted está tratando de lograr el mismo objetivo como SecureString de .NET, entonces su ejemplo realmente no resuelve el problema. (Podría estar malinterpretando sus objetivos, en cuyo caso me disculpo).

La idea de SecureString de .NET es que almacena los datos de cadena encriptados en un trozo de memoria no administrado, es inmutable una vez creado, y no puede ser leído en .NET usando una variable de cadena normal. Esto protege la cadena de cualquier persona que intente sondear su espacio de memoria (es decir, malware, gusano, troyano, lo que sea) y debe ser limpiada por usted de manera explícita. Las razones de esto implican cómo .NET trata cadenas y el hecho de que los datos en la memoria solo se limpian por el capricho del GC.

Aunque su clase SecureString encripta la cadena en una variable privada, la cadena original que se pasó todavía es insegura. También puede permanecer por un tiempo antes de que el GC lo recolecte o, si ese hilo fue internado, vivirá durante la duración del proceso en el que reside. Las cadenas internas se almacenan en una tabla, lo que las hace más fáciles de encontrar también.

En el otro lado de las cosas ... si descifra su SecureString, obtiene una nueva variable de cadena que podría tener los mismos problemas que la cadena de entrada ... solo se limpia cuando el GC lo decide. ... y también puede terminar internado y vivir durante la duración del proceso.

Para resolver problemas, cada vez que descifra, obtiene otra copia de su cadena cifrada. Esto podría generar un exceso de versiones descifradas de su cadena segura, lo que aumenta las posibilidades de que algún tipo de malware que esté buscando, por ejemplo, números de tarjetas de crédito ... realmente encuentre uno.

He intentado muchas veces crear una mejor versión .NET de .NET 2.0 SecureString, pero nunca he podido producir algo que sea realmente seguro. Se podría obtener un puntero a la variable de cadena que fue descifrada, limpie, ajuste cada personaje a cero, etc. Sin embargo esto podría ser muy problemático en el que incluso algo todavía hace referencia a esa cadena, haciendo que el texto desaparece, corrompido lee, etc. Si la cadena está intervenida, lo que generalmente significa que está siendo utilizada por muchas cosas durante un período de tiempo prolongado, borrarla borrará la única versión y afectará su uso.Incluso si logró borrar con éxito una copia de su cadena segura, no hay garantía de que no haya sido copiada por otro código antes de borrarla (es decir, usted envía su cadena a algún servicio web ... ahora vive en más que un espacio de proceso, muy posiblemente en diferentes ubicaciones físicas en todo el mundo.)

Es definitivamente un problema complicado, y solo proporciona seguridad en el caso de que el espacio de memoria de su aplicación se haya visto comprometido por algún tipo de malware.

+0

Gracias por tomarse el tiempo para publicar. Si lees el OP, declaro explícitamente "(No debe confundirse con la clase 'SecureString')." – user111370

+0

"Esto protege el hilo de cualquier persona que intente sondear el espacio de tu memoria" no lo hace y no tiene como objetivo. Si puede leer la memoria de un proceso, es casi seguro que también puede insertar código nativo, en cuyo punto extraer el texto plano detrás de 'SecureString's es trivial. Solo mantiene la cadena fuera de los volcados de error, el archivo de intercambio, etc. – CodesInChaos

+0

@CodesInChaos: El texto no es simple, está encriptado. Si un 'SecureString' simplemente almacenara texto sin formato en un montón no administrado, estaría de acuerdo, probablemente solo lo mantendría fuera de volcados, archivos de intercambio, etc. Dado que el hilo está encriptado, protege a cualquiera que pueda estar sondeando su memoria inmediatamente obtiene su valor. Claro, la fuerza bruta o los ataques conocidos (si hay alguno para su protocolo de seguridad) aún podrían romper el cifrado, pero ese es el caso con todos los mecanismos de seguridad. Así que estoy de acuerdo con mi declaración. – jrista