c# aes算法时间限制超过时间解密失败笨办法

2023-05-25  本文已影响0人  吉凶以情迁

最不容易出错的写法

    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);
            }
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读