Java - AES对称加密算法

in TCEHJava with 0 comment

一、简介

  高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图:
1.png

下面简单介绍下各个部分的作用与意义:

明文P

没有经过加密的数据。

密钥K

用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。

密文C

经加密函数处理后的数据

AES加密函数

设AES加密函数为E,则 C = E(K, P),其中P为明文,K为密钥,C为密文。也就是说,把明文P和密钥K作为加密函数的参数输入,则加密函数E会输出密文C。

AES解密函数

设AES解密函数为D,则 P = D(K, C),其中C为密文,K为密钥,P为明文。也就是说,把密文C和密钥K作为解密函数的参数输入,则解密函数会输出明文P。

在这里简单介绍下对称加密算法与非对称加密算法的区别。

对称加密算法

加密和解密用到的密钥是相同的,这种加密方式加密速度非常,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。

非对称加密算法

加密和解密用的密钥是不同的,这种加密方式是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA、ECC和EIGamal。

实际中,一般是通过RSA加密AES的密钥,传输到接收方,接收方解密得到AES密钥,然后发送方和接收方用AES密钥来通信。

二、AES加密、解密示例

package com.back.web;

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

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AESTest {
    private static final String KEY_ALGORITHM = "AES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";// 默认的加密算法

    /**
     * AES 加密操作
     *
     * @param content
     *            待加密内容
     * @param password
     *            加密密码
     * @return 返回Base64转码后的加密数据
     */
    public static String encrypt(String content, String password) throws Exception {
        // 创建密码器
        Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

        // 字符集设为形参
        byte[] byteContent = content.getBytes("utf-8");

        // 初始化为加密模式的密码器
        cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));

        // 加密
        byte[] result = cipher.doFinal(byteContent);

        // 通过Base64转码返回
        return Base64.getEncoder().encodeToString(result);
    }

    /**
     * AES 解密操作
     *
     * @param content
     *            密文
     * @param password
     *            加密密码
     * @return 加密前原字符串
     */
    public static String decrypt(String content, String password) throws Exception {

        // 实例化
        Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

        // 使用密钥初始化,设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));

        // 执行操作
        byte[] result = cipher.doFinal(Base64.getDecoder().decode(content));

        // 字符集可设为形参
        return new String(result, "utf-8");
    }

    /**
     * 生成加密秘钥
     * 
     * @param password
     *            加密密码
     * @return
     * @throws NoSuchAlgorithmException
     */
    private static SecretKeySpec getSecretKey(final String password) throws NoSuchAlgorithmException {
        // 返回生成指定算法密钥生成器的 KeyGenerator 对象
        KeyGenerator kg = null;

        kg = KeyGenerator.getInstance(KEY_ALGORITHM);

        // AES 要求密钥长度为 128
        kg.init(128, new SecureRandom(password.getBytes()));

        // 生成一个密钥
        SecretKey secretKey = kg.generateKey();

        return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
    }

    public static void main(String[] args) throws Exception {
        String str = "待加密字符!!!";
        String pwd = "12345";

        System.out.println("加密前:" + str);

        String encryptStr = AESTest.encrypt(str, pwd);

        System.out.println("加密后:" + encryptStr);
        // 输出 加密后:AfY1Uuf9NzKBpl9nrvmMB0uZU4ID5bPJDpzJjhhu79I=

        String decryptStr = AESTest.decrypt(encryptStr, pwd);

        System.out.println("解密后:" + decryptStr);
        // 输出 解密后:待加密字符!!!

    }

}
Comments are closed.