찾다
Javajava지도 시간Java에서 AES 암호화 및 암호 해독 작업을 수행하는 방법

1. 배경 지식

Java에서 AES 암호화 및 암호 해독 작업을 수행하는 방법

  • 암호화에서 암호화 알고리즘은 단방향 암호화와 양방향 암호화로 구분됩니다.

    • 대칭 암호화는 AES 암호화, DES 암호화 등을 포함하여 암호화와 복호화가 동일한 키를 사용함을 의미합니다.

    • 비대칭 암호화는 RSA 암호화 등을 포함하여 암호화와 복호화가 서로 다른 키를 사용한다는 의미입니다.

    • 단방향 암호화에는 되돌릴 수 없는 MD5 및 SHA와 같은 다이제스트 알고리즘이 포함됩니다.

    • 양방향 암호화에는 대칭 암호화와 비대칭 암호화가 포함됩니다. 양방향 암호화는 되돌릴 수 있으며 암호문에 대한 키가 존재합니다.

2. AES 소개

AES: 고급 암호화 표준(Advanced Encryption Standard)은 미국 연방 정부에서 채택한 블록 암호화 표준으로 현재 가장 널리 사용되는 ​​대칭 암호화 알고리즘입니다. 코드>. 对称加密算法

  • 是用来替代DES的新一代分组加密算法。

  • AES支持三种长度的密钥:128位、192位、256位。

3.AES的加密过程(AES处理单位:字节)

AES的加解密过程和DES一样,都是通过分组加密、分组解密。所谓分组加密,就是将待加解密的内容按照128位进行分组,将密钥按照128位、192位、256位进行分组,分别将分组后的明文与相应分组后的密钥进行加解密。

加密: 明文与密钥分组后,对每组:明文组与密钥组处理 -> 轮密钥加 -> 10轮加密 -> 密文组

解密: 对每组:密文组 -> 轮密钥加 -> 10轮解密 -> 明文组

明文分组: 每组长度相等,都是128位(16字节);

密钥分组: 有128位、192位、256位,推荐加密轮数分别为 10、12、14

密钥组处理: 以密钥分组每组128位为例(则推荐加密轮数为10,前9次执行操作一样,第十次有所不同) 类似地,128位密钥也是用字节为单位的矩阵表示,通过密钥编排函数,形成具有44个元素的序列W[0],W[1], … ,W[43](每个元素4个字节);其中,W[0],W[1],W[2],W[3]为原始密钥,其余40个元素分为10组,每组4个元素(4*4=16字节),分别用于10轮加密。

AES加密算法涉及4种操作: 字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。

下图给出了AES加解密的流程:

  • AddRoundKey (轮密钥加)— 矩阵中的每一个字节都与该次轮密钥(round key)做XOR运算;每个子密钥由密钥生成方案产生。

  • SubBytes(字节替代) — 通过非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。

  • ShiftRows(行移位) — 将矩阵中的每个横列进行循环式移位。

  • MixColumns (列混淆)— 为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每列的四个字节。

Java에서 AES 암호화 및 암호 해독 작업을 수행하는 방법

假如一段明文长度是192bit,如果按每128bit一个明文块来拆分的话,第二个明文块只有64bit,不足128bit。这时候怎么办呢?就需要对明文块进行填充(Padding)。

填充涉及以下三种填充模式

  • NoPadding:不做任何填充,但是要求明文必须是16字节的整数倍。

  • PKCS5Padding(默认):如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。

比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6}

  • ISO10126Padding

은 DES를 대체하는 데 사용되는 차세대 블록 암호화 알고리즘입니다.

AES는 128비트, 192비트, 256비트의 세 가지 키 길이를 지원합니다.

3. AES 암호화 과정(AES 처리 단위: 바이트)

AES의 암호화 및 복호화 과정은 블록 암호화와 그룹 복호화 모두 DES와 동일합니다. 소위 블록 암호화란 암호화 및 복호화할 내용을 128비트 단위로 그룹화하고, 키를 128비트, 192비트, 256비트 단위로 그룹화하고, 그룹화된 평문과 이에 상응하는 평문을 암호화 및 복호화하는 것입니다. 그룹화된 키입니다.

암호화:

일반 텍스트와 키를 그룹화한 후 각 그룹 처리: 일반 텍스트 그룹 및 키 그룹-> 10라운드 암호화-> 암호문 그룹

복호화:

오른쪽 각 그룹: 암호 텍스트 그룹-> 라운드 키 추가-> 일반 텍스트 그룹

