C # chiffrer la sortie texte

J’ai créé quelques petits programmes qui exportent des données dans un fichier texte à l’aide de StreamWriter, puis je les ai lus à l’aide de StreamReader. Cela fonctionne très bien et fait ce dont j’ai besoin, mais je me demandais s’il était possible de sauvegarder ces informations sans que l’utilisateur ne puisse y accéder, ni les modifier, intentionnellement ou non. Un exemple de ce que j’aurais dans un fichier texte serait si une case à cocher était cochée, lorsque vous cochez cette case, il affiche “Ticked” dans un fichier texte. était fermé. Je ne veux évidemment pas continuer à utiliser des fichiers texte. Quelqu’un a-t-il des idées sur la manière dont je peux facilement stocker ces informations sans que l’utilisateur puisse les modifier? Merci beaucoup.

Le moyen le plus simple consiste à coder / décoder ce texte en base 64. Ce n’est pas sécurisé, mais empêchera un utilisateur occasionnel de modifier les données.

static public ssortingng EncodeTo64(ssortingng toEncode) { byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode); ssortingng returnValue = System.Convert.ToBase64Ssortingng(toEncodeAsBytes); return returnValue; } static public ssortingng DecodeFrom64(ssortingng encodedData) { byte[] encodedDataAsBytes = System.Convert.FromBase64Ssortingng(encodedData); ssortingng returnValue = System.Text.ASCIIEncoding.ASCII.GetSsortingng(encodedDataAsBytes); return returnValue; } 

EDIT: Cryptage réel

 #region Encryption ssortingng passPhrase = "Pasword"; // can be any ssortingng ssortingng saltValue = "sALtValue"; // can be any ssortingng ssortingng hashAlgorithm = "SHA1"; // can be "MD5" int passwordIterations = 7; // can be any number ssortingng initVector = "~1B2c3D4e5F6g7H8"; // must be 16 bytes int keySize = 256; // can be 192 or 128 private ssortingng Encrypt(ssortingng data) { byte[] bytes = Encoding.ASCII.GetBytes(this.initVector); byte[] rgbSalt = Encoding.ASCII.GetBytes(this.saltValue); byte[] buffer = Encoding.UTF8.GetBytes(data); byte[] rgbKey = new PasswordDeriveBytes(this.passPhrase, rgbSalt, this.hashAlgorithm, this.passwordIterations).GetBytes(this.keySize / 8); RijndaelManaged managed = new RijndaelManaged(); managed.Mode = CipherMode.CBC; ICryptoTransform transform = managed.CreateEncryptor(rgbKey, bytes); MemoryStream stream = new MemoryStream(); CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write); stream2.Write(buffer, 0, buffer.Length); stream2.FlushFinalBlock(); byte[] inArray = stream.ToArray(); stream.Close(); stream2.Close(); return Convert.ToBase64Ssortingng(inArray); } private ssortingng Decrypt(ssortingng data) { byte[] bytes = Encoding.ASCII.GetBytes(this.initVector); byte[] rgbSalt = Encoding.ASCII.GetBytes(this.saltValue); byte[] buffer = Convert.FromBase64Ssortingng(data); byte[] rgbKey = new PasswordDeriveBytes(this.passPhrase, rgbSalt, this.hashAlgorithm, this.passwordIterations).GetBytes(this.keySize / 8); RijndaelManaged managed = new RijndaelManaged(); managed.Mode = CipherMode.CBC; ICryptoTransform transform = managed.CreateDecryptor(rgbKey, bytes); MemoryStream stream = new MemoryStream(buffer); CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Read); byte[] buffer5 = new byte[buffer.Length]; int count = stream2.Read(buffer5, 0, buffer5.Length); stream.Close(); stream2.Close(); return Encoding.UTF8.GetSsortingng(buffer5, 0, count); } #endregion 

Vous pouvez append une sum de contrôle ou un hachage au fichier. Si le contenu du fichier ne correspond pas à la sum de contrôle, vous savez qu’il a été falsifié.

S’il est important que les utilisateurs ne puissent pas lire le contenu du fichier, vous pouvez le chiffrer.

Je ne crois pas que vous puissiez créer un fichier qui ne puisse pas être falsifié (un utilisateur averti pourrait utiliser un éditeur hexadécimal et le modifier, par exemple). Le mieux que vous puissiez faire est de détecter une telle falsification.

Vous devez appeler ProtectedData.Protect pour chiffrer les données à l’aide d’une clé par utilisateur.

Notez qu’il ne serait pas très difficile pour un utilisateur qualifié de décrypter et de modifier les données.
Tout ce que votre programme fait sur la machine de l’utilisateur peut également être effectué par l’utilisateur.

Vous pouvez utiliser les bibliothèques zip Ionic pour compresser ces fichiers texte. Si nécessaire, vous pouvez également utiliser des fonctionnalités de Ionic zip telles que la protection par mot de passe et le cryptage. Et vous pourrez toujours ouvrir le fichier manuellement (avec les applications de compression, comme par exemple 7zip) manuellement, en utilisant les mêmes parameters que vous avez précédemment créés pour le créer.

