最不容易出错的写法
public static string Encrypt(string data, byte[] key, byte[] iv, DateTime expirationTime)
{
DateTimeOffset dateTimeOffset = new DateTimeOffset(expirationTime);
long timestamp = dateTimeOffset.ToUnixTimeSeconds(); // 转换为秒级时间
data = data + "." + timestamp;
// 要加密的字符串
// 生成密钥
/* byte[] key = Encoding.UTF8.GetBytes("0123456789abcdef");
// 生成 IV(初始化向量)
byte[] iv = Encoding.UTF8.GetBytes("fedcba9876543210");*/
// 创建 AES 算法的实例
using (Aes aes1 = Aes.Create())
{
// 设置算法的属性
aes1.Key = key;
aes1.IV = iv;
// 创建加密器
ICryptoTransform encryptor = aes1.CreateEncryptor();
// 将字符串转换为字节数组
byte[] data1 = Encoding.UTF8.GetBytes(data);
// 加密数据
byte[] encryptedData = encryptor.TransformFinalBlock(data1, 0, data1.Length);
// 将加密后的数据转换为字符串
string ciphertext = Convert.ToBase64String(encryptedData);
return ciphertext;
}
}
public static string? Decrypt(string data, byte[] key, byte[] iv)
{
using (Aes aes1 = Aes.Create())
{
// 设置算法的属性
aes1.Key = key;
aes1.IV = iv;
// 创建加密器
ICryptoTransform encryptor = aes1.CreateEncryptor();
// 将字符串转换为字节数组
byte[] data1 = Encoding.UTF8.GetBytes(data);
// 创建解密器
ICryptoTransform decryptor = aes1.CreateDecryptor();
// 将加密后的数据转换为字节数组
byte[] encryptedData2 = Convert.FromBase64String(data);
// 解密数据
byte[] decryptedData = decryptor.TransformFinalBlock(encryptedData2, 0, encryptedData2.Length);
// 将解密后的数据转换为字符串
string decryptedText = Encoding.UTF8.GetString(decryptedData);
int i = decryptedText.LastIndexOf(".");
if (i <= 0)
{
return decryptedText;
}
string time=decryptedText.Substring(i + 1);
long timestap=long.Parse(time);
DateTimeOffset expirationTime = DateTimeOffset.FromUnixTimeSeconds(timestap);
if (expirationTime.LocalDateTime < DateTime.Now)
{
return null;
}
string content = decryptedText.Substring(0, i);
return content;
}
}
有毛病的写法,解密的时候 虽然能解密但是多了很多\0 其次这个解密的文本长度不是已知的,要完善要调整,把长度也写入进去.
public static string Encrypt1(string data, byte[] key, byte[] iv, DateTime expirationTime)
{
using (var aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
// 将有效期截止时间转换为字节数组,然后将其写入内存流
DateTimeOffset dateTimeOffset = new DateTimeOffset(expirationTime);
long timestamp = dateTimeOffset.ToUnixTimeSeconds(); // 转换为秒级时间
byte[] expirationTimeBytes = BitConverter.GetBytes(timestamp);// expirationTime.ToBinary());
cryptoStream.Write(expirationTimeBytes, 0, expirationTimeBytes.Length);
Debug.WriteLine("时间:" + BitConverter.ToString(expirationTimeBytes) + ",长度:" + expirationTimeBytes.Length);
// 将要加密的数据写入内存流
var dataBytes = System.Text.Encoding.UTF8.GetBytes(data);
cryptoStream.Write(dataBytes, 0, dataBytes.Length);
cryptoStream.FlushFinalBlock();
string temp = Convert.ToBase64String(memoryStream.ToArray());
Debug.WriteLine("aes加密后:" + temp);
Debug.WriteLine("aesbypte加密后:" + BitConverter.ToString(memoryStream.ToArray()));
return temp;
}
}
}
}
public static string? Decrypt1(string data, byte[] key, byte[] iv, int len = 0)
{
Debug.WriteLine("aes解密前:" + data);
byte[] dataBytes = Convert.FromBase64String(data);
Debug.WriteLine("aesbypte解密后:" + BitConverter.ToString(dataBytes));
using (var aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
using (var memoryStream = new MemoryStream(dataBytes))
{
using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
using (var reader = new StreamReader(cryptoStream))
{
// 从内存流中读取有效期截止时间,并将其转换为DateTime
byte[] expirationTimeBytes = new byte[sizeof(long)];
cryptoStream.Read(expirationTimeBytes, 0, expirationTimeBytes.Length);
Debug.WriteLine("时间1:" + BitConverter.ToString(expirationTimeBytes) + ",长度:" + expirationTimeBytes.Length);
long value = BitConverter.ToInt64(expirationTimeBytes, 0);
DateTimeOffset expirationTime = DateTimeOffset.FromUnixTimeSeconds(value);
// var expirationTime = DateTime.FromBinary(value);// BitConverter.ToInt64(expirationTimeBytes, 0));
// 检查有效期是否已过期
if (expirationTime.LocalDateTime < DateTime.Now)
{
return null;
}
byte[] contentBytes = new byte[dataBytes.Length - expirationTimeBytes.Length];
int start = expirationTimeBytes.Length - 1;
int end = start + len;
cryptoStream.Read(contentBytes, start, end);// dataBytes.Length);
string result = Encoding.UTF8.GetString(contentBytes);
//string result= reader.ReadToEnd();
Debug.WriteLine("解密字符串后:" + result);
return result;
}
}
}
}
}
改良后的写法
using System;
using System.Security.Cryptography;
using System.Text;
class Program
{
static void Main(string[] args)
{
// 要加密的字符串
string plaintext = "Hello World!";
// 生成密钥和 IV(初始化向量)
byte[] key = Encoding.UTF8.GetBytes("0123456789abcdef");
byte[] iv = Encoding.UTF8.GetBytes("fedcba9876543210");
// 创建 AES 算法的实例
using (Aes aes = Aes.Create())
{
// 设置算法的属性
aes.Key = key;
aes.IV = iv;
// 创建加密器
ICryptoTransform encryptor = aes.CreateEncryptor();
// 将要加密的数据和当前时间戳合并为字节数组
byte[] data = Encoding.UTF8.GetBytes(plaintext);
byte[] timestamp = BitConverter.GetBytes(DateTimeOffset.UtcNow.ToUnixTimeSeconds());
byte[] combinedData = new byte[data.Length + timestamp.Length];
data.CopyTo(combinedData, 0);
timestamp.CopyTo(combinedData, data.Length);
// 加密数据
byte[] encryptedData = encryptor.TransformFinalBlock(combinedData, 0, combinedData.Length);
// 将加密后的数据转换为字符串
string ciphertext = Convert.ToBase64String(encryptedData);
Console.WriteLine("加密后的字符串:{0}", ciphertext);
// 创建解密器
ICryptoTransform decryptor = aes.CreateDecryptor();
// 将加密后的字符串转换为字节数组
byte[] encryptedData2 = Convert.FromBase64String(ciphertext);
// 解密数据
byte[] decryptedData = decryptor.TransformFinalBlock(encryptedData2, 0, encryptedData2.Length);
// 分离出时间戳和原始数据
int timestampSize = sizeof(long);
int dataSize = decryptedData.Length - timestampSize;
byte[] dataDecrypted = new byte[dataSize];
byte[] timestampDecrypted = new byte[timestampSize];
Array.Copy(decryptedData, 0, timestampDecrypted, 0, timestampSize);
Array.Copy(decryptedData, timestampSize, dataDecrypted, 0, dataSize);
// 验证时间戳是否过期
long timestampValue = BitConverter.ToInt64(timestampDecrypted, 0);
DateTimeOffset timestampOffset = DateTimeOffset.FromUnixTimeSeconds(timestampValue);
if (DateTimeOffset.UtcNow - timestampOffset > TimeSpan.FromDays(1))
{
Console.WriteLine("解密失败:数据已过期");
}
else
{
// 将解密后的数据转换为字符串并输出
string decryptedText = Encoding.UTF8.GetString(dataDecrypted);
Console.WriteLine("解密后的字符串:{0}", decryptedText);
}
}
}
}
网友评论