Java C# 通用AES加密工具类

9 篇文章 0 订阅
3 篇文章 0 订阅

Java C# 通用AES加密工具类

参考:AES加密(java和C#)
为了解决C#与Java使用AES加密后内容不一致的问题,参考文章已经解决该问题,本篇只是在此基础上进行优化等。


C#:

using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

	/// <summary>
    /// AES工具
    /// </summary>
    public class AESUtils
    {
        /// <summary>
        /// AES加密(Base64)
        /// </summary>
        /// <param name="Plaintext">明文(UTF-8字符串)</param>
        /// <param name="Key">密钥</param>
        /// <param name="IV">向量(16位)</param>
        /// <returns>密文(Base64)</returns>
        public static string Encrypt_Base64(string Plaintext, string Key, string IV)
        {
            try
            {
                return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(Plaintext), GetKeyBySeed(Key), IV));
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// AES解密(Base64)
        /// </summary>
        /// <param name="Ciphertext">密文(Base64)</param>
        /// <param name="Key">密钥</param>
        /// <param name="IV">向量(16位)</param>
        /// <returns>明文(UTF-8字符串)</returns>
        public static string Decrypt_Base64(string Ciphertext, string Key, string IV)
        {
            try
            {
                return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(Ciphertext), GetKeyBySeed(Key), IV));
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// AES加密(16进制)
        /// </summary>
        /// <param name="Plaintext">明文(UTF-8字符串)</param>
        /// <param name="Key">密钥</param>
        /// <param name="IV">向量(16位)</param>
        /// <returns>密文(16进制)</returns>
        public static string Encrypt_Hex(string Plaintext, string Key, string IV)
        {
            try
            {
                return BytesToHexStr(Encrypt(Encoding.UTF8.GetBytes(Plaintext), GetKeyBySeed(Key), IV));
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// AES解密(16进制)
        /// </summary>
        /// <param name="Ciphertext">密文(16进制)</param>
        /// <param name="Key">密钥</param>
        /// <param name="IV">向量(16位)</param>
        /// <returns>明文(UTF-8字符串)</returns>
        public static string Decrypt_Hex(string Ciphertext, string Key, string IV)
        {
            try
            {
                return Encoding.UTF8.GetString(Decrypt(HexStrToBytes(Ciphertext), GetKeyBySeed(Key), IV));
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 用种子获取密钥
        /// </summary>
        /// <param name="Seed">种子</param>
        /// <param name="KeyLen">密钥长度(默认为16)</param>
        /// <returns>密钥Key</returns>
        public static byte[] GetKeyBySeed(string Seed, int KeyLen = 16)
        {
            byte[] bySeed = Encoding.UTF8.GetBytes(Seed);
            byte[] byKeyArray = null;
            using (var st = new SHA1CryptoServiceProvider())
            {
                using (var nd = new SHA1CryptoServiceProvider())
                {
                    var rd = nd.ComputeHash(st.ComputeHash(bySeed));
                    byKeyArray = rd.Take(KeyLen).ToArray();
                }
            }
            return byKeyArray;
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="Bytes">明文(byte[])</param>
        /// <param name="Key">密钥(byte[])</param>
        /// <param name="Vector">向量</param>
        /// <returns>密文(byte[])</returns>
        public static byte[] Encrypt(byte[] Bytes, byte[] Key, string Vector)
        {
            RijndaelManaged aes = new RijndaelManaged();
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            aes.Key = Key;
            aes.IV = Encoding.UTF8.GetBytes(Vector);

            ICryptoTransform cTransform = aes.CreateEncryptor();
            return cTransform.TransformFinalBlock(Bytes, 0, Bytes.Length);
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="Bytes">密文(byte[])</param>
        /// <param name="Key">密钥(byte[])</param>
        /// <param name="Vector">向量</param>
        /// <returns>明文(byte[])</returns>
        public static byte[] Decrypt(byte[] Bytes, byte[] Key, string Vector)
        {
            RijndaelManaged aes = new RijndaelManaged();
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            aes.Key = Key;
            aes.IV = Encoding.UTF8.GetBytes(Vector);

            ICryptoTransform cTransform = aes.CreateDecryptor();
            return cTransform.TransformFinalBlock(Bytes, 0, Bytes.Length);
        }

        /// <summary> 
        /// 字节数组 -> 十六进制字符串
        /// </summary> 
        /// <param name="Bytes"></param> 
        /// <returns>十六进制字符串</returns> 
        public static string BytesToHexStr(byte[] Bytes)
        {
            // 准备十六进制字符串
            string result = "";

            // 检查字节数组是否为空
            if (Bytes == null)
                return null;

            // 遍历字节数组
            for (int i = 0; i < Bytes.Length; i++)
                result += Bytes[i].ToString("X2");

            // 返回结果
            return result;
        }

        /// <summary>
        /// 十六进制字符串 -> 字节数组
        /// </summary>
        /// <param name="HexString">十六进制字符串</param>
        /// <returns>字节数组</returns>
        public static byte[] HexStrToBytes(string HexString)
        {
            // 检查十六进制字符串是否为奇数
            if (HexString.Length % 2 == 1)
            {
                return null;
            }

            // 十六进制字符串去重空白符
            HexString = Regex.Replace(HexString, @"\s", "");

            // 准备字节数组
            byte[] result = new byte[HexString.Length / 2];

            // 遍历十六进制字符串
            for (int i = 0; i < result.Length; i++)
                result[i] = Convert.ToByte(HexString.Substring(i * 2, 2), 16);

            // 返回结果
            return result;
        }
    }

Java:

package repalce.your.package;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES工具
 */
public class AESUtils {

	/**
	 * AES加密(16进制)
	 * 
	 * @param plaintext 明文(UTF-8字符串)
	 * @param key       密钥
	 * @param iv        向量(16位)
	 * @return 密文(16进制)
	 */
	public static String encryptHex(String plaintext, String key, String iv) {
		// 检查参数
		if (plaintext == null || "".equals((plaintext = plaintext.trim().replaceAll("\\s", "")))) {
			return null;
		}
		if (key == null || "".equals((key = key.trim().replaceAll("\\s", "")))) {
			return null;
		}
		if (iv == null || "".equals((iv = iv.trim().replaceAll("\\s", ""))) || iv.length() != 16) {
			return null;
		}

		try {
			return bytes2HexStr(encrypt(plaintext.getBytes("utf-8"), key.getBytes("utf-8"), iv.getBytes("utf-8")));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * AES解密(16进制)
	 * 
	 * @param ciphertext 密文(16进制)
	 * @param key        密钥
	 * @param iv         向量(16位)
	 * @return 明文(UTF-8字符串)
	 */
	public static String decryptHex(String ciphertext, String key, String iv) {
		// 检查参数
		if (ciphertext == null || "".equals((ciphertext = ciphertext.trim().replaceAll("\\s", "")))) {
			return null;
		}
		if (key == null || "".equals((key = key.trim().replaceAll("\\s", "")))) {
			return null;
		}
		if (iv == null || "".equals((iv = iv.trim().replaceAll("\\s", ""))) || iv.length() != 16) {
			return null;
		}

		try {
			return new String(decrypt(hexStr2Bytes(ciphertext), key.getBytes("utf-8"), iv.getBytes("utf-8")), "utf-8");
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * AES加密(Base64)
	 * 
	 * @param plaintext 明文(UTF-8字符串)
	 * @param key       密钥
	 * @param iv        向量(16位)
	 * @return 密文(Base64)
	 */
	public static String encryptBase64(String plaintext, String key, String iv) {
		// 检查参数
		if (plaintext == null || "".equals((plaintext = plaintext.trim().replaceAll("\\s", "")))) {
			return null;
		}
		if (key == null || "".equals((key = key.trim().replaceAll("\\s", "")))) {
			return null;
		}
		if (iv == null || "".equals((iv = iv.trim().replaceAll("\\s", ""))) || iv.length() != 16) {
			return null;
		}

		try {
			return Base64.getEncoder().encodeToString(encrypt(plaintext.getBytes("utf-8"), key.getBytes("utf-8"), iv.getBytes("utf-8")));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * AES解密(Base64)
	 * 
	 * @param ciphertext	密文(Base64)
	 * @param key       	密钥
	 * @param iv        	向量(16位)
	 * @return 明文(UTF-8字符串)
	 */
	public static String decryptBase64(String ciphertext, String key, String iv) {
		// 检查参数
		if (ciphertext == null || "".equals((ciphertext = ciphertext.trim().replaceAll("\\s", "")))) {
			return null;
		}
		if (key == null || "".equals((key = key.trim().replaceAll("\\s", "")))) {
			return null;
		}
		if (iv == null || "".equals((iv = iv.trim().replaceAll("\\s", ""))) || iv.length() != 16) {
			return null;
		}

		try {
			return new String(decrypt(Base64.getDecoder().decode(ciphertext), key.getBytes("utf-8"), iv.getBytes("utf-8")), "utf-8");
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * AES加密
	 * 
	 * @param plaintext 明文
	 * @param key       密钥
	 * @param iv        向量
	 * @return 密文
	 * @throws NoSuchPaddingException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidAlgorithmParameterException
	 * @throws InvalidKeyException
	 * @throws BadPaddingException
	 * @throws IllegalBlockSizeException
	 */
	public static byte[] encrypt(byte[] plaintext, byte[] key, byte[] iv)
			throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
			InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
		// 构造密钥生成器,指定为 AES 算法,不区分大小写
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		// 新增下面两行,处理 Linux 操作系统下随机数生成不一致的问题
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

		random.setSeed(key);
		kgen.init(128, random);

		// 根据字节数组生成AES密钥
		SecretKey secretKey = new SecretKeySpec(kgen.generateKey().getEncoded(), "AES");

		// 根据指定算法AES自成密码器
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		// 初始化密码器(向量必须是16位)
		cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));

		// 返回密文
		return cipher.doFinal(plaintext);
	}

	/**
	 * AES解密
	 * 
	 * @param ciphertext 密文
	 * @param key        密钥
	 * @param iv         向量
	 * @return 明文
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws InvalidAlgorithmParameterException
	 * @throws InvalidKeyException
	 * @throws BadPaddingException
	 * @throws IllegalBlockSizeException
	 */
	public static byte[] decrypt(byte[] ciphertext, byte[] key, byte[] iv)
			throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
			InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
		// 构造密钥生成器,指定为AES算法,不区分大小写
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		// 新增下面两行,处理 Linux 操作系统下随机数生成不一致的问题
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

		random.setSeed(key);
		kgen.init(128, random);

		// 根据字节数组生成AES密钥
		SecretKey secretKey = new SecretKeySpec(kgen.generateKey().getEncoded(), "AES");

		// 根据指定算法AES自成密码器
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		// 初始化密码器(向量必须是16位)
		cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));

		// 返回明文
		return cipher.doFinal(ciphertext);
	}

	/**
	 * 字节 --> 十六进制字符串
	 * 
	 * @param bytes 字节
	 * @return 十六进制字符串
	 */
	public static String bytes2HexStr(byte[] bytes) {
		// 检查字节是否为空
		if (bytes.length < 1)
			return null;

		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < bytes.length; i++) {
			String hex = Integer.toHexString(bytes[i] & 0xFF);

			if (hex.length() == 1) {
				hex = '0' + hex;
			}

			sb.append(hex.toUpperCase());
		}

		return sb.toString();
	}

	/**
	 * 十六进制字符串 --> 字节
	 * 
	 * @param hexStr 十六进制字符串
	 * @return 字节
	 */
	public static byte[] hexStr2Bytes(String hexStr) {
		// 检查十六进制字符串是否为空
		if (hexStr == null || "".equals(hexStr.trim()))
			return null;

		byte[] result = new byte[hexStr.length() / 2];

		for (int i = 0; i < hexStr.length() / 2; i++) {
			int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
			int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
			result[i] = (byte) (high * 16 + low);
		}

		return result;
	}
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#Java 都支持 AES 加密算法,因此可以在两种语言中进行加密和解密。下面是一个示例代码,演示了 C#Java 中如何使用 AES 加密和解密数据。 首先是 Java 中的代码,用于加密数据: ```java import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class AesEncryption { private static final String ALGORITHM = "AES/CBC/PKCS5Padding"; private static final String KEY = "0123456789abcdef"; // 16-byte key private static final String IV = "0123456789abcdef"; // 16-byte initialization vector public static String encrypt(String data) throws Exception { Cipher cipher = Cipher.getInstance(ALGORITHM); SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "AES"); IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); byte[] encrypted = cipher.doFinal(data.getBytes()); return Base64.getEncoder().encodeToString(encrypted); } } ``` 这个代码使用了 AES/CBC/PKCS5Padding 加密算法,采用了 16 字节的密钥和初始化向量。`encrypt()` 方法接受一个字符串参数,并返回加密后的字符串。 接下来是 C# 中的代码,用于解密数据: ```csharp using System; using System.Security.Cryptography; using System.Text; public class AesDecryption { private static readonly byte[] Key = Encoding.UTF8.GetBytes("0123456789abcdef"); // 16-byte key private static readonly byte[] Iv = Encoding.UTF8.GetBytes("0123456789abcdef"); // 16-byte initialization vector public static string Decrypt(string data) { byte[] encryptedData = Convert.FromBase64String(data); using (Aes aes = Aes.Create()) { aes.Key = Key; aes.IV = Iv; aes.Padding = PaddingMode.PKCS7; aes.Mode = CipherMode.CBC; ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); byte[] decrypted = decryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length); return Encoding.UTF8.GetString(decrypted); } } } ``` 这个代码使用了相同的 AES/CBC/PKCS5Padding 加密算法和 16 字节的密钥和初始化向量。`Decrypt()` 方法接受一个加密的字符串参数,并返回解密后的字符串。 使用这两个类,可以在 C#Java 中进行 AES 加密和解密操作。注意,密钥和初始化向量需要在两种语言中保持一致。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值