All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.joekerouac.common.tools.util.Aes Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package com.github.joekerouac.common.tools.util;

import java.security.SecureRandom;
import java.util.function.Function;

import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import com.github.joekerouac.common.tools.constant.ExceptionProviderConst;
import com.github.joekerouac.common.tools.crypto.CipherSpi;
import com.github.joekerouac.common.tools.crypto.constant.CipherDesc;

/**
 * AES加解密封装,注意,如果选择的算法没有padding,需要自己对齐数据,数据长度需要是{@link CipherSpi#getBlockSize()}的整数倍;
 * 
 * @since 1.0.0
 * @author JoeKerouac
 * @date 2022-10-14 14:37:00
 */
public class Aes {

    private final ObjectPool encryptCipherPool;

    private final ObjectPool decryptCipherPool;

    /**
     * 默认构造器
     *
     * @param key
     *            key
     * @param iv
     *            iv
     * @param desc
     *            要采用的算法说明
     */
    public Aes(byte[] key, byte[] iv, CipherDesc desc) {
        this(key, iv, desc, 30, 5);
    }

    /**
     * 默认构造器
     * 
     * @param key
     *            key
     * @param iv
     *            iv
     * @param desc
     *            要采用的算法说明
     * @param maxIdle
     *            加解密最大并发数量(例如设置为10,则加密和解密各自最大并发都是10)
     * @param minIdle
     *            加解密最小并发
     */
    public Aes(byte[] key, byte[] iv, CipherDesc desc, int maxIdle, int minIdle) {
        Assert.argNotNull(key, "key");
        Assert.argNotNull(iv, "iv");
        Assert.argNotNull(desc, "desc");
        Assert.assertTrue(desc.getKeySize() == key.length, "key格式不对",
            ExceptionProviderConst.IllegalArgumentExceptionProvider);
        Assert.assertTrue(desc.getIvLen() == iv.length, "iv格式不对",
            ExceptionProviderConst.IllegalArgumentExceptionProvider);
        Assert.assertTrue(!desc.isGcm(), "gcm模式每次加密完需要重新初始化,并且变更iv,无法使用本工具",
            ExceptionProviderConst.IllegalArgumentExceptionProvider);

        GenericObjectPoolConfig config = new GenericObjectPoolConfig<>();
        config.setMaxIdle(maxIdle);
        config.setMaxTotal(maxIdle);
        config.setMinIdle(minIdle);

        this.encryptCipherPool = new GenericObjectPool<>(new PooledObjectFactory() {

            @Override
            public PooledObject makeObject() throws Exception {
                CipherSpi cipherSpi = CipherSpi.getInstance(desc);
                cipherSpi.init(key, iv, CipherSpi.ENCRYPT_MODE);
                return new DefaultPooledObject<>(cipherSpi);
            }

            @Override
            public void destroyObject(final PooledObject p) throws Exception {

            }

            @Override
            public boolean validateObject(final PooledObject p) {
                return true;
            }

            @Override
            public void activateObject(final PooledObject p) throws Exception {

            }

            @Override
            public void passivateObject(final PooledObject p) throws Exception {

            }
        }, config);

        this.decryptCipherPool = new GenericObjectPool<>(new PooledObjectFactory() {

            @Override
            public PooledObject makeObject() throws Exception {
                CipherSpi cipherSpi = CipherSpi.getInstance(desc);
                cipherSpi.init(key, iv, CipherSpi.DECRYPT_MODE);
                return new DefaultPooledObject<>(cipherSpi);
            }

            @Override
            public void destroyObject(final PooledObject p) throws Exception {

            }

            @Override
            public boolean validateObject(final PooledObject p) {
                return true;
            }

            @Override
            public void activateObject(final PooledObject p) throws Exception {

            }

            @Override
            public void passivateObject(final PooledObject p) throws Exception {

            }
        }, config);
    }

    /**
     * 随机生成一个指定算法的key
     * 
     * @param desc
     *            算法说明
     * @return 随机key
     */
    public static byte[] generateKey(CipherDesc desc) {
        byte[] key = new byte[desc.getKeySize()];
        new SecureRandom().nextBytes(key);
        return key;
    }

    /**
     * 随机生成一个指定算法的iv
     * 
     * @param desc
     *            算法说明
     * @return iv
     */
    public static byte[] generateIv(CipherDesc desc) {
        if (desc.getIvLen() == 0) {
            return new byte[0];
        }

        byte[] iv = new byte[desc.getIvLen()];
        new SecureRandom().nextBytes(iv);
        return iv;
    }

    /**
     * 加密数据
     * 
     * @param data
     *            要加密的数据
     * @return 加密结果
     */
    public byte[] encrypt(byte[] data) {
        return runWithCipher(encryptCipherPool, cipherSpi -> cipherSpi.doFinal(data));
    }

    /**
     * 解密
     * 
     * @param data
     *            要解密的数据
     * @return 解密结果
     */
    public byte[] decrypt(byte[] data) {
        return runWithCipher(decryptCipherPool, cipherSpi -> cipherSpi.doFinal(data));
    }

    /**
     * 使用指定cipher pool提供的cipher运行函数
     * 
     * @param cipherPool
     *            cipher pool
     * @param function
     *            函数
     * @return 结果
     */
    private byte[] runWithCipher(ObjectPool cipherPool, Function function) {
        CipherSpi cipherSpi = null;
        try {
            cipherSpi = cipherPool.borrowObject();
            try {
                return function.apply(cipherSpi);
            } finally {
                cipherPool.returnObject(cipherSpi);
            }
        } catch (Throwable throwable) {
            throw new RuntimeException("加解密过程中发生异常", throwable);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy