2009-05-23 5 views
5

Je cherche une classe de cryptage de chaîne générale dans .NET. (A ne pas confondre avec la classe 'SecureString'.)Cryptage de chaînes de caractères général

J'ai commencé à créer ma propre classe, mais je pensais qu'il devait y avoir une classe .NET qui vous permet déjà de crypter/décrypter des chaînes de n'importe quel codage avec tout fournisseur de services cryptographiques.

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, vous devez passer IV pour le décryptage. – Migol

+0

@Migol - Pourriez-vous préciser votre commentaire? – user111370

+0

IV peut être envoyé via opentext et contient des données autres que la clé pour déchiffrer votre chaîne. – Migol

Répondre

4

L'algorithme AES pour le chiffrement symétrique est généralement la voie à suivre pour le chiffrement générique de chaînes. Cependant, je crains que le .NET BCL ne simplifie pas les choses pour vous fournir les classes et les fonctions de base de chiffrement/décryptage.

Vous pouvez trouver un bon exemple d'utilisation des classes cryptographiques spécifiquement pour le chiffrement de chaîne sur this page. Il semble être très complet et bien commenté - vous pouvez même trouver que vous pouvez l'utiliser sans autres modifications. Remarque: Rijndael est le même algorithme que AES. (. Techniquement, le premier se réfère à vrai nom de l'algorithme, et celui-ci Advanced Encryption Standard )

+0

@Noldorin - Merci pour le lien! Existe-t-il une fonction générique permettant de transmettre une chaîne d'encodage quelconque et d'utiliser l'un des fournisseurs de services cryptographiques? – user111370

+0

@cryptospin: Pas de problème. Je viens de réaliser que j'ai un peu mal compris votre question initiale. Je viens de mettre à jour le post avec un peu plus d'infos, de toute façon. Il n'y a certainement pas de classe/méthodes d'aide dans le framework .NET pour faire cela pour vous, j'en ai peur, bien que le code sur la page liée puisse vous fournir un bon point de départ. Une bonne façon de s'y prendre pourrait être d'utiliser des méthodes d'extension ici. – Noldorin

3

Si vous essayez d'atteindre le même objectif En tant que SecureString .NET, votre exemple ne résout pas vraiment le problème. (Je pourrais mal comprendre vos objectifs, auquel cas je m'excuse.)

L'idée de SecureString .NET est qu'il stocke les données de chaîne cryptées dans un morceau de mémoire non géré, est immuable une fois créé, et ne peut pas être lu dans .NET en utilisant une variable de chaîne normale. Cela protège la chaîne contre toute tentative d'exploration de votre espace mémoire (c'est-à-dire un logiciel malveillant, un ver, un cheval de Troie ou autre) et doit être explicitement nettoyé par vous. Les raisons de cela impliquent comment .NET traite les chaînes, et le fait que les données en mémoire sont seulement nettoyées au gré du GC.

Même si votre classe SecureString chiffre la chaîne en une variable privée, la chaîne d'origine transmise n'est toujours pas sécurisée. Il peut aussi rester un moment avant que le GC ne le recueille, ou, si cette chaîne a été internée, il vivra pendant la durée du processus dans lequel il se trouve. Les chaînes internées sont stockées dans une table, ce qui les rend plus faciles à trouver. De l'autre côté des choses ... si vous déchiffrez votre SecureString, vous obtenez une nouvelle variable de chaîne qui pourrait rencontrer les mêmes problèmes que la chaîne d'entrée ... elle n'est nettoyée que lorsque le GC le décide. ..et il peut aussi finir interné et vivre pendant la durée du processus. Pour compliquer les problèmes, chaque fois que vous déchiffrez, vous obtenez une autre copie de votre chaîne cryptée. Cela pourrait générer un surplus de versions décryptées de votre chaîne sécurisée, ce qui augmente les chances que certains logiciels malveillants qui recherchent, disons, des numéros de cartes de crédit ... en trouveront un.

J'ai essayé plusieurs fois de créer une meilleure version .NET de SecureString .NET 2.0, mais je n'ai jamais réussi à produire quelque chose de vraiment sécurisé. Vous pouvez obtenir un pointeur sur la variable de chaîne décryptée, l'effacer, définir chaque caractère sur zéro, etc. Cependant, cela peut être très problématique dans le cas où quelque chose referme toujours cette chaîne, causant la disparition du texte, des lectures corrompues, etc. Si la chaîne est internée, ce qui signifie généralement qu'elle est utilisée par beaucoup de choses pendant une longue période de temps, l'effacer efface la seule version et affecte toute utilisation de celle-ci.Même si vous avez réussi à effacer une copie de votre chaîne sécurisée, il n'y a aucune garantie qu'elle n'a pas été copiée par un autre code avant de l'avoir effacée (c'est-à-dire que vous envoyez votre chaîne à un service Web ... C'est certainement un problème compliqué, et ne fournit vraiment de la sécurité que si l'espace mémoire de votre application a été compromis par des logiciels malveillants.

+0

Merci d'avoir pris le temps de poster. Si vous lisez l'OP, je déclare explicitement "(Ne pas confondre avec la classe 'SecureString'.)" – user111370

+0

"Cela protège la chaîne de toute personne essayant de sonder votre espace mémoire" elle ne vise pas et ne vise pas. Si vous pouvez lire la mémoire d'un processus, vous pouvez presque certainement aussi injecter du code natif, à quel point extraire le texte en clair derrière 'SecureString's est trivial. Il ne conserve que la chaîne de crashs, le fichier d'échange, etc. – CodesInChaos

+0

@CodesInChaos: Le texte n'est pas clair, il est crypté. Si un 'SecureString' stockait simplement du texte brut sur un tas non-géré, je serais probablement d'accord pour le garder à l'abri des vidages sur incident, du fichier d'échange, etc. Etant donné que la chaîne est cryptée, elle protège quiconque votre mémoire d'obtenir immédiatement sa valeur. Bien sûr, la force brute ou les attaques éventuellement connues (s'il y en a pour votre protocole de sécurité) pourraient potentiellement casser le cryptage, mais c'est techniquement le cas avec tous les mécanismes de sécurité. Donc, je maintiens ma déclaration. – jrista

Questions connexes