zoukankan      html  css  js  c++  java
  • java对称加密(AES)

    Java代码 复制代码 收藏代码
    1. /**  
    2.  * AESHelper.java  
    3.  * cn.com.songjy.test  
    4.  *  
    5.  * Function: TODO   
    6.  *  
    7.  *   ver     date           author  
    8.  * ──────────────────────────────────  
    9.  *           2012-6-29      songjianyong  
    10.  *  
    11.  * Copyright (c) 2012, TNT All Rights Reserved.  
    12. */  
    13.   
    14. package cn.com.songjy.test;   
    15.   
    16. import java.io.UnsupportedEncodingException;   
    17. import java.security.InvalidKeyException;   
    18. import java.security.NoSuchAlgorithmException;   
    19. import java.security.SecureRandom;   
    20.   
    21. import javax.crypto.BadPaddingException;   
    22. import javax.crypto.Cipher;   
    23. import javax.crypto.IllegalBlockSizeException;   
    24. import javax.crypto.KeyGenerator;   
    25. import javax.crypto.NoSuchPaddingException;   
    26. import javax.crypto.SecretKey;   
    27. import javax.crypto.spec.SecretKeySpec;   
    28.   
    29. /**  
    30.  * ClassName:AESHelper  
    31.  *  
    32.  * @author   songjianyong  
    33.  * @version  1.0  
    34.  * @since    v1.0  
    35.  * @Date     2012-6-29 下午2:06:07   
    36.  */  
    37. public class AESHelper {   
    38.   
    39.     /**  
    40.      * @method main  
    41.      * @param args  
    42.      * @throws   
    43.      * @since v1.0  
    44.      */  
    45.   
    46.     public static void main(String[] args) {   
    47.   
    48.         String content = "宋建勇";   
    49.         String password = "12345678";   
    50.         byte[] encryptResult = encrypt(content, password);//加密   
    51.         byte[] decryptResult = decrypt(encryptResult,password);//解密   
    52.         System.out.println("解密后:" + new String(decryptResult));   
    53.            
    54.         /*容易出错的地方,请看下面代码*/  
    55.         System.out.println("***********************************************");   
    56.         try {   
    57.             String encryptResultStr = new String(encryptResult,"utf-8");   
    58.             decryptResult = decrypt(encryptResultStr.getBytes("utf-8"),password);   
    59.             System.out.println("解密后:" + new String(decryptResult));   
    60.         } catch (UnsupportedEncodingException e) {   
    61.             e.printStackTrace();   
    62.         } catch (Exception e) {   
    63.             // TODO: handle exception   
    64.         }   
    65.         /*则,系统会报出如下异常:javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher  
    66.     at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)  
    67.     at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)  
    68.     at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)  
    69.     at javax.crypto.Cipher.doFinal(DashoA13*..)  
    70.     at cn.com.songjy.test.ASCHelper.decrypt(ASCHelper.java:131)  
    71.     at cn.com.songjy.test.ASCHelper.main(ASCHelper.java:58)  
    72.          * */  
    73.         /*这主要是因为加密后的byte数组是不能强制转换成字符串的, 换言之,字符串和byte数组在这种情况下不是互逆的,  
    74.          * 要避免这种情况,我们需要做一些修订,可以考虑将二进制数据转换成十六进制表示,  
    75.          * 主要有两个方法:将二进制转换成16进制(见方法parseByte2HexStr)或是将16进制转换为二进制(见方法parseHexStr2Byte)*/  
    76.            
    77.         /*然后,我们再修订以上测试代码*/  
    78.         System.out.println("***********************************************");   
    79.         String encryptResultStr = parseByte2HexStr(encryptResult);   
    80.         System.out.println("加密后:" + encryptResultStr);   
    81.         byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);   
    82.         decryptResult = decrypt(decryptFrom,password);//解码   
    83.         System.out.println("解密后:" + new String(decryptResult));   
    84.     }   
    85.   
    86.     /**  
    87.      * 加密  
    88.      * @method encrypt  
    89.      * @param content   需要加密的内容  
    90.      * @param password  加密密码  
    91.      * @return  
    92.      * @throws   
    93.      * @since v1.0  
    94.      */  
    95.     public static byte[] encrypt(String content, String password){   
    96.         try {   
    97.             KeyGenerator kgen = KeyGenerator.getInstance("AES");   
    98.             kgen.init(128, new SecureRandom(password.getBytes()));   
    99.             SecretKey secretKey = kgen.generateKey();   
    100.             byte[] enCodeFormat = secretKey.getEncoded();   
    101.             SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");   
    102.             Cipher cipher = Cipher.getInstance("AES");// 创建密码器   
    103.             byte[] byteContent = content.getBytes("utf-8");   
    104.             cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化   
    105.             byte[] result = cipher.doFinal(byteContent);   
    106.             return result; // 加密   
    107.         } catch (NoSuchAlgorithmException e) {   
    108.             e.printStackTrace();   
    109.         }catch (NoSuchPaddingException e) {   
    110.             e.printStackTrace();   
    111.         }catch (UnsupportedEncodingException e) {   
    112.             e.printStackTrace();   
    113.         }catch (InvalidKeyException e) {   
    114.             e.printStackTrace();   
    115.         }catch (IllegalBlockSizeException e) {   
    116.             e.printStackTrace();   
    117.         }catch (BadPaddingException e) {   
    118.             e.printStackTrace();   
    119.         }   
    120.         return null;   
    121.     }   
    122.        
    123.     /**  
    124.      * 解密  
    125.      * @method decrypt  
    126.      * @param content   待解密内容  
    127.      * @param password  解密密钥  
    128.      * @return  
    129.      * @throws   
    130.      * @since v1.0  
    131.      */  
    132.     public static byte[] decrypt(byte[] content, String password){   
    133.         try {   
    134.             KeyGenerator kgen = KeyGenerator.getInstance("AES");   
    135.             kgen.init(128, new SecureRandom(password.getBytes()));   
    136.             SecretKey secretKey = kgen.generateKey();   
    137.             byte[] enCodeFormat = secretKey.getEncoded();   
    138.             SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");   
    139.             Cipher cipher = Cipher.getInstance("AES");// 创建密码器   
    140.             cipher.init(Cipher.DECRYPT_MODE, key);// 初始化   
    141.             byte[] result = cipher.doFinal(content);   
    142.             return result; // 解密   
    143.         } catch (NoSuchAlgorithmException e) {   
    144.             e.printStackTrace();   
    145.         }catch (NoSuchPaddingException e) {   
    146.             e.printStackTrace();   
    147.         }catch (InvalidKeyException e) {   
    148.             e.printStackTrace();   
    149.         }catch (IllegalBlockSizeException e) {   
    150.             e.printStackTrace();   
    151.         }catch (BadPaddingException e) {   
    152.             e.printStackTrace();   
    153.         }   
    154.            
    155.         return null;   
    156.     }   
    157.        
    158.     /**  
    159.      * 将二进制转换成16进制  
    160.      * @method parseByte2HexStr  
    161.      * @param buf  
    162.      * @return  
    163.      * @throws   
    164.      * @since v1.0  
    165.      */  
    166.     public static String parseByte2HexStr(byte buf[]){   
    167.         StringBuffer sb = new StringBuffer();   
    168.         for(int i = 0; i < buf.length; i++){   
    169.             String hex = Integer.toHexString(buf[i] & 0xFF);   
    170.             if (hex.length() == 1) {   
    171.                 hex = '0' + hex;   
    172.             }   
    173.             sb.append(hex.toUpperCase());   
    174.         }   
    175.         return sb.toString();   
    176.     }   
    177.        
    178.     /**  
    179.      * 将16进制转换为二进制  
    180.      * @method parseHexStr2Byte  
    181.      * @param hexStr  
    182.      * @return  
    183.      * @throws   
    184.      * @since v1.0  
    185.      */  
    186.     public static byte[] parseHexStr2Byte(String hexStr){   
    187.         if(hexStr.length() < 1)   
    188.             return null;   
    189.         byte[] result = new byte[hexStr.length()/2];   
    190.         for (int i = 0;i< hexStr.length()/2; i++) {   
    191.             int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);   
    192.             int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);   
    193.             result[i] = (byte) (high * 16 + low);   
    194.         }   
    195.         return result;   
    196.     }   
    197.        
    198.     /**  
    199.      * 另外一种加密方式--这种加密方式有两种限制  
    200.      * 1、密钥必须是16位的  
    201.      * 2、待加密内容的长度必须是16的倍数,如果不是16的倍数,就会出如下异常  
    202.      * javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes  
    203.         at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)  
    204.         at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)  
    205.         at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)  
    206.         at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)  
    207.         at javax.crypto.Cipher.doFinal(DashoA13*..)  
    208.         要解决如上异常,可以通过补全传入加密内容等方式进行避免。  
    209.      * @method encrypt2  
    210.      * @param content   需要加密的内容  
    211.      * @param password  加密密码  
    212.      * @return  
    213.      * @throws   
    214.      * @since v1.0  
    215.      */  
    216.     public static byte[] encrypt2(String content, String password){   
    217.         try {   
    218.             SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");   
    219.             Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");   
    220.             byte[] byteContent = content.getBytes("utf-8");   
    221.             cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化   
    222.             byte[] result = cipher.doFinal(byteContent);   
    223.             return result; // 加密   
    224.         } catch (NoSuchAlgorithmException e) {   
    225.             e.printStackTrace();   
    226.         } catch (NoSuchPaddingException e) {   
    227.             e.printStackTrace();   
    228.         } catch (UnsupportedEncodingException e) {   
    229.             e.printStackTrace();   
    230.         } catch (InvalidKeyException e) {   
    231.             e.printStackTrace();   
    232.         } catch (IllegalBlockSizeException e) {   
    233.             e.printStackTrace();   
    234.         } catch (BadPaddingException e) {   
    235.             e.printStackTrace();   
    236.         }   
    237.         return null;   
    238.     }   
    239.        
    240.        
    241. }  
    /**
     * AESHelper.java
     * cn.com.songjy.test
     *
     * Function: TODO 
     *
     *   ver     date      		author
     * ──────────────────────────────────
     *   		 2012-6-29 		songjianyong
     *
     * Copyright (c) 2012, TNT All Rights Reserved.
    */
    
    package cn.com.songjy.test;
    
    import java.io.UnsupportedEncodingException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.KeyGenerator;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    /**
     * ClassName:AESHelper
     *
     * @author   songjianyong
     * @version  1.0
     * @since    v1.0
     * @Date	 2012-6-29 下午2:06:07 
     */
    public class AESHelper {
    
    	/**
    	 * @method main
    	 * @param args
    	 * @throws 
    	 * @since v1.0
    	 */
    
    	public static void main(String[] args) {
    
    		String content = "宋建勇";
    		String password = "12345678";
    		byte[] encryptResult = encrypt(content, password);//加密
    		byte[] decryptResult = decrypt(encryptResult,password);//解密
    		System.out.println("解密后:" + new String(decryptResult));
    		
    		/*容易出错的地方,请看下面代码*/
    		System.out.println("***********************************************");
    		try {
    			String encryptResultStr = new String(encryptResult,"utf-8");
    			decryptResult = decrypt(encryptResultStr.getBytes("utf-8"),password);
    			System.out.println("解密后:" + new String(decryptResult));
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		} catch (Exception e) {
    			// TODO: handle exception
    		}
    		/*则,系统会报出如下异常:javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    	at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    	at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    	at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
    	at javax.crypto.Cipher.doFinal(DashoA13*..)
    	at cn.com.songjy.test.ASCHelper.decrypt(ASCHelper.java:131)
    	at cn.com.songjy.test.ASCHelper.main(ASCHelper.java:58)
    		 * */
    		/*这主要是因为加密后的byte数组是不能强制转换成字符串的, 换言之,字符串和byte数组在这种情况下不是互逆的,
    		 * 要避免这种情况,我们需要做一些修订,可以考虑将二进制数据转换成十六进制表示,
    		 * 主要有两个方法:将二进制转换成16进制(见方法parseByte2HexStr)或是将16进制转换为二进制(见方法parseHexStr2Byte)*/
    		
    		/*然后,我们再修订以上测试代码*/
    		System.out.println("***********************************************");
    		String encryptResultStr = parseByte2HexStr(encryptResult);
    		System.out.println("加密后:" + encryptResultStr);
    		byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);
    		decryptResult = decrypt(decryptFrom,password);//解码
    		System.out.println("解密后:" + new String(decryptResult));
    	}
    
    	/**
    	 * 加密
    	 * @method encrypt
    	 * @param content	需要加密的内容
    	 * @param password	加密密码
    	 * @return
    	 * @throws 
    	 * @since v1.0
    	 */
    	public static byte[] encrypt(String content, String password){
    		try {
    			KeyGenerator kgen = KeyGenerator.getInstance("AES");
    			kgen.init(128, new SecureRandom(password.getBytes()));
    			SecretKey secretKey = kgen.generateKey();
    			byte[] enCodeFormat = secretKey.getEncoded();
    			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
    			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
    			byte[] byteContent = content.getBytes("utf-8");
    			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
    			byte[] result = cipher.doFinal(byteContent);
    			return result; // 加密
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		}catch (NoSuchPaddingException e) {
    			e.printStackTrace();
    		}catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}catch (InvalidKeyException e) {
    			e.printStackTrace();
    		}catch (IllegalBlockSizeException e) {
    			e.printStackTrace();
    		}catch (BadPaddingException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    	
    	/**
    	 * 解密
    	 * @method decrypt
    	 * @param content	待解密内容
    	 * @param password	解密密钥
    	 * @return
    	 * @throws 
    	 * @since v1.0
    	 */
    	public static byte[] decrypt(byte[] content, String password){
    		try {
    			KeyGenerator kgen = KeyGenerator.getInstance("AES");
    			kgen.init(128, new SecureRandom(password.getBytes()));
    			SecretKey secretKey = kgen.generateKey();
    			byte[] enCodeFormat = secretKey.getEncoded();
    			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
    			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
    			cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
    			byte[] result = cipher.doFinal(content);
    			return result; // 解密
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		}catch (NoSuchPaddingException e) {
    			e.printStackTrace();
    		}catch (InvalidKeyException e) {
    			e.printStackTrace();
    		}catch (IllegalBlockSizeException e) {
    			e.printStackTrace();
    		}catch (BadPaddingException e) {
    			e.printStackTrace();
    		}
    		
    		return null;
    	}
    	
    	/**
    	 * 将二进制转换成16进制
    	 * @method parseByte2HexStr
    	 * @param buf
    	 * @return
    	 * @throws 
    	 * @since v1.0
    	 */
    	public static String parseByte2HexStr(byte buf[]){
    		StringBuffer sb = new StringBuffer();
    		for(int i = 0; i < buf.length; i++){
    			String hex = Integer.toHexString(buf[i] & 0xFF);
    			if (hex.length() == 1) {
    				hex = '0' + hex;
    			}
    			sb.append(hex.toUpperCase());
    		}
    		return sb.toString();
    	}
    	
    	/**
    	 * 将16进制转换为二进制
    	 * @method parseHexStr2Byte
    	 * @param hexStr
    	 * @return
    	 * @throws 
    	 * @since v1.0
    	 */
    	public static byte[] parseHexStr2Byte(String hexStr){
    		if(hexStr.length() < 1)
    			return null;
    		byte[] result = new byte[hexStr.length()/2];
    		for (int i = 0;i< hexStr.length()/2; i++) {
    			int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
    			int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
    			result[i] = (byte) (high * 16 + low);
    		}
    		return result;
    	}
    	
    	/**
    	 * 另外一种加密方式--这种加密方式有两种限制
    	 * 1、密钥必须是16位的
    	 * 2、待加密内容的长度必须是16的倍数,如果不是16的倍数,就会出如下异常
    	 * javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
            at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)
            at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
            at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
            at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
            at javax.crypto.Cipher.doFinal(DashoA13*..)
    		要解决如上异常,可以通过补全传入加密内容等方式进行避免。
    	 * @method encrypt2
    	 * @param content	需要加密的内容
    	 * @param password	加密密码
    	 * @return
    	 * @throws 
    	 * @since v1.0
    	 */
    	public static byte[] encrypt2(String content, String password){
    		try {
    			SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
    			Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
    			byte[] byteContent = content.getBytes("utf-8");
    			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
    			byte[] result = cipher.doFinal(byteContent);
    			return result; // 加密
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		} catch (NoSuchPaddingException e) {
    			e.printStackTrace();
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		} catch (InvalidKeyException e) {
    			e.printStackTrace();
    		} catch (IllegalBlockSizeException e) {
    			e.printStackTrace();
    		} catch (BadPaddingException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    	
    	
    }
    
    



    测试效果:

    解密后:宋建勇
    ***********************************************
    javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)
    at cn.com.songjy.test.ASCHelper.decrypt(ASCHelper.java:141)
    at cn.com.songjy.test.ASCHelper.main(ASCHelper.java:58)
    java.lang.NullPointerException
    at java.lang.String.<init>(String.java:594)
    at cn.com.songjy.test.ASCHelper.main(ASCHelper.java:59)
    ***********************************************
    加密后:961000B09BDDA1F81E81EF3EFDC3A926
    解密后:宋建勇

  • 相关阅读:
    JAVA中对null进行强制类型转换
    git 初次push
    svn还原与本地版本回退
    后台用map接收数据,报类型转换错误
    eclipse从svn导入静态文件
    APP项目下载及运行
    Yii2中如何使用CodeCeption
    开发资源整合
    工作流设计参考(包括PHP实现)
    PHP单元测试利器:PHPUNIT初探
  • 原文地址:https://www.cnblogs.com/firstdream/p/5478393.html
Copyright © 2011-2022 走看看