0

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

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

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

4

3 回答 3

0

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

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

于 2013-06-29T04:50:57.157 回答
0

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

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

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

于 2013-06-29T16:09:03.067 回答
-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);
        }
    }

}

所以要加密一个字符串

Crypto cs =new Crypto();
String originaltext="hello";
String password="password123";
/encrypting
String encryptedtext=cs.encrypto(originaltext, password);
//decrypting
String decryptedtext=cs.decrypto(encryptedtext, password);
于 2013-06-29T04:33:48.443 回答