Si un programme peut accéder aux informations, un utilisateur peut également le faire. Cependant, vous pouvez produire des données que l’utilisateur ne comprendra pas immédiatement.

Je commencerais par créer une classe contenant toutes les informations d’état que vous souhaitez enregistrer, en isolant le problème. Par coïncidence, la classe BinaryFormatter vous permettra ensuite de sauvegarder et de charger facilement cette classe dans / à partir d’un fichier. Je ne sais pas si ses résultats sont “assez illisibles” – si ce n’est pas le cas, appliquez le codage Base64 comme Leon l’a mentionné

Bien que vous puissiez encoder en base64 ou même entièrement vos données de configuration (avec SHA1 ou MD5) comme déjà suggéré, je pense que la bonne pratique consisterait à travailler avec les classes de framework traitant des données de configuration ( Configuration sous l’espace de noms System.Configuration ). en capacité de chiffrer des données (via la méthode ProtectSection de la classe ConfigurationSection ).

Tout d’abord, vous devez déclarer et initialiser une instance:

 using System.Configuration; ... static void Main(ssortingng[] args) { Configuration config; config = ConfigurationManager.OpenExeConfiguration(/*path to config file*/); //Use ConfigurationManager.OpenMachineConfiguration(/*path to config file*/) when opening machine configuration ... 

Après cela, vous devez définir une section de configuration personnalisée définissant votre configuration ( exemple avec msdn ).

Une fois que vous avez fait cela, il vous suffit d’initialiser une instance de votre section de configuration personnalisée et de l’append au fichier de configuration à l’aide de ce code:

 isTicked = config.Sections.Add("isTicked", customSection); 

Pour chiffrer la section que vous venez d’append, utilisez ce code (avec d’autres exemples dans VB.NET et C # trouvés ici ):

 config.Sections["isTicked"].SectionInformation.ProtectSection("protection provider"); 

“DPAPIProtectedConfigurationProvider” et “RSAProtectedConfigurationProvider” sont intégrés par défaut.

Une fois que vous voulez déchiffrer la section, utilisez ce code:

 config.Sections["isTicked"].SectionInformation.UnprotectSection(); 

Pour insister sur un point – le chiffrement et le déchiffrement ne prennent effet que lorsque vous enregistrez le fichier de configuration

Pour enregistrer le fichier, utilisez le code:

 config.Save(); //config.SaveAs("ssortingng") is also available 

Vous trouverez des informations complémentaires sur les classes et méthodes pertinentes dans le msdn, en commençant par la page de classe de Configuration liée ci-dessus.

Essayez ce code pour chiffrer et déchiffrer votre texte! C’est assez facile et fort je pense …

 public static class Crypto { private static readonly byte[] IVa = new byte[] { 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }; public static ssortingng Encrypt(this ssortingng text, ssortingng salt) { try { using (Aes aes = new AesManaged()) { Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetSsortingng(IVa, 0, IVa.Length), Encoding.UTF8.GetBytes(salt)); aes.Key = deriveBytes.GetBytes(128 / 8); aes.IV = aes.Key; using (MemoryStream encryptionStream = new MemoryStream()) { using (CryptoStream encrypt = new CryptoStream(encryptionStream, aes.CreateEncryptor(), CryptoStreamMode.Write)) { byte[] cleanText = Encoding.UTF8.GetBytes(text); System.Diagnostics.Debug.WriteLine(Ssortingng.Concat("Before encryption text data size: ", text.Length.ToSsortingng())); System.Diagnostics.Debug.WriteLine(Ssortingng.Concat("Before encryption byte data size: ", cleanText.Length.ToSsortingng())); encrypt.Write(cleanText, 0, cleanText.Length); encrypt.FlushFinalBlock(); } byte[] encryptedData = encryptionStream.ToArray(); ssortingng encryptedText = Convert.ToBase64Ssortingng(encryptedData); System.Diagnostics.Debug.WriteLine(Ssortingng.Concat("Encrypted text data size: ", encryptedText.Length.ToSsortingng())); System.Diagnostics.Debug.WriteLine(Ssortingng.Concat("Encrypted byte data size: ", encryptedData.Length.ToSsortingng())); return encryptedText; } } } catch(Exception e) { return Ssortingng.Empty; } } public static ssortingng Decrypt(this ssortingng text, ssortingng salt) { try { using (Aes aes = new AesManaged()) { Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetSsortingng(IVa, 0, IVa.Length), Encoding.UTF8.GetBytes(salt)); aes.Key = deriveBytes.GetBytes(128 / 8); aes.IV = aes.Key; using (MemoryStream decryptionStream = new MemoryStream()) { using (CryptoStream decrypt = new CryptoStream(decryptionStream, aes.CreateDecryptor(), CryptoStreamMode.Write)) { byte[] encryptedData = Convert.FromBase64Ssortingng(text); System.Diagnostics.Debug.WriteLine(Ssortingng.Concat("Encrypted text data size: ", text.Length.ToSsortingng())); System.Diagnostics.Debug.WriteLine(Ssortingng.Concat("Encrypted byte data size: ", encryptedData.Length.ToSsortingng())); decrypt.Write(encryptedData, 0, encryptedData.Length); decrypt.Flush(); } byte[] decryptedData = decryptionStream.ToArray(); ssortingng decryptedText = Encoding.UTF8.GetSsortingng(decryptedData, 0, decryptedData.Length); System.Diagnostics.Debug.WriteLine(Ssortingng.Concat("After decryption text data size: ", decryptedText.Length.ToSsortingng())); System.Diagnostics.Debug.WriteLine(Ssortingng.Concat("After decryption byte data size: ", decryptedData.Length.ToSsortingng())); return decryptedText; } } } catch(Exception e) { return Ssortingng.Empty; } } } 

Juste pour append une autre implémentation de la réponse de Leon, et en suivant les documents Microsoft

Voici un exemple de classe qui chiffre et déchiffre des chaînes

  public static class EncryptionExample { #region internal consts internal const ssortingng passPhrase = "pass"; internal const ssortingng saltValue = "salt"; internal const ssortingng hashAlgorithm = "MD5"; internal const int passwordIterations = 3; // can be any number internal const ssortingng initVector = "0123456789abcdf"; // must be 16 bytes internal const int keySize = 64; // can be 192 or 256 #endregion #region public static Methods public static ssortingng Encrypt(ssortingng data) { ssortingng res = ssortingng.Empty; try { byte[] bytes = Encoding.ASCII.GetBytes(initVector); byte[] rgbSalt = Encoding.ASCII.GetBytes(saltValue); byte[] buffer = Encoding.UTF8.GetBytes(data); byte[] rgbKey = new PasswordDeriveBytes(passPhrase, rgbSalt, hashAlgorithm, passwordIterations).GetBytes(keySize / 8); RijndaelManaged managed = new RijndaelManaged(); managed.Mode = CipherMode.CBC; ICryptoTransform transform = managed.CreateEncryptor(rgbKey, bytes); byte[] inArray = null; using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, transform, CryptoStreamMode.Write)) { csEncrypt.Write(buffer, 0, buffer.Length); csEncrypt.FlushFinalBlock(); inArray = msEncrypt.ToArray(); res = Convert.ToBase64Ssortingng(inArray); } } } catch (Exception ex) { Console.WriteLine("Encrypt " + ex); } return res; } public static ssortingng Decrypt(ssortingng data) { ssortingng res = ssortingng.Empty; try { byte[] bytes = Encoding.ASCII.GetBytes(initVector); byte[] rgbSalt = Encoding.ASCII.GetBytes(saltValue); byte[] buffer = Convert.FromBase64Ssortingng(data); byte[] rgbKey = new PasswordDeriveBytes(passPhrase, rgbSalt, hashAlgorithm, passwordIterations).GetBytes(keySize / 8); RijndaelManaged managed = new RijndaelManaged(); managed.Mode = CipherMode.CBC; ICryptoTransform transform = managed.CreateDecryptor(rgbKey, bytes); using (MemoryStream msEncrypt = new MemoryStream(buffer)) { using (CryptoStream csDecrypt = new CryptoStream(msEncrypt, transform, CryptoStreamMode.Read)) { using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { res = srDecrypt.ReadToEnd(); } } } } catch (Exception ex) { Console.WriteLine("Decrypt " + ex); } return res; } } 

À propos, voici la définition de la «valeur salée» que j’avais recherchée sur Google pour savoir de quoi il s’agissait.

La valeur du sel

Si un attaquant ne connaît pas le mot de passe et essaie de le deviner avec une attaque par force brute, alors chaque mot de passe essayé doit être essayé avec chaque valeur de sel. Ainsi, pour un sel 1 bit (0 ou 1), le chiffrement est deux fois plus difficile à casser de cette façon.

Il est possible d’empêcher les modifications non intentionnelles de chaînes à l’aide d’une sum de contrôle, comme indiqué dans cette réponse .

Cependant, il est assez facile de générer une telle sum de contrôle, car ils ne sont pas aussi nombreux que les algorithmes largement utilisés .

Cela ne vous protège donc pas contre une modification intentionnelle .

Pour empêcher cela, les gens utilisent des signatures numériques . Cela permet à quiconque de vérifier que vos données ne sont pas falsifiées, mais vous seul (le propriétaire du secret privé) pouvez générer la signature.

Voici un exemple en C #.

Cependant, comme d’autres l’ont fait remarquer, vous devez intégrer votre clé privée quelque part dans votre binary, et un programmeur (pas très doué) sera capable de la récupérer, même si vous masquez votre dll .net ou si vous le créez dans un autre fichier processus.

Cela serait cependant suffisant pour la plupart des problèmes.

Si la sécurité vous tient vraiment à cœur, vous devez vous déplacer sur le cloud et exécuter le code sur une machine que vous possédez.