StreamWriter を使用してデータをテキスト ファイルにエクスポートし、StreamReader を使用してデータを読み込む小さなプログラムをいくつか作成しました。これはうまく機能し、必要なことを行いますが、ユーザーが意図的または意図せずにアクセスまたは変更することなく、この情報を保存できる方法があるかどうか疑問に思っていました. テキストファイルにあるものの例は、チェックボックスがチェックされている場合です。チェックボックスをチェックすると、テキストファイルに「チェック済み」が出力され、プログラムが再度開かれると、フォームがどのような状態であったかがわかります。閉鎖されました。私は明らかにテキストファイルを使い続けたくありません。ユーザーが変更できないように、この情報を簡単に保存する方法について誰かアイデアがありますか? どうもありがとうございました。
9 に答える
最も簡単な方法は、このテキストを Base-64 でエンコード/デコードすることです。これは安全ではありませんが、一般ユーザーがデータを変更することを防ぎます。
static public string EncodeTo64(string toEncode)
{
byte[] toEncodeAsBytes
= System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
string returnValue
= System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}
static public string DecodeFrom64(string encodedData)
{
byte[] encodedDataAsBytes
= System.Convert.FromBase64String(encodedData);
string returnValue =
System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
return returnValue;
}
編集:本当の暗号化
#region Encryption
string passPhrase = "Pasword"; // can be any string
string saltValue = "sALtValue"; // can be any string
string hashAlgorithm = "SHA1"; // can be "MD5"
int passwordIterations = 7; // can be any number
string initVector = "~1B2c3D4e5F6g7H8"; // must be 16 bytes
int keySize = 256; // can be 192 or 128
private string Encrypt(string 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.ToBase64String(inArray);
}
private string Decrypt(string data)
{
byte[] bytes = Encoding.ASCII.GetBytes(this.initVector);
byte[] rgbSalt = Encoding.ASCII.GetBytes(this.saltValue);
byte[] buffer = Convert.FromBase64String(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.GetString(buffer5, 0, count);
}
#endregion
ProtectedData.Protect
ユーザーごとのキーを使用してデータを暗号化するには、を呼び出す必要があります。
熟練したユーザーがデータを解読して変更することはそれほど難しくないことに注意してください。
プログラムがユーザーのマシンで行うことはすべて、ユーザーも行うことができます。
すでに提案したように、構成データを(SHA1またはMD5で)base64エンコードまたは完全に暗号化することもできますが、(名前空間Configuration
の下で)構成データを処理するフレームワーククラスを操作することをお勧めします。暗号化機能が組み込まれています。System.Configuration
データ(クラスのProtectSection
メソッドを介して)。ConfigurationSection
まず、インスタンスを宣言して初期化する必要があります。
using System.Configuration;
...
static void Main(string[] args)
{
Configuration config;
config = ConfigurationManager.OpenExeConfiguration(/*path to config file*/); //Use ConfigurationManager.OpenMachineConfiguration(/*path to config file*/) when opening machine configuration
...
その後、構成を定義するカスタム構成セクションを定義する必要があります(msdnの例)
それが完了したら、カスタム構成セクションのインスタンスを初期化し、次のコードを使用して構成ファイルに追加する必要があります。
isTicked = config.Sections.Add("isTicked", customSection);
追加したセクションを暗号化するには、次のコードを使用します(VB.NETとC#の両方でさらに例を示します)。
config.Sections["isTicked"].SectionInformation.ProtectSection("protection provider");
「DPAPIProtectedConfigurationProvider」と「RSAProtectedConfigurationProvider」はデフォルトで組み込まれています。
セクションを復号化する場合は、次のコードを使用します。
config.Sections["isTicked"].SectionInformation.UnprotectSection();
要点を強調するために-暗号化と復号化の両方は、構成ファイルを保存した後にのみ有効になります
ファイルを保存するには、次のコードを使用します。
config.Save(); //config.SaveAs("string") is also available
Configuration
関連するクラスとメソッドの詳細については、上記のリンク先のクラスページから始まるmsdnを参照してください。
このコードを試して、テキストを暗号化および復号化してください! かなり簡単で強いと思います...
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 string Encrypt(this string text, string salt)
{
try
{
using (Aes aes = new AesManaged())
{
Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetString(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(String.Concat("Before encryption text data size: ", text.Length.ToString()));
System.Diagnostics.Debug.WriteLine(String.Concat("Before encryption byte data size: ", cleanText.Length.ToString()));
encrypt.Write(cleanText, 0, cleanText.Length);
encrypt.FlushFinalBlock();
}
byte[] encryptedData = encryptionStream.ToArray();
string encryptedText = Convert.ToBase64String(encryptedData);
System.Diagnostics.Debug.WriteLine(String.Concat("Encrypted text data size: ", encryptedText.Length.ToString()));
System.Diagnostics.Debug.WriteLine(String.Concat("Encrypted byte data size: ", encryptedData.Length.ToString()));
return encryptedText;
}
}
}
catch(Exception e)
{
return String.Empty;
}
}
public static string Decrypt(this string text, string salt)
{
try
{
using (Aes aes = new AesManaged())
{
Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetString(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.FromBase64String(text);
System.Diagnostics.Debug.WriteLine(String.Concat("Encrypted text data size: ", text.Length.ToString()));
System.Diagnostics.Debug.WriteLine(String.Concat("Encrypted byte data size: ", encryptedData.Length.ToString()));
decrypt.Write(encryptedData, 0, encryptedData.Length);
decrypt.Flush();
}
byte[] decryptedData = decryptionStream.ToArray();
string decryptedText = Encoding.UTF8.GetString(decryptedData, 0, decryptedData.Length);
System.Diagnostics.Debug.WriteLine(String.Concat("After decryption text data size: ", decryptedText.Length.ToString()));
System.Diagnostics.Debug.WriteLine(String.Concat("After decryption byte data size: ", decryptedData.Length.ToString()));
return decryptedText;
}
}
}
catch(Exception e)
{
return String.Empty;
}
}
}
Ionic zip ライブラリを使用して、これらのテキスト ファイルを圧縮できます。必要に応じて、パスワード保護や暗号化などの Ionic zip の機能を使用することもできます。また、最初にファイルを作成したときと同じ設定を使用して、ファイルを自分で手動で開くこともできます (たとえば、7zip などの圧縮アプリケーションを使用)。
プログラムが情報にアクセスできる場合、通常はユーザーもアクセスできます。ただし、ユーザーがすぐに理解できないデータを作成することはできます。
まず、保存するすべての状態情報を保持するクラスを作成して、問題を切り分けます。偶然にも、BinaryFormatter
クラスを使用すると、このクラスをファイルに簡単に保存およびロードできます。結果が「十分に読めない」かどうかはわかりません。そうでない場合は、レオンが述べたようにBase64エンコーディングを適用してください。
この回答で指摘されているように、チェックサムを使用して、意図しない文字列の変更を防ぐことができます。
ただし、広く使用されているアルゴリズムはそれほど多くないため、このようなチェックサムを生成するのは非常に簡単です。
したがって、意図的な変更から保護することはできません。
それを防ぐために、人々はデジタル署名を使用します。これにより、誰でもデータが改ざんされていないことを確認できますが、署名を生成できるのはあなた (秘密の秘密の所有者) だけです。
C# での例を次に示します。
ただし、他の人が指摘したように、バイナリのどこかに秘密鍵を埋め込む必要があり、.net dll を難読化したり、別のネイティブで作成したりしても、(そうではない) 熟練したプログラマーがそれを取得できます。処理する。
ただし、ほとんどの懸念事項にはそれで十分です。
セキュリティが本当に心配な場合は、クラウドに移動し、所有するマシンでコードを実行する必要があります。