JDK自带方法实现AES对称加密
请看代码。
1 package jdbc.pro.lin; 2 3 import java.security.InvalidAlgorithmParameterException; 4 import java.security.InvalidKeyException; 5 import java.security.NoSuchAlgorithmException; 6 7 import javax.crypto.BadPaddingException; 8 import javax.crypto.Cipher; 9 import javax.crypto.IllegalBlockSizeException; 10 import javax.crypto.KeyGenerator; 11 import javax.crypto.NoSuchPaddingException; 12 import javax.crypto.SecretKey; 13 import javax.crypto.spec.IvParameterSpec; 14 import javax.crypto.spec.SecretKeySpec; 15 16 import org.apache.commons.codec.binary.Base64; 17 18 public class MyAES { 19 /** 20 * 注意key和加密用到的字符串是不一样的 加密还要指定填充的加密模式和填充模式 AES密钥可以是128或者256,加密模式包括ECB, CBC等 21 * ECB模式是分组的模式,CBC是分块加密后,每块与前一块的加密结果异或后再加密 第一块加密的明文是与IV变量进行异或 22 */ 23 public static final String KEY_ALGORITHM = "AES"; 24 public static final String ECB_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; 25 public static final String CBC_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; 26 public static final String PLAIN_TEXT = "MANUTD is the greatest club in the world"; 27 28 /** 29 * IV(Initialization Value)是一个初始值,对于CBC模式来说,它必须是随机选取并且需要保密的 30 * 而且它的长度和密码分组相同(比如:对于AES 128为128位,即长度为16的byte类型数组) 31 * 32 */ 33 public static final byte[] IVPARAMETERS = new byte[] { 1, 2, 3, 4, 5, 6, 7, 34 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 35 36 public static void main(String[] arg) { 37 byte[] secretBytes = generateAESSecretKey(); 38 SecretKey key = restoreSecretKey(secretBytes); 39 byte[] encodedText = AesEcbEncode(PLAIN_TEXT.getBytes(), key); 40 41 System.out.println("AES ECB encoded with Base64: " + Base64.encodeBase64String(encodedText)); 42 System.out.println("AES ECB decoded: " 43 + AesEcbDecode(encodedText, key)); 44 45 46 47 encodedText = AesCbcEncode(PLAIN_TEXT.getBytes(), key, IVPARAMETERS); 48 49 50 System.out.println("AES CBC encoded with Base64: " + Base64.encodeBase64String(encodedText)); 51 System.out.println("AES CBC decoded: " 52 + AesCbcDecode(encodedText, key, 53 IVPARAMETERS)); 54 } 55 56 /** 57 * 使用ECB模式进行加密。 加密过程三步走: 1. 传入算法,实例化一个加解密器 2. 传入加密模式和密钥,初始化一个加密器 3. 58 * 调用doFinal方法加密 59 * 60 * @param plainText 61 * @return 62 */ 63 public static byte[] AesEcbEncode(byte[] plainText, SecretKey key) { 64 65 try { 66 67 Cipher cipher = Cipher.getInstance(ECB_CIPHER_ALGORITHM); 68 cipher.init(Cipher.ENCRYPT_MODE, key); 69 return cipher.doFinal(plainText); 70 } catch (NoSuchAlgorithmException | NoSuchPaddingException 71 | InvalidKeyException | IllegalBlockSizeException 72 | BadPaddingException e) { 73 // TODO Auto-generated catch block 74 e.printStackTrace(); 75 } 76 return null; 77 } 78 79 /** 80 * 使用ECB解密,三步走,不说了 81 * 82 * @param decodedText 83 * @param key 84 * @return 85 */ 86 public static String AesEcbDecode(byte[] decodedText, SecretKey key) { 87 try { 88 Cipher cipher = Cipher.getInstance(ECB_CIPHER_ALGORITHM); 89 cipher.init(Cipher.DECRYPT_MODE, key); 90 return new String(cipher.doFinal(decodedText)); 91 } catch (NoSuchAlgorithmException | NoSuchPaddingException 92 | InvalidKeyException | IllegalBlockSizeException 93 | BadPaddingException e) { 94 // TODO Auto-generated catch block 95 e.printStackTrace(); 96 } 97 return null; 98 99 } 100 101 /** 102 * CBC加密,三步走,只是在初始化时加了一个初始变量 103 * 104 * @param plainText 105 * @param key 106 * @param IVParameter 107 * @return 108 */ 109 public static byte[] AesCbcEncode(byte[] plainText, SecretKey key, 110 byte[] IVParameter) { 111 try { 112 IvParameterSpec ivParameterSpec = new IvParameterSpec(IVParameter); 113 114 Cipher cipher = Cipher.getInstance(CBC_CIPHER_ALGORITHM); 115 cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec); 116 return cipher.doFinal(plainText); 117 118 } catch (NoSuchAlgorithmException | NoSuchPaddingException 119 | InvalidKeyException | InvalidAlgorithmParameterException 120 | IllegalBlockSizeException | BadPaddingException e) { 121 // TODO Auto-generated catch block 122 e.printStackTrace(); 123 } 124 return null; 125 } 126 127 /** 128 * CBC 解密 129 * 130 * @param decodedText 131 * @param key 132 * @param IVParameter 133 * @return 134 */ 135 public static String AesCbcDecode(byte[] decodedText, SecretKey key, 136 byte[] IVParameter) { 137 IvParameterSpec ivParameterSpec = new IvParameterSpec(IVParameter); 138 139 try { 140 Cipher cipher = Cipher.getInstance(CBC_CIPHER_ALGORITHM); 141 cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec); 142 return new String(cipher.doFinal(decodedText)); 143 } catch (NoSuchAlgorithmException | NoSuchPaddingException 144 | InvalidKeyException | InvalidAlgorithmParameterException 145 | IllegalBlockSizeException | BadPaddingException e) { 146 // TODO Auto-generated catch block 147 e.printStackTrace(); 148 } 149 150 return null; 151 152 } 153 154 /** 155 * 1.创建一个KeyGenerator 2.调用KeyGenerator.generateKey方法 156 * 由于某些原因,这里只能是128,如果设置为256会报异常,原因在下面文字说明 157 * 158 * @return 159 */ 160 public static byte[] generateAESSecretKey() { 161 KeyGenerator keyGenerator; 162 try { 163 keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM); 164 // keyGenerator.init(256); 165 return keyGenerator.generateKey().getEncoded(); 166 } catch (NoSuchAlgorithmException e) { 167 // TODO Auto-generated catch block 168 e.printStackTrace(); 169 } 170 return null; 171 } 172 173 /** 174 * 还原密钥 175 * 176 * @param secretBytes 177 * @return 178 */ 179 public static SecretKey restoreSecretKey(byte[] secretBytes) { 180 SecretKey secretKey = new SecretKeySpec(secretBytes, KEY_ALGORITHM); 181 return secretKey; 182 } 183 }
因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。比如默认不允许256位密钥的AES加解密,解决方法就是修改策略文件。
官方网站提供了JCE无限制权限策略文件的下载:
JDK6的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
JDK7的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。
如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security下覆盖原来文件,记得先备份。
如果安装了JDK,将两个jar文件也放到%JDK_HOME%\jre\lib\security下。
JDK6的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
JDK7的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。
如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security下覆盖原来文件,记得先备份。
如果安装了JDK,将两个jar文件也放到%JDK_HOME%\jre\lib\security下。
PS:我也没试过,不行别找我。
KeyFactory最常用的操作就是通过密钥规范获得对应的密钥。像DES 3DES都是通过这样获得的,而AES只要一般的密钥规范就可以了,因此不需要KeyFactory.