Android AES加密工具类实现(基础回顾)
2016-06-30 22:21
609 查看
package com.powercreator.cms.util; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * @author vijoz * @version 创建时间:2016-6-30 */ public class AESUtils { public static final String TAG = "AESUtils"; public static String encrypt(String seed, String clearText) { // Log.d(TAG, "加密前的seed=" + seed + ",内容为:" + clearText); byte[] result = null; try { byte[] rawkey = getRawKey(seed.getBytes()); result = encrypt(rawkey, clearText.getBytes()); } catch (Exception e) { e.printStackTrace(); } String content = toHex(result); // Log.d(TAG, "加密后的内容为:" + content); return content; } public static String decrypt(String seed, String encrypted) { // Log.d(TAG, "解密前的seed=" + seed + ",内容为:" + encrypted); byte[] rawKey; try { rawKey = getRawKey(seed.getBytes()); byte[] enc = toByte(encrypted); byte[] result = decrypt(rawKey, enc); String coentn = new String(result); // Log.d(TAG, "解密后的内容为:" + coentn); return coentn; } catch (Exception e) { e.printStackTrace(); return null; } } private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(seed); kgen.init(128, sr); SecretKey sKey = kgen.generateKey(); byte[] raw = sKey.getEncoded(); return raw; } private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); // Cipher cipher = Cipher.getInstance("AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] encrypted = cipher.doFinal(clear); return encrypted; } private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); // Cipher cipher = Cipher.getInstance("AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; } public static String toHex(String txt) { return toHex(txt.getBytes()); } public static String fromHex(String hex) { return new String(toByte(hex)); } public static byte[] toByte(String hexString) { int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); return result; } public static String toHex(byte[] buf) { if (buf == null) return ""; StringBuffer result = new StringBuffer(2 * buf.length); for (int i = 0; i < buf.length; i++) { appendHex(result, buf[i]); } return result.toString(); } private static void appendHex(StringBuffer sb, byte b) { final String HEX = "0123456789ABCDEF"; sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); } }
上面的实现貌似有些问题,待调试!
下面是转发的另一个实现:
import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; public class AES { static final String algorithmStr = "AES/ECB/PKCS5Padding"; private static final Object TAG = "AES"; static private KeyGenerator keyGen; static private Cipher cipher; static boolean isInited = false; private static void init() { try { /**为指定算法生成一个 KeyGenerator 对象。 *此类提供(对称)密钥生成器的功能。 *密钥生成器是使用此类的某个 getInstance 类方法构造的。 *KeyGenerator 对象可重复使用,也就是说,在生成密钥后, *可以重复使用同一 KeyGenerator 对象来生成进一步的密钥。 *生成密钥的方式有两种:与算法无关的方式,以及特定于算法的方式。 *两者之间的惟一不同是对象的初始化: *与算法无关的初始化 *所有密钥生成器都具有密钥长度 和随机源 的概念。 *此 KeyGenerator 类中有一个 init 方法,它可采用这两个通用概念的参数。 *还有一个只带 keysize 参数的 init 方法, *它使用具有最高优先级的提供程序的 SecureRandom 实现作为随机源 *(如果安装的提供程序都不提供 SecureRandom 实现,则使用系统提供的随机源)。 *此 KeyGenerator 类还提供一个只带随机源参数的 inti 方法。 *因为调用上述与算法无关的 init 方法时未指定其他参数, *所以由提供程序决定如何处理将与每个密钥相关的特定于算法的参数(如果有)。 *特定于算法的初始化 *在已经存在特定于算法的参数集的情况下, *有两个具有 AlgorithmParameterSpec 参数的 init 方法。 *其中一个方法还有一个 SecureRandom 参数, *而另一个方法将已安装的高优先级提供程序的 SecureRandom 实现用作随机源 *(或者作为系统提供的随机源,如果安装的提供程序都不提供 SecureRandom 实现)。 *如果客户端没有显式地初始化 KeyGenerator(通过调用 init 方法), *每个提供程序必须提供(和记录)默认初始化。 */ keyGen = KeyGenerator.getInstance("AES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } // 初始化此密钥生成器,使其具有确定的密钥长度。 keyGen.init(128); //128位的AES加密 try { // 生成一个实现指定转换的 Cipher 对象。 cipher = Cipher.getInstance(algorithmStr); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } //标识已经初始化过了的字段 isInited = true; } private static byte[] genKey() { if (!isInited) { init(); } //首先 生成一个密钥(SecretKey), //然后,通过这个秘钥,返回基本编码格式的密钥,如果此密钥不支持编码,则返回 null。 return keyGen.generateKey().getEncoded(); } private static byte[] encrypt(byte[] content, byte[] keyBytes) { byte[] encryptedText = null; if (!isInited) { init(); } /** *类 SecretKeySpec *可以使用此类来根据一个字节数组构造一个 SecretKey, *而无须通过一个(基于 provider 的)SecretKeyFactory。 *此类仅对能表示为一个字节数组并且没有任何与之相关联的钥参数的原始密钥有用 *构造方法根据给定的字节数组构造一个密钥。 *此构造方法不检查给定的字节数组是否指定了一个算法的密钥。 */ Key key = new SecretKeySpec(keyBytes, "AES"); try { // 用密钥初始化此 cipher。 cipher.init(Cipher.ENCRYPT_MODE, key); } catch (InvalidKeyException e) { e.printStackTrace(); } try { //按单部分操作加密或解密数据,或者结束一个多部分操作。(不知道神马意思) encryptedText = cipher.doFinal(content); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return encryptedText; } private static byte[] encrypt(String content, String password) { try { byte[] keyStr = getKey(password); SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr 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 (InvalidKeyException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } private static byte[] decrypt(byte[] content, String password) { try { byte[] keyStr = getKey(password); SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr 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; } private static byte[] getKey(String password) { byte[] rByte = null; if (password!=null) { rByte = password.getBytes(); }else{ rByte = new byte[24]; } return rByte; } /** * 将二进制转换成16进制 * @param buf * @return */ 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进制转换为二进制 * @param hexStr * @return */ 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; } //注意: 这里的password(秘钥必须是16位的) private static final String keyBytes = "abcdefgabcdefg12"; /** *加密 */ public static String encode(String content){ //加密之后的字节数组,转成16进制的字符串形式输出 return parseByte2HexStr(encrypt(content, keyBytes)); } /** *解密 */ public static String decode(String content){ //解密之前,先将输入的字符串按照16进制转成二进制的字节数组,作为待解密的内容输入 byte[] b = decrypt(parseHexStr2Byte(content), keyBytes); return new String(b); } //测试用例 public static void test1(){ String content = "hello abcdefggsdfasdfasdf"; String pStr = encode(content ); System.out.println("加密前:"+content); System.out.println("加密后:" + pStr); String postStr = decode(pStr); System.out.println("解密后:"+ postStr ); } public static void main(String[] args) { test1(); } }
第三个,说实测兼容所有版本的:
import android.annotation.SuppressLint; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * * * Author:sunger */ public class AESUtils { public static String encrypt(String seed, String cleartext) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] result = encrypt(rawKey, cleartext.getBytes()); return toHex(result); } public static String decrypt(String seed, String encrypted) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] enc = toByte(encrypted); byte[] result = decrypt(rawKey, enc); return new String(result); } @SuppressLint("TrulyRandom") private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr.setSeed(seed); kgen.init(128, sr); // 192 and 256 bits may not be available SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] encrypted = cipher.doFinal(clear); return encrypted; } private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; } private static byte[] toByte(String hexString) { int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); return result; } private static String toHex(byte[] buf) { if (buf == null) return ""; StringBuffer result = new StringBuffer(2 * buf.length); for (int i = 0; i < buf.length; i++) { appendHex(result, buf[i]); } return result.toString(); } private final static String HEX = "0123456789ABCDEF"; private static void appendHex(StringBuffer sb, byte b) { sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); } }
相关连接:http://blog.csdn.net/xinzheng_wang/article/details/9159969
http://blog.csdn.net/randyjiawenjie/article/details/6587986
http://blog.csdn.net/wuchuanpingstone/article/details/6715196
相关文章推荐
- Android的消息机制Handler详解
- Android自定义饼状图,支持点击弹出扇形
- Android对敏感数据进行MD5加密(基础回顾)
- 用FragmentTabHost达到现在市面上的主流导航页面
- android基础—新建一个Activity
- android 二维码 扫描与生成(内置)
- Android 使用Mina的Nio实现客户端服务器通信
- 最新的Android版本和API Level的对应关系表
- Android进阶(二十三)Android开发过程之实例讲解
- Android进阶(二十三)Android开发过程之实例讲解
- 实现点击Button后弹出提示语
- 一个小白从零基础自学Android编程笔记之如何设置EidtText的边框
- How to integrate ZXing Library to Android Studio for Barcode Scanning?
- 在Activity中响应ListView内部按钮的点击事件的两种方法
- Android中的几种对话框(AlertDialog)
- Android开发进阶学习整理--Activity篇
- ViewPager实现页卡的最新方法--简洁的TabLayout(AndroidSupportDesign)
- 一个小白从零基础自学Android编程笔记之如何在AndroidManifext.xml文件中注册
- android 禁用和开启四大组件的方法(setComponentEnabledSetting )
- Android连续点击两次退出程序