일반 텍스트 그룹: 🎜 각 그룹의 길이는 모두 128비트(16바이트)입니다. 그룹화: 🎜 권장되는 암호화 라운드는 각각 10, 12, 14비트입니다. 🎜🎜🎜키 그룹 처리: 🎜 그룹당 128비트의 키 그룹화를 예로 들어 보겠습니다. 권장 암호화 라운드 수는 10이며 처음 9번은 연산이 동일하고 10번은 다름) 마찬가지로 128비트 키도 바이트 단위의 행렬로 표현되며 키 배열 기능을 사용하여 44개 요소를 포함하는 시퀀스 W[0], W[1], &hellip, W[43](요소당 4바이트), W[0], W[1], W[2], W[3 ]는 원본 키이고, 나머지 40개 요소는 10개 그룹으로 나뉘며, 각 그룹에는 4개 요소(4*4=16바이트)가 있으며, 이는 각각 10라운드 암호화에 사용됩니다. 🎜🎜🎜AES 암호화 알고리즘에는 4가지 작업이 포함됩니다: 🎜 바이트 대체(SubBytes), 행 이동(ShiftRows), 열 난독화(MixColumns) 및 라운드 키 추가(AddRoundKey). 🎜🎜다음 그림은 AES 암호화 및 암호 해독 프로세스를 보여줍니다. 🎜🎜🎜🎜🎜AddRoundKey(라운드 키 추가)🎜— 매트릭스의 각 바이트는 라운드 키와 XOR됩니다. 각 하위 키는 키 생성 방식에 의해 생성됩니다. . 🎜🎜🎜🎜🎜SubBytes(바이트 대체)🎜 — 비선형 대체 함수를 통해 조회 테이블을 사용하여 각 바이트를 해당 바이트로 대체합니다. 🎜🎜🎜🎜🎜ShiftRows(행 이동)🎜 — 행렬의 각 열을 순환적으로 이동합니다. 🎜🎜🎜🎜🎜MixColumns (열 혼동)🎜— 행렬의 각 직선 행의 연산을 완전히 혼합하기 위해. 이 단계에서는 선형 변환을 사용하여 각 열의 4바이트를 혼합합니다. 🎜🎜🎜🎜Java를 사용하여 AES 암호화 및 암호 해독을 구현하는 방법🎜 🎜문단의 경우 평문의 길이가 192비트라면 128비트마다 하나의 평문 블록으로 분할되면 두 번째 평문 블록은 64비트에 불과해 128비트보다 작습니다. 이때 무엇을 해야 할까요? 일반 텍스트 블록을 패딩(Padding)하는 것이 필요합니다. 🎜🎜Padding에는 다음 세 가지 패딩 모드가 포함됩니다. 🎜🎜🎜🎜NoPadding: 패딩은 수행되지 않지만 일반 텍스트는 16바이트의 정수 배수여야 합니다. 🎜🎜🎜🎜PKCS5Padding(기본값): 일반 텍스트 블록이 16바이트(128비트) 미만인 경우 해당 문자 수가 일반 텍스트 블록 끝에 추가되고 각 바이트의 값 누락된 문자 번호와 같습니다. 🎜🎜🎜🎜예를 들어 일반 텍스트가 {1,2,3,4,5,a,b,c,d,e}인 경우 6바이트가 누락되면 완성은 {1,2, 3,4,5, a,b,c,d,e,6,6,6,6,6,6}🎜🎜🎜🎜ISO10126Padding: 일반 텍스트 블록이 16바이트 미만인 경우 (128bit), 일반 텍스트에서 블록의 끝은 해당 바이트 수로 채워지고 마지막 문자 값은 누락된 문자 수와 동일하며 나머지 문자는 임의의 숫자로 채워집니다. 🎜🎜🎜🎜예를 들어 일반 텍스트: {1,2,3,4,5,a,b,c,d,e}, 6바이트가 누락된 경우 완성은 {1,2,3,4일 수 있습니다. ,5 ,a,b,c,d,e,5,c,3,G,$,6}🎜🎜4.Java 구현🎜🎜🎜참고: AES 암호화에는 Base64 암호화가 포함됩니다🎜🎜🎜🎜🎜암호화:🎜 AES 암호화-> Base64 암호화-> 암호문 🎜🎜🎜 복호화: 🎜 Base64 복호화-> 일반 텍스트 🎜🎜🎜 테스트 주소: 여기를 클릭하세요 🎜🎜

4.1 키 및 오프셋 생성

16개의 임의의 대문자, 소문자 및 숫자 생성:

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);
}

4.2 AESUtil.java 소스 코드

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();
    }
}

4.3 실행 결과

随机key:golrtt58318fx7ol
---------加密---------
aes加密结果:Xy8W9lCeVue9Ao36z+duM7D7WeS5tdBihIMb1q9KpNg=
---------解密---------
aes解密结果:测试AES加密12
--------AES_CBC加密解密---------
aes_cbc加密结果:xs3ypQXyd62P9jB0+RvOqxFnHIHBIlVdqoZLuqYNBLw=
---------解密CBC---------
aes解密结果:测试AES加密12456

4.4 온라인 확인

Java에서 AES 암호화 및 암호 해독 작업을 수행하는 방법

위 내용은 Java에서 AES 암호화 및 암호 해독 작업을 수행하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 亿速云에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)