c#使用自带库对字符串进行AES加密、解密

37 篇文章 1 订阅
6 篇文章 0 订阅


参考文章: C#软件加密实例?
参考官文: Aes 类

在使用C#的自带的System.Security.Cryptography.Aes模块进行加密和解密时,需要注意的点是:定义用于对称算法的密钥Key初始化向量IV
如果不定义,就算是对相同字符串加密,每次得到的加密结果也都不一样。

1 代码

1.1 定义Aes加密类块
using System.IO;
using System.Security.Cryptography;

namespace Encryption
{
    internal class AesModule
    {
        Aes myAes = null;

        public AesModule()
        {
            // 创建一个Aes对象
            myAes = Aes.Create();
            // 【key的值获取方法见2.1】 
            myAes.Key = new byte[32] { 0xDD, 0xB7, 0xAA, 0xE5, 0xC6, 0x68, 0x95, 0x39, 0x72, 0x7C, 0x7F, 0xDC, 0x5B, 0xC9, 0x77, 0x21, 0x62, 0x59, 0xC4, 0x92, 0xBC, 0x7D, 0x44, 0xA7, 0x3D, 0x02, 0x37, 0x7B, 0x3C, 0x19, 0xEB, 0x7F };
            // 【IV的值获取方法见2.1】
            myAes.IV = new byte[16] { 0x84, 0xAA, 0xCD, 0x08, 0x21, 0xCE, 0x4D, 0xA7, 0x7B, 0x34, 0xD9, 0x9F, 0x28, 0x51, 0x8A, 0xEB };
        }
        ~AesModule()
        {
            myAes.Dispose();
        }
        /// <summary>
        /// 将字符串加密为字节数组
        /// </summary>
        /// <param name="original">待加密的字符串</param>
        /// <returns>加密好的字节数组</returns>
        public byte[] EncryptAes(string original)
        {
            if (original == null || original.Length <= 0) return null;
            byte[] encrypted;
            // 创建一个加密器来执行流转换。
            ICryptoTransform encryptor = myAes.CreateEncryptor(myAes.Key, myAes.IV);

            // 创建加密流。
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        //将原始文本写入流。
                        swEncrypt.Write(original);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
            return encrypted;
        }
        /// <summary>
        /// 将字节数组解密为字符串
        /// </summary>
        /// <param name="bArr">待解密的字节数组</param>
        /// <returns>解密好的字符串</returns>
        public string DecryptAes(byte[] bArr)
        {
            if (bArr == null || bArr.Length <= 0) return null;

            string plaintext = null;

            ICryptoTransform decryptor = myAes.CreateDecryptor(myAes.Key, myAes.IV);
            using (MemoryStream msDecrypt = new MemoryStream(bArr))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        // 从解密流中读取解密的字节。
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }
            return plaintext;
        }
    }
}
1.2 在主函数中调用
internal class Program
{
    static void Main(string[] args)
    {
        string original = "Here is some data to encrypt!";

        AesModule aes = new AesModule();	// 创建自定义Aes模块的对象
        Console.WriteLine("Original:   {0}", original);
        byte[] bArr = aes.EncryptAes(original);	// 加密
        Console.WriteLine("Encrypted:  {0}", BitConverter.ToString(bArr));
        Console.WriteLine("Decrypted: {0}", aes.DecryptAes(bArr));	// 解密
        Console.ReadLine();
    }
}

调用结果:

Original:   Here is some data to encrypt!
Encrypted:  6B-AB-9D-2A-54-16-59-1B-B7-5F-5C-F5-43-6B-D0-C2-E3-6A-72-98-8D-42-99-D9-38-DC-20-09-9C-94-6B-27
Decrypted: Here is some data to encrypt!

2 获取Key和IV

2.1 基本方法

其实方法就是:
定义Aes对象,然后调用它的函数GenerateXXX()方法,来生成Key和IV,并且写死到程序中。

internal class demo
{
    static void Main()
    {    	
    	using (Aes myAes = Aes.Create())	// 定义Aes对象
        {
            myAes.GenerateKey();			// 生成key
            Console.WriteLine("Key");			
            PrintBytes(myAes.Key);	
            		
            myAes.GenerateIV();				// 生成IV
            Console.WriteLine("IV");
            PrintBytes(myAes.IV);
        }
        Console.ReadLine();
    }
    /// <summary>
	/// 输出字节数组,加0x并按逗号分割
	/// </summary>
	/// <param name="bArr">待输出字节数组</param>
	static void PrintBytes(byte[] bArr)
	{
	    for (int i = 0; i < bArr.Length; i++)
	    {
	        if (i != 0) Console.Write(",");
	        Console.Write("0x" + bArr[i].ToString("X2")); // 其中"X2"表示以大写十六进制格式输出,并且占两个字符的宽度(不足两位时前面补0)
	    }
	    Console.WriteLine();
	}
}

得到结果(每次运行都不一样):

Key
0xDD,0xB7,0xAA,0xE5,0xC6,0x68,0x95,0x39,0x72,0x7C,0x7F,0xDC,0x5B,0xC9,0x77,0x21,0x62,0x59,0xC4,0x92,0xBC,0x7D,0x44,0xA7,0x3D,0x02,0x37,0x7B,0x3C,0x19,0xEB,0x7F
IV
0x84,0xAA,0xCD,0x08,0x21,0xCE,0x4D,0xA7,0x7B,0x34,0xD9,0x9F,0x28,0x51,0x8A,0xEB

将结果拷贝到代码中下述位置即可:

myAes.Key = new byte[32] { 【key】};
myAes.IV = new byte[16] {【IV】};
2.2 自定义Key

如果你想要生成自定义的Key,那么,也可以使用如下方法来生成。注意自定义字符串的位数(32位)。

byte[] key = Encoding.UTF8.GetBytes("Heisagoodboyandwillfindtruelove!");
PrintBytes(key);

会得到专属Key:

0x48,0x65,0x69,0x73,0x61,0x67,0x6F,0x6F,0x64,0x62,0x6F,0x79,0x61,0x6E,0x64,0x77,0x69,0x6C,0x6C,0x66,0x69,0x6E,0x64,0x74,0x72,0x75,0x65,0x6C,0x6F,0x76,0x65,0x21
2.3 技术方面的原理

这里仅略述该预定义AES类的使用原理:
Key定义了get-set函数,而且会自动生成Key,其源代码如下:

public virtual byte[] Key
{
    get
    {
        if (KeyValue == null)
        {
            GenerateKey();
        }
        ...
    }
    set
    {
        ...
        KeyValue = (byte[])value.Clone();
    }
}

IV类似。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
# 前端使用typescript和AES加密一个字符串 在前端使用typescript和AES加密一个字符串的例子中,我们可以使用crypto-js库来实现加密。首先,我们需要安装crypto-js库: ``` npm install crypto-js ``` 然后,我们可以使用以下代码来加密一个字符串: ```typescript import * as CryptoJS from 'crypto-js'; const key = CryptoJS.enc.Utf8.parse('1234567890123456'); const iv = CryptoJS.enc.Utf8.parse('1234567890123456'); const plaintext = 'Hello, world!'; const ciphertext = CryptoJS.AES.encrypt(plaintext, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); console.log(ciphertext.toString()); ``` 这里,我们使用了一个16字节的密钥和一个16字节的初始化向量来加密一个字符串。加密模式为CBC,填充模式为Pkcs7。 # 后端使用C 在后端使用C语言解密一个AES加密字符串的例子中,我们可以使用OpenSSL库来实现解密。首先,我们需要安装OpenSSL库: ``` sudo apt-get install libssl-dev ``` 然后,我们可以使用以下代码来解密一个字符串: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/aes.h> int main() { unsigned char key[] = "1234567890123456"; unsigned char iv[] = "1234567890123456"; unsigned char ciphertext[] = "U2FsdGVkX1+XKjJ5y5+5JfK5J5gJfZzJ"; unsigned char plaintext[128]; AES_KEY aes_key; AES_set_decrypt_key(key, 128, &aes_key); AES_cbc_encrypt(ciphertext, plaintext, sizeof(ciphertext), &aes_key, iv, AES_DECRYPT); printf("%s\n", plaintext); return 0; } ``` 这里,我们使用了一个16字节的密钥和一个16字节的初始化向量来解密一个字符串解密模式为CBC。注意,解密后的明文可能包含空字符,因此我们需要使用printf函数来输出明文。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值