簡體   English   中英

如何在C#中加密數據文件?

[英]How can I encrypt a data file in C#?

我正在開發數獨游戲,並且列出了可以保存的數獨游戲。 我目前有以下序列化程序類來保存游戲:

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

當然,這樣做的問題是數據文件仍然顯示與數獨解決方案關聯的文本,因此用戶可以閱讀和作弊。 我嘗試使用非對稱加密,但是當然游戲對象列表太長。 我使用了對稱加密,只要游戲沒有關閉,它就可以工作。 一旦關閉並重新打開,密鑰就消失了,無法重新打開加密的數據文件。 是否可以保留對稱加密密鑰?

嘗試將序列化的對象保存在SQLite表中。 可以使用密碼對數據庫進行加密,這非常簡單,因為您無需編寫任何代碼即可加密,只需在連接字符串中添加密碼即可。

優點:您沒有很多分散的文件,易於編碼和讀寫表。 缺點:如果此文件損壞,您的整個保存都將丟失。

當然,對稱密鑰可以保留-就像任何其他數據一樣。 您可以將其保存到例如文件中。 但是在這種情況下,用戶顯然會從文件中恢復密鑰。

這是加密的基本屬性。 加密將少量數據(密鑰)的機密性替換為任意數量的數據(明文)的機密性。 有關此的更多信息: http : //blogs.msdn.com/b/ericlippert/archive/2011/09/27/keep-it-secret-keep-it-safe.aspx

因為您的游戲必須能夠讀取文件,所以它必須能夠訪問執行此操作所需的所有信息。 充其量,您正在尋找某種混淆。 您必須問自己一個問題:您真的很在乎作弊嗎?

是的,您當然可以加密和解密。 我會給你一個示例代碼。

您的加密類將如下所示

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM