AES apache commons-crypto 对称加密
apache实现的AES256加密
官方用户指导链接:http://commons.apache.org/proper/commons-crypto/userguide.html
官方字节缓存实现的例子链接:http://commons.apache.org/proper/commons-crypto/xref-test/org/apache/commons/crypto/examples/CipherByteBufferExample.html
其实官方给了两种实现,另外一种是字节数组方式,如果加密的字符串过长,官方例子中的new的字节数组会异常,不如字节缓存方式更好。这里说下字节缓存的实现。
官方例子的main方法是加密和解密一起处理的,不实际;我将官方例子中的main方法里的逻辑拆出来了加密和解密两个方法(注:@slf4j需要用到lombok,如果你没有引入,则把该注解去掉,修改代码中的log)
package com.dmy.util; import lombok.extern.slf4j.Slf4j; import org.apache.commons.crypto.cipher.CryptoCipher; import org.apache.commons.crypto.utils.Utils; import org.springframework.util.Base64Utils; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.ShortBufferException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.util.Properties; /** * Example showing the CryptoCipher API using a ByteBuffer */ @Slf4j public class CipherByteBufferExample { //32字节长度的秘钥,也就是256位 static final SecretKeySpec key = new SecretKeySpec(getUTF8Bytes("12345678901234561234567890123456"), "AES"); //固定16字节长度 static final IvParameterSpec iv = new IvParameterSpec(getUTF8Bytes("1234567890123456")); //加密方法/加密模式/填充方式,CBC是安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准 static final String transform = "AES/CBC/PKCS5Padding"; /** * Converts String to UTF8 bytes * * @param input the input string * @return UTF8 bytes */ private static byte[] getUTF8Bytes(String input) { return input.getBytes(StandardCharsets.UTF_8); } /** * Converts ByteBuffer to String * * @param buffer input byte buffer * @return the converted string */ private static String asString(ByteBuffer buffer) { final ByteBuffer copy = buffer.duplicate(); final byte[] bytes = new byte[copy.remaining()]; copy.get(bytes); return new String(bytes, StandardCharsets.UTF_8); } /** * 加密 * @param text 需要加密的明文 * @return 经过base64加密后的密文 * @throws IOException * @throws InvalidAlgorithmParameterException * @throws InvalidKeyException * @throws ShortBufferException * @throws BadPaddingException * @throws IllegalBlockSizeException */ public static String encrypt(String text) throws IOException, InvalidAlgorithmParameterException, InvalidKeyException, ShortBufferException, BadPaddingException, IllegalBlockSizeException { Properties properties = new Properties(); final ByteBuffer outBuffer; final int bufferSize = 1024; final int updateBytes; final int finalBytes; //Creates a CryptoCipher instance with the transformation and properties. try (CryptoCipher encipher = Utils.getCipherInstance(transform, properties)) { ByteBuffer inBuffer = ByteBuffer.allocateDirect(bufferSize); outBuffer = ByteBuffer.allocateDirect(bufferSize); inBuffer.put(getUTF8Bytes(text)); inBuffer.flip(); // ready for the cipher to read it // Show the data is there log.debug("inBuffer={}", asString(inBuffer)); // Initializes the cipher with ENCRYPT_MODE,key and iv. encipher.init(Cipher.ENCRYPT_MODE, key, iv); // Continues a multiple-part encryption/decryption operation for byte buffer. updateBytes = encipher.update(inBuffer, outBuffer); log.debug("updateBytes={}", updateBytes); // We should call do final at the end of encryption/decryption. finalBytes = encipher.doFinal(inBuffer, outBuffer); log.debug("finalBytes={}", finalBytes); } outBuffer.flip(); // ready for use as decrypt byte[] encoded = new byte[updateBytes + finalBytes]; outBuffer.duplicate().get(encoded); String encodedString = Base64Utils.encodeToString(encoded); log.debug("encodedString={}", encodedString); return encodedString; } /** * 解密 * @param encodedString 经过base64加密后的密文 * @return 明文 * @throws IOException * @throws InvalidAlgorithmParameterException * @throws InvalidKeyException * @throws ShortBufferException * @throws BadPaddingException * @throws IllegalBlockSizeException */ public static String dencrypt(String encodedString) throws IOException, InvalidAlgorithmParameterException, InvalidKeyException, ShortBufferException, BadPaddingException, IllegalBlockSizeException { Properties properties = new Properties(); final ByteBuffer outBuffer; final int bufferSize = 1024; ByteBuffer decoded = ByteBuffer.allocateDirect(bufferSize); //Creates a CryptoCipher instance with the transformation and properties. try (CryptoCipher decipher = Utils.getCipherInstance(transform, properties)) { decipher.init(Cipher.DECRYPT_MODE, key, iv); outBuffer = ByteBuffer.allocateDirect(bufferSize); outBuffer.put(Base64Utils.decode(getUTF8Bytes(encodedString))); outBuffer.flip(); decipher.update(outBuffer, decoded); decipher.doFinal(outBuffer, decoded); decoded.flip(); // ready for use log.debug("decoded={}", asString(decoded)); } return asString(decoded); } }