gpt4 book ai didi

c# - 如何使用 AES 在一个程序中加密,在另一个程序中解密

转载 作者:行者123 更新时间:2023-12-02 21:28:24 25 4
gpt4 key购买 nike

有人告诉我not to use RSA 加密简单文本但使用 AES。我找到了一段简单的代码来实现 AES:

public static class Crypto
{
#region Settings

private static int _iterations = 2;
private static int _keySize = 256;

private static string _hash = "SHA1";
private static string _salt = "aselrias38490a32"; // Random
private static string _vector = "8947az34awl34kjq"; // Random

#endregion

public static string Encrypt(string value, string password)
{
return Encrypt<AesManaged>(value, password);
}

public static string Encrypt<T>(string value, string password)
where T : SymmetricAlgorithm, new()
{

byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector);
byte[] saltBytes = Encoding.ASCII.GetBytes(_salt);
byte[] valueBytes = Encoding.UTF8.GetBytes(value);

byte[] encrypted;
using (T cipher = new T())
{
PasswordDeriveBytes _passwordBytes =
new PasswordDeriveBytes(password, saltBytes, _hash, _iterations);
byte[] keyBytes = _passwordBytes.GetBytes(_keySize/8);

cipher.Mode = CipherMode.CBC;

using (ICryptoTransform encryptor = cipher.CreateEncryptor(keyBytes, vectorBytes))
{
using (MemoryStream to = new MemoryStream())
{
using (CryptoStream writer = new CryptoStream(to, encryptor, CryptoStreamMode.Write))
{
writer.Write(valueBytes, 0, valueBytes.Length);
writer.FlushFinalBlock();
encrypted = to.ToArray();
}
}
}
cipher.Clear();
}
return Convert.ToBase64String(encrypted);
}

public static string Decrypt(string value, string password)
{
return Decrypt<AesManaged>(value, password);
}

public static string Decrypt<T>(string value, string password) where T : SymmetricAlgorithm, new()
{
byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector);
byte[] saltBytes = Encoding.ASCII.GetBytes(_salt);
byte[] valueBytes = Convert.FromBase64String(value);

byte[] decrypted;
int decryptedByteCount = 0;

using (T cipher = new T())
{
PasswordDeriveBytes _passwordBytes = new PasswordDeriveBytes(password, saltBytes, _hash, _iterations);
byte[] keyBytes = _passwordBytes.GetBytes(_keySize/8);

cipher.Mode = CipherMode.CBC;

try
{
using (ICryptoTransform decryptor = cipher.CreateDecryptor(keyBytes, vectorBytes))
{
using (MemoryStream from = new MemoryStream(valueBytes))
{
using (CryptoStream reader = new CryptoStream(from, decryptor, CryptoStreamMode.Read))
{
decrypted = new byte[valueBytes.Length];
decryptedByteCount = reader.Read(decrypted, 0, decrypted.Length);
}
}
}
}
catch (Exception ex)
{
return String.Empty;
}

cipher.Clear();
}
return Encoding.UTF8.GetString(decrypted, 0, decryptedByteCount);
}

}

但是,这是基于返回的字符串,然后用于在同一程序中解密。我需要在 WinForms 程序中加密以下数据,并在整个单独的 Windows 服务程序中解密:

string fileName = System.IO.Path.Combine(Application.StartupPath, "alphaService.xml");
XDocument doc = new XDocument();
XElement xml = new XElement("Info",
new XElement("DatabaseServerName", txtServerName.Text),
new XElement("DatabaseUserName", txtDatabaseUserName.Text),
new XElement("DatabasePassword", txtDatabasePassword.Text),
new XElement("ServiceAccount", txtAccount.Text),
new XElement("ServicePassword", txtServicePassword.Text),
new XElement("RegistrationCode", txtRegistrationCode.Text));

doc.Add(xml);
doc.Save(fileName);

// Convert XML doc to byte stream
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(fileName);

// byte[] fileBytes = Encoding.Default.GetBytes(xmlDoc.OuterXml);

string encrypted = Crypto.Encrypt(xmlDoc.OuterXml, "testpass");

我该怎么做?请显示示例代码。

编辑:凯文,我已经实现了你的算法,但问题是我想生成一次 key 并将其保存以供其他程序解密使用,但我需要将 byte[] 传递给加密函数。所以我尝试使用 System.Text.Encoding.ASCII.GetBytes(key); 进行转换而且它做得不正确。我的 key byte[] 的字节数错误。

string fileName = System.IO.Path.Combine(Application.StartupPath, "alphaService.xml");
XDocument doc = new XDocument();
XElement xml = new XElement("Info",
new XElement("DatabaseServerName", txtServerName.Text),
new XElement("DatabaseUserName", txtDatabaseUserName.Text),
new XElement("DatabasePassword", txtDatabasePassword.Text),
new XElement("ServiceAccount", txtAccount.Text),
new XElement("ServicePassword", txtServicePassword.Text),
new XElement("RegistrationCode", txtRegistrationCode.Text));

doc.Add(xml);
doc.Save(fileName);

// Read file to a string
string contents = File.ReadAllText(fileName);

string key = String.Empty;
byte[] aesKey;
using (var aes = Aes.Create())
{
// aesKey = aes.Key;
key = Convert.ToBase64String(aes.Key);
}

string sKey = "LvtZELDrB394hbSOi3SurLWAvC8adNpZiJmQDJHdfJU=";
aesKey = System.Text.Encoding.UTF8.GetBytes(sKey);

string encyptedText = EncryptDecrpt.EncryptStringToBase64String(contents, aesKey);
File.WriteAllText(fileName, encyptedText);

EDIT2:这是现在的两个部分。加密端:

