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

org.slingerxv.limitart.util.SymmetricEncryptionUtil Maven / Gradle / Ivy

/*
 * Copyright (c) 2016-present The Limitart Project
 *
 * Licensed 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 org.slingerxv.limitart.util;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import io.netty.util.CharsetUtil;

/**
 * 对称加密验证工具
 * 
 * @author hank
 *
 */
public final class SymmetricEncryptionUtil {
	private static final String TRANSFORMATION = "AES/CBC/NoPadding";
	private static final String ALGORITHM = "AES";
	private Key generateKey;
	private byte[] iv;

	public synchronized static SymmetricEncryptionUtil getEncodeInstance(String password, String ivStr)
			throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
			InvalidAlgorithmParameterException {
		return new SymmetricEncryptionUtil(password, ivStr);
	}

	public synchronized static SymmetricEncryptionUtil getDecodeInstance(String password)
			throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
			InvalidAlgorithmParameterException {
		return new SymmetricEncryptionUtil(password);
	}

	/**
	 * 加密端构造函数
	 * 
	 * @param password
	 * @param ivStr
	 * @throws NoSuchPaddingException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidAlgorithmParameterException
	 * @throws InvalidKeyException
	 */
	private SymmetricEncryptionUtil(String password, String ivStr) throws NoSuchAlgorithmException,
			NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
		byte[] bytes = password.getBytes(CharsetUtil.UTF_8);
		byte[] resultKey = new byte[0X10];
		System.arraycopy(bytes, 0, resultKey, 0, Math.min(resultKey.length, bytes.length));
		generateKey = new SecretKeySpec(resultKey, ALGORITHM);
		if (ivStr != null) {
			// 初始化16位向量
			this.iv = new byte[0X10];
			byte[] ivRaw = ivStr.getBytes(CharsetUtil.UTF_8);
			System.arraycopy(ivRaw, 0, this.iv, 0, Math.min(this.iv.length, ivRaw.length));
		}
	}

	/**
	 * 解密端构造函数
	 * 
	 * @param password
	 * @throws NoSuchPaddingException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidAlgorithmParameterException
	 * @throws InvalidKeyException
	 */
	private SymmetricEncryptionUtil(String password) throws NoSuchAlgorithmException, NoSuchPaddingException,
			InvalidKeyException, InvalidAlgorithmParameterException {
		this(password, null);
	}

	public String encode(byte[] bytes) throws Exception {
		// 加密验证
		int zeroFlag = 0;
		byte[] jsonByteFillZero = null;
		int len = bytes.length;
		if ((len & 0XF) != 0) {
			len = ((len >> 4) + 1) << 4;
			zeroFlag = len - bytes.length;
			jsonByteFillZero = new byte[len];
			System.arraycopy(bytes, 0, jsonByteFillZero, 0, bytes.length);
		} else {
			jsonByteFillZero = bytes;
		}
		byte[] doFinal = null;
		Cipher cipher = Cipher.getInstance(TRANSFORMATION);
		cipher.init(Cipher.ENCRYPT_MODE, generateKey, new IvParameterSpec(this.iv));
		doFinal = cipher.doFinal(jsonByteFillZero);
		byte[] content = new byte[doFinal.length + this.iv.length];
		System.arraycopy(this.iv, 0, content, 0, this.iv.length);
		System.arraycopy(doFinal, 0, content, this.iv.length, doFinal.length);
		byte[] base64Encode = SecurityUtil.base64Encode(content);
		String b64Str = new String(base64Encode, CharsetUtil.UTF_8);
		String result = b64Str.replace('+', '-').replace('/', '_').replace('=', '.');
		if (zeroFlag > 0) {
			result = "$" + String.format("%02d", zeroFlag) + result;
		}
		return result;
	}

	public String encode(String source) throws Exception {
		return encode(source.getBytes(CharsetUtil.UTF_8));
	}

	public String decode(String source) throws Exception {
		String tokenSource = source;
		int zeroFlag = 0;
		if (tokenSource.startsWith("$")) {
			zeroFlag = Integer.parseInt(tokenSource.substring(1, 3));
			tokenSource = tokenSource.substring(3);
		}
		String token = tokenSource.replace('-', '+').replace('_', '/').replace('.', '=');
		byte[] base64Decode = SecurityUtil.base64Decode(token.getBytes(CharsetUtil.UTF_8));
		byte[] iv = new byte[0X10];
		byte[] content = new byte[base64Decode.length - iv.length];
		System.arraycopy(base64Decode, 0, iv, 0, iv.length);
		System.arraycopy(base64Decode, iv.length, content, 0, content.length);
		Cipher cipher = Cipher.getInstance(TRANSFORMATION);
		cipher.init(Cipher.DECRYPT_MODE, generateKey, new IvParameterSpec(iv));
		byte[] doFinal = cipher.doFinal(content);
		// 去补零
		int realSize = doFinal.length;
		if (zeroFlag > 0) {
			realSize = doFinal.length - zeroFlag;
			byte[] afterZero = new byte[realSize];
			System.arraycopy(doFinal, 0, afterZero, 0, afterZero.length);
			return new String(afterZero, CharsetUtil.UTF_8);
		} else {
			return new String(doFinal, CharsetUtil.UTF_8);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy