如何在C#中加密数据文件?

时间:2013-06-29 04:02:48

标签: c# encryption

我正在玩数独游戏,我有一个可以保存的数独游戏列表。我目前有以下序列化程序类来保存游戏:

    /// <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;
    }

当然,问题在于数据文件仍然显示与数独解决方案相关联的文本,因此用户可以阅读和作弊。我尝试使用非对称加密,但当然游戏对象列表太长。我使用对称加密,只要游戏没有关闭就可以使用。关闭并重新打开后,密钥消失,加密的数据文件无法重新打开。是否可以保留对称加密密钥?

3 个答案:

答案 0 :(得分:0)

尝试将序列化对象保存在SQLite表中。数据库可以使用密码加密,而且非常简单,因为您不必编写任何代码来加密,只需在连接字符串中添加密码。

优点:您没有大量分散的文件,易于编码和读写表。 缺点:如果此文件损坏,则整个保存都将丢失。

答案 1 :(得分:0)

当然可以保持对称密钥 - 它就像任何其他数据一样。例如,您可以将其保存到文件中。但在这种情况下,用户显然会从文件中恢复密钥。

这是加密的基本属性。加密用任意数量的数据(明文)的机密性代替少量数据(密钥)的机密性。更多相关信息:http://blogs.msdn.com/b/ericlippert/archive/2011/09/27/keep-it-secret-keep-it-safe.aspx

因为您的游戏必须能够读取该文件,所以它必须能够访问执行该操作所需的所有信息。充其量,你正在寻找某种混淆。你必须问自己一个问题:你真的非常关心作弊吗?

答案 2 :(得分:-1)

是的,您可以加密和解密。我会给你一个示例代码。

您的加密类将是这样的

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);
        }
    }

}

所以加密一个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);