private void SaveForm()
{
try
{
string fileName = System.IO.Path.Combine(Application.StartupPath, "alphaService.xml");
XDocument doc = new XDocument();
XElement xml = new XElement("Info",
new XElement("DatabaseServerName", txtServerName.Text),
new XElement("DatabaseUserName", txtDatabaseUserName.Text),
new XElement("DatabasePassword", txtDatabasePassword.Text),
new XElement("ServiceAccount", txtAccount.Text),
new XElement("ServicePassword", txtServicePassword.Text),
new XElement("RegistrationCode", txtRegistrationCode.Text));

doc.Add(xml);
// doc.Save(fileName);

// Read file to a string
// string contents = File.ReadAllText(fileName);

string key = String.Empty;
byte[] aesKey;
//using (var aes = Aes.Create())
//{
// aesKey = aes.Key;
// key = Convert.ToBase64String(aes.Key);
//}

string sKey = "LvtZELDrB394hbSOi3SurLWAvC8adNpZiJmQDJHdfJU=";
aesKey = Convert.FromBase64String(sKey);

string encyptedText = EncryptDecrpt.EncryptStringToBase64String(doc.ToString(), aesKey);
File.WriteAllText(fileName, encyptedText);
//doc.Save(fileName);

尝试解密的 Windows 服务端:

try
{
string path = AppDomain.CurrentDomain.BaseDirectory;
eventLog1.WriteEntry(path);
string fileName = System.IO.Path.Combine(path, "alphaService.xml");

string sKey = "LvtZELDrB394hbSOi3SurLWAvC8adNpZiJmQDJHdfJU=";
Byte[] keyBytes = Convert.FromBase64String(sKey);

var encryptedText = File.ReadAllText(fileName, new ASCIIEncoding());
string xmlStr = DecryptStringFromBase64String(encryptedText, keyBytes);

eventLog1.WriteEntry(xmlStr);

using (XmlReader reader = XmlReader.Create(new StringReader(xmlStr)))
{
reader.ReadToFollowing("DatabaseServerName");
DatabaseServerName = reader.ReadElementContentAsString();
reader.ReadToFollowing("DatabaseUserName");
DatabaseUserName = reader.ReadElementContentAsString();
reader.ReadToFollowing("DatabasePassword");
DatabasePassword = reader.ReadElementContentAsString();
reader.ReadToFollowing("RegistrationCode");
RegistrationCode = reader.ReadElementContentAsString();
}
eventLog1.WriteEntry("Configuration data loaded successfully");
}
catch (Exception ex)
{
eventLog1.WriteEntry("Unable to load configuration data. " + ex.Message);
}

最佳答案

我在下面编写的算法使用随机初始化向量,将其放在加密值的开头,这样您就可以对相同的值加密两次,而不会获得相同的加密输出。这是相当正常的,并且只允许您来回传递一个“ secret ”。

您将需要通过某些越界进程共享您的 key ,因为加密和解密都需要知道 key 。这是在其他地方记录的 key 交换的单独主题。 Here这是一个 SO 链接,如果您需要一些帮助,可以帮助您入门。

此外,如果您正在“编造”随机值,我建议您不要这样做。使用以下内容可以帮助您生成随机字节,然后将它们转换为 base64 字符串,这对于人类使用或某些类型的 key 交换来说更容易。请注意,这只是如何生成随 secret 钥的示例...实际上,这可能基于一些可重新创建的用户输入,或者您使用用户哈希值来查找您生成的随 secret 钥。无论如何,这里是 key 的代码...

byte[] key;
string base64Key;
using (var aes = Aes.Create())
{
// key as byte[]
key = aes.Key;
// key as base64string - which one you use depends on how you store your keys
base64Key= Convert.ToBase64String(aes.Key);
}

使用方法如下...

    // you get the base64 encoded key from somewhere
var base64Key = "+CffHxKmykUvCrrCILd4rZDBcrIoe3w89jnPNXYi0rU=";
// convert it to byte[] or alternatively you could store your key as a byte[]
// but that depends on how you set things up.
var key = Convert.FromBase64String(base64Key);
var plainText = "EncryptThis";
var encryptedText = EncryptStringToBase64String(plainText, key);
var decryptedText = DecryptStringFromBase64String(encryptedText, key);

以下是加密方法...EncryptStringToBase64StringDecryptStringFromBase64String

编辑:关于使用 Aes.BlockSize 作为 IV 大小的观点非常好。我还清理了争论检查。

    private const int KeySize = 256; // in bits
static string EncryptStringToBase64String(string plainText, byte[] Key)
{
// Check arguments.
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
byte[] returnValue;
using (var aes = Aes.Create())
{
aes.KeySize = KeySize;
aes.GenerateIV();
aes.Mode = CipherMode.CBC;
var iv = aes.IV;
if (string.IsNullOrEmpty(plainText))
return Convert.ToBase64String(iv);
var encryptor = aes.CreateEncryptor(Key, iv);

// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
// this is just our encrypted data
var encrypted = msEncrypt.ToArray();
returnValue = new byte[encrypted.Length + iv.Length];
// append our IV so our decrypt can get it
Array.Copy(iv, returnValue, iv.Length);
// append our encrypted data
Array.Copy(encrypted, 0, returnValue, iv.Length, encrypted.Length);
}
}
}

// return encrypted bytes converted to Base64String
return Convert.ToBase64String(returnValue);
}

static string DecryptStringFromBase64String(string cipherText, byte[] Key)
{
// Check arguments.
if (string.IsNullOrEmpty(cipherText))
return string.Empty;
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");

string plaintext = null;
// this is all of the bytes
var allBytes = Convert.FromBase64String(cipherText);

using (var aes = Aes.Create())
{
aes.KeySize = KeySize;
aes.Mode = CipherMode.CBC;

// get our IV that we pre-pended to the data
byte[] iv = new byte[aes.BlockSize/8];
if (allBytes.Length < iv.Length)
throw new ArgumentException("Message was less than IV size.");
Array.Copy(allBytes, iv, iv.Length);
// get the data we need to decrypt
byte[] cipherBytes = new byte[allBytes.Length - iv.Length];
Array.Copy(allBytes, iv.Length, cipherBytes, 0, cipherBytes.Length);

// Create a decrytor to perform the stream transform.
var decryptor = aes.CreateDecryptor(Key, iv);

// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherBytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}

return plaintext;
}

编辑 2:切勿使用 TextEncoding 将实际的二进制数据(如随 secret 钥)转换为字符串。如果数据以字符串形式开始,并且您使用编码将其转换为二进制,则且仅此您可以使用正确的编码将其从二进制转换为字符串吗?否则,您的代码将有时工作,这是折磨自己的良方。

        // This is base64 not UTF8, unicode, ASCII or anything else!!!
string sKey = "LvtZELDrB394hbSOi3SurLWAvC8adNpZiJmQDJHdfJU=";
aesKey = Convert.FromBase64String(sKey);

编辑3:

为什么写入文件时使用File.WriteAllText,而读取文件时却使用File.ReadAllBytes?您可以将其作为文本写入和读取,并使用 ASCII 编码,因为 base64 保证是 ASCII。 Decrypt 还会返回一个您未存储或使用的解密字符串。解密后的字符串是您需要解析的内容,因为它是您的 xml。

您可以使用它来保存文件...

    var encryptedText = File.ReadAllText(fileName, new ASCIIEncoding());

在解密中你应该这样做...

    var encryptedText = File.ReadAllText(fileName, new ASCIIEncoding());
string xmlStr = DecryptStringFromBase64String(encryptedStr , keyBytes);

编辑4:我试图复制您的异常,但无法实现...这是我在控制台应用程序中运行的测试代码,它可以工作。

public static void EncryptMethod()
{
var fileName = @"c:/text.xml";
XDocument doc = new XDocument();
XElement xml = new XElement("Info",
new XElement("DatabaseServerName", "txtServerName.Text"),
new XElement("DatabaseUserName", "txtDatabaseUserName.Text"),
new XElement("DatabasePassword", "txtDatabasePassword.Text"),
new XElement("ServiceAccount", "txtAccount.Text"),
new XElement("ServicePassword", "txtServicePassword.Text"),
new XElement("RegistrationCode", "txtRegistrationCode.Text"));
doc.Add(xml);

var sKey = "LvtZELDrB394hbSOi3SurLWAvC8adNpZiJmQDJHdfJU=";
var aesKey = Convert.FromBase64String(sKey);

string encyptedText = EncryptStringToBase64String(doc.ToString(), aesKey);
File.WriteAllText(fileName, encyptedText);
}


public static void DecryptMethod()
{
var fileName = @"c:/text.xml";
string sKey = "LvtZELDrB394hbSOi3SurLWAvC8adNpZiJmQDJHdfJU=";
Byte[] keyBytes = Convert.FromBase64String(sKey);

var encryptedText = File.ReadAllText(fileName, new ASCIIEncoding());
string xmlStr = DecryptStringFromBase64String(encryptedText, keyBytes);

using (XmlReader reader = XmlReader.Create(new StringReader(xmlStr)))
{
reader.ReadToFollowing("DatabaseServerName");
Console.WriteLine(reader.ReadElementContentAsString());
reader.ReadToFollowing("DatabaseUserName");
Console.WriteLine(reader.ReadElementContentAsString());
reader.ReadToFollowing("DatabasePassword");
Console.WriteLine(reader.ReadElementContentAsString());
reader.ReadToFollowing("RegistrationCode");
Console.WriteLine(reader.ReadElementContentAsString());
}
}

从控制台应用程序的使用...

    EncryptMethod();
DecryptMethod();

关于c# - 如何使用 AES 在一个程序中加密,在另一个程序中解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22920337/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com