简体   繁体   中英

How can I encrypt a data file in C#?

I'm working on a sudoku game and I have a list of sudoku games that I can save. I currently have the following serializer classes to save the games:

    /// <summary>
    /// A method to serialize the game repository
    /// </summary>
    /// <param name="filename">A string representation of the output file name</param>
    /// <param name="savedGameRepository">The saved game repository</param>
    public void SerializeRepository(string filename, SavedGameRepository savedGameRepository)
    {
        using (Stream stream = File.Open(filename, FileMode.OpenOrCreate))
        {
            BinaryFormatter bFormatter = new BinaryFormatter();
            bFormatter.Serialize(stream, savedGameRepository);
        }
    }

    /// <summary>
    /// A method to deserialize the game repository
    /// </summary>
    /// <param name="filename">A string representation of the input file name</param>
    /// <returns>A SavedGameRepository object</returns>
    public SavedGameRepository DeserializeRepository(string filename)
    {
        SavedGameRepository savedGameRepository = new SavedGameRepository();

        using (Stream stream = File.Open(filename, FileMode.OpenOrCreate))
        {
            BinaryFormatter bFormatter = new BinaryFormatter();
            if (stream.Length > 0)
            {
                savedGameRepository = (SavedGameRepository)bFormatter.Deserialize(stream);
            }
        }

        return savedGameRepository;
    }

Of course the problem with this is that the data file still displays the text associated with the sudoku solution so the user could read and cheat. I tried to use asymmetric encryption but of course the list of game objects is too long. I used symmetric encryption and it works as long as the game is not closed. Once closed and reopened the key is gone and the encrypted data file cannot be reopened. Is it possible to persist a symmetric encryption key?

Try to save the serialized objects in a SQLite table. The database can be encrypted with a password, and it is very simple as you don't have to write any code to encrypt just add password in the connection string.

Advantages: You don't have lot of scattered files, easy to code and read write to table. Disadvantage: If this file gets corrupt your entire save is lost.

Of course a symmetric key can be persisted – it's just like any other data. You could save it to a file for instance. But the user would obviously recover the key from the file in that case.

This is a fundamental property of encryption. Encryption substitutes the confidentiality of an arbitrary amount of data (the plaintext) with the confidentiality of a small amount data (the key). More on this: http://blogs.msdn.com/b/ericlippert/archive/2011/09/27/keep-it-secret-keep-it-safe.aspx

Because your game has to be able to read the file, it has to have access to all the information required to do that. At best, you are looking at some sort of obfuscation. You have to ask yourself the question: Do you really care that much about cheating?

Yes ofcourse you can encrypt and decrypt. I will give you a sample code.

Your encrypt class will be like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace demo.encry
{
    public class Crypto
    {
        public Crypto()
        {
        }

        public String encrypto(string te, string ps,
              string Salt = "Kosher", string HashAlgorithm = "SHA1",
              int PasswordIterations = 2, string InitialVector = "OFRna73m*aze01xY",
              int KeySize = 256)
        {
            if (string.IsNullOrEmpty(te))
                return "";
            byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
            byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
            byte[] PlainTextBytes = Encoding.UTF8.GetBytes(te);
            PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(ps, SaltValueBytes, HashAlgorithm, PasswordIterations);
            byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
            RijndaelManaged SymmetricKey = new RijndaelManaged();

            SymmetricKey.Mode = CipherMode.CBC;
            byte[] CipherTextBytes = null;
            using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
            {
                using (MemoryStream MemStream = new MemoryStream())
                {
                    using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
                    {
                        CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
                        CryptoStream.FlushFinalBlock();
                        CipherTextBytes = MemStream.ToArray();
                        MemStream.Close();
                        CryptoStream.Close();
                    }
                }



            }
            SymmetricKey.Clear();
            return Convert.ToBase64String(CipherTextBytes);
        }

        public String decrypto(string ct, string ps,
              string Salt = "Kosher", string HashAlgorithm = "SHA1",
             int PasswordIterations = 2, string InitialVector = "OFRna73m*aze01xY",
             int KeySize = 256)
        {
            if (string.IsNullOrEmpty(ct))
                return "";

            byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
            byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
            byte[] CipherTextBytes = Convert.FromBase64String(ct);
            PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(ps, SaltValueBytes, HashAlgorithm, PasswordIterations);
            byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
            RijndaelManaged SymmetricKey = new RijndaelManaged();
            SymmetricKey.Mode = CipherMode.CBC;
            byte[] PlainTextBytes = new byte[CipherTextBytes.Length];
            int ByteCount = 0;
            using (ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes))
            {
                using (MemoryStream MemStream = new MemoryStream(CipherTextBytes))
                {
                    using (CryptoStream CryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read))
                    {

                        ByteCount = CryptoStream.Read(PlainTextBytes, 0, PlainTextBytes.Length);

                        MemStream.Close();
                        CryptoStream.Close();
                    }
                }
            }

            SymmetricKey.Clear();
            return Encoding.UTF8.GetString(PlainTextBytes, 0, ByteCount);
        }
    }

}

so to encrypt a String do

Crypto cs =new Crypto();
String originaltext="hello";
String password="password123";
/encrypting
String encryptedtext=cs.encrypto(originaltext, password);
//decrypting
String decryptedtext=cs.decrypto(encryptedtext, password);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM