Rumah >Java >javaTutorial >Cara melaksanakan operasi penyulitan dan penyahsulitan AES dalam Java
Dalam kriptografi, algoritma penyulitan dibahagikan kepada penyulitan sehala dan penyulitan dua hala.
Penyulitan simetri bermakna penyulitan dan penyahsulitan menggunakan kunci yang sama, termasuk penyulitan AES, penyulitan DES, dsb.
Penyulitan asimetri bermaksud penyulitan dan penyahsulitan menggunakan kunci yang berbeza, termasuk penyulitan RSA, dsb.
Penyulitan sehala termasuk algoritma ringkasan seperti MD5 dan SHA, yang tidak boleh diterbalikkan.
Penyulitan dua hala termasuk penyulitan simetri dan penyulitan asimetri. Penyulitan dua hala boleh diterbalikkan, dan kunci kepada teks sifir wujud.
AES: Standard Penyulitan Lanjutan diterima pakai oleh kerajaan persekutuan A.S. penyulitan blok standard, salah satu yang paling popular pada masa ini
对称加密算法
.
ialah algoritma penyulitan blok generasi baharu yang digunakan untuk menggantikan DES.
AES menyokong tiga panjang kunci: 128 bit, 192 bit dan 256 bit.
Proses penyulitan dan penyahsulitan AES adalah sama seperti DES, kedua-duanya melalui 分组加密
dan kumpulan penyahsulitan . Penyulitan blok yang dipanggil adalah untuk mengumpulkan kandungan yang akan disulitkan dan dinyahsulitkan kepada kumpulan mengikut 128 bit, mengumpulkan kunci ke dalam kumpulan mengikut 128 bit, 192 bit, dan 256 bit, dan menyulitkan dan menyahsulit teks biasa yang dikumpulkan dan yang sepadan. kunci berkumpulan masing-masing.
Penyulitan: Selepas teks biasa dan kunci dikumpulkan, untuk setiap kumpulan: kumpulan teks biasa dan pemprosesan kumpulan kunci-> 10 pusingan penyulitan->
Penyahsulitan: Untuk setiap kumpulan: Kumpulan teks sifir -> Penambahan kunci bulat ->
Setiap kumpulan mempunyai panjang yang sama, 128 bit (16 bait);Kumpulan utama:
Terdapat 128 bit, 192 bit dan 256 bit bilangan pusingan penyulitan 10, 12, 14 masing-masingPemprosesan kumpulan utama:
Mengambil kumpulan kunci 128 bit setiap satu sebagai contoh (bilangan pusingan penyulitan yang disyorkan ialah 10, dan operasi adalah sama untuk 9 kali pertama, Masa kesepuluh adalah berbeza) Begitu juga, kunci 128-bit juga diwakili oleh matriks dalam bait Melalui fungsi susunan kunci, urutan 44 elemen terbentuk W[0],W[1], … , W[43] (setiap elemen ialah 4 bait antaranya, W[0], W[1], W[2], W[3] ialah kunci asal, dan baki 40 elemen dibahagikan kepada 10 kumpulan, setiap elemen Kumpulan 4 (4*4=16 bait), yang digunakan untuk 10 pusingan penyulitan masing-masing.Algoritma penyulitan AES melibatkan 4 operasi:
(SubBytes), (ShiftRows), (MixColumns) dan 字节替代
(AddRoundKey). 行移位
列混淆
Rajah berikut menunjukkan proses penyulitan dan penyahsulitan AES: 轮密钥加
Andaikan panjang sekeping plaintext ialah 192 bit, dan jika ia dipecahkan kepada satu blok plaintext setiap 128 bit, blok plaintext kedua hanya akan mempunyai 64 bit, iaitu kurang daripada 128 bit. Apa yang perlu dilakukan pada masa ini? Ia adalah perlu untuk melapik blok plaintext (Padding).
Padding melibatkan perkara berikut:
三种填充模式
NoPadding
PKCS5Padding
ISO10126Padding
Penyulitan:
penyulitan AES-> Teks SifirPenyahsulitan: Penyahsulitan Base64-> Penyahsulitan AES->
Jana 16 nombor rawak huruf besar dan huruf kecil dan nombor:
private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 数字和26个字母组成 private static final Random RANDOM = new SecureRandom(); /** * 获取长度为 6 的随机字母+数字 * @return 随机数字 */ public static String getRandomNumber() { char[] nonceChars = new char[16]; //指定长度为6位/自己可以要求设置 for (int index = 0; index < nonceChars.length; ++index) { nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } return new String(nonceChars); }
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Base64Utils; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * AES加密工具类 * * @author ACGkaka * @since 2021-06-18 19:11:03 */ public class AESUtil { /** * 日志相关 */ private static final Logger LOGGER = LoggerFactory.getLogger(AESUtil.class); /** * 编码 */ private static final String ENCODING = "UTF-8"; /** * 算法定义 */ private static final String AES_ALGORITHM = "AES"; /** * 指定填充方式 */ private static final String CIPHER_PADDING = "AES/ECB/PKCS5Padding"; private static final String CIPHER_CBC_PADDING = "AES/CBC/PKCS5Padding"; /** * 偏移量(CBC中使用,增强加密算法强度) */ private static final String IV_SEED = "1234567812345678"; /** * AES加密 * @param content 待加密内容 * @param aesKey 密码 * @return */ public static String encrypt(String content, String aesKey){ if(StringUtils.isBlank(content)){ LOGGER.info("AES encrypt: the content is null!"); return null; } //判断秘钥是否为16位 if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){ try { //对密码进行编码 byte[] bytes = aesKey.getBytes(ENCODING); //设置加密算法,生成秘钥 SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM); // "算法/模式/补码方式" Cipher cipher = Cipher.getInstance(CIPHER_PADDING); //选择加密 cipher.init(Cipher.ENCRYPT_MODE, skeySpec); //根据待加密内容生成字节数组 byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING)); //返回base64字符串 return Base64Utils.encodeToString(encrypted); } catch (Exception e) { LOGGER.info("AES encrypt exception:" + e.getMessage()); throw new RuntimeException(e); } }else { LOGGER.info("AES encrypt: the aesKey is null or error!"); return null; } } /** * 解密 * * @param content 待解密内容 * @param aesKey 密码 * @return */ public static String decrypt(String content, String aesKey){ if(StringUtils.isBlank(content)){ LOGGER.info("AES decrypt: the content is null!"); return null; } //判断秘钥是否为16位 if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){ try { //对密码进行编码 byte[] bytes = aesKey.getBytes(ENCODING); //设置解密算法,生成秘钥 SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM); // "算法/模式/补码方式" Cipher cipher = Cipher.getInstance(CIPHER_PADDING); //选择解密 cipher.init(Cipher.DECRYPT_MODE, skeySpec); //先进行Base64解码 byte[] decodeBase64 = Base64Utils.decodeFromString(content); //根据待解密内容进行解密 byte[] decrypted = cipher.doFinal(decodeBase64); //将字节数组转成字符串 return new String(decrypted, ENCODING); } catch (Exception e) { LOGGER.info("AES decrypt exception:" + e.getMessage()); throw new RuntimeException(e); } }else { LOGGER.info("AES decrypt: the aesKey is null or error!"); return null; } } /** * AES_CBC加密 * * @param content 待加密内容 * @param aesKey 密码 * @return */ public static String encryptCBC(String content, String aesKey){ if(StringUtils.isBlank(content)){ LOGGER.info("AES_CBC encrypt: the content is null!"); return null; } //判断秘钥是否为16位 if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){ try { //对密码进行编码 byte[] bytes = aesKey.getBytes(ENCODING); //设置加密算法,生成秘钥 SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM); // "算法/模式/补码方式" Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING); //偏移 IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING)); //选择加密 cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); //根据待加密内容生成字节数组 byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING)); //返回base64字符串 return Base64Utils.encodeToString(encrypted); } catch (Exception e) { LOGGER.info("AES_CBC encrypt exception:" + e.getMessage()); throw new RuntimeException(e); } }else { LOGGER.info("AES_CBC encrypt: the aesKey is null or error!"); return null; } } /** * AES_CBC解密 * * @param content 待解密内容 * @param aesKey 密码 * @return */ public static String decryptCBC(String content, String aesKey){ if(StringUtils.isBlank(content)){ LOGGER.info("AES_CBC decrypt: the content is null!"); return null; } //判断秘钥是否为16位 if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){ try { //对密码进行编码 byte[] bytes = aesKey.getBytes(ENCODING); //设置解密算法,生成秘钥 SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM); //偏移 IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING)); // "算法/模式/补码方式" Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING); //选择解密 cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); //先进行Base64解码 byte[] decodeBase64 = Base64Utils.decodeFromString(content); //根据待解密内容进行解密 byte[] decrypted = cipher.doFinal(decodeBase64); //将字节数组转成字符串 return new String(decrypted, ENCODING); } catch (Exception e) { LOGGER.info("AES_CBC decrypt exception:" + e.getMessage()); throw new RuntimeException(e); } }else { LOGGER.info("AES_CBC decrypt: the aesKey is null or error!"); return null; } } public static void main(String[] args) { // AES支持三种长度的密钥:128位、192位、256位。 // 代码中这种就是128位的加密密钥,16字节 * 8位/字节 = 128位。 String random = RandomStringUtils.random(16, "abcdefghijklmnopqrstuvwxyz1234567890"); System.out.println("随机key:" + random); System.out.println(); System.out.println("---------加密---------"); String aesResult = encrypt("测试AES加密12", random); System.out.println("aes加密结果:" + aesResult); System.out.println(); System.out.println("---------解密---------"); String decrypt = decrypt(aesResult, random); System.out.println("aes解密结果:" + decrypt); System.out.println(); System.out.println("--------AES_CBC加密解密---------"); String cbcResult = encryptCBC("测试AES加密12456", random); System.out.println("aes_cbc加密结果:" + cbcResult); System.out.println(); System.out.println("---------解密CBC---------"); String cbcDecrypt = decryptCBC(cbcResult, random); System.out.println("aes解密结果:" + cbcDecrypt); System.out.println(); } }
随机key:golrtt58318fx7ol ---------加密--------- aes加密结果:Xy8W9lCeVue9Ao36z+duM7D7WeS5tdBihIMb1q9KpNg= ---------解密--------- aes解密结果:测试AES加密12 --------AES_CBC加密解密--------- aes_cbc加密结果:xs3ypQXyd62P9jB0+RvOqxFnHIHBIlVdqoZLuqYNBLw= ---------解密CBC--------- aes解密结果:测试AES加密12456
Atas ialah kandungan terperinci Cara melaksanakan operasi penyulitan dan penyahsulitan AES dalam Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!