1. AES加密,相对比较简单,之前已经配置好工具类。
package com.bbguoxue.poetry.util; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; /** * AES加密器 * @author Eric_Ni * */ public class AESEncryptor { /** * AES加密 */ public static String encrypt(String seed, String cleartext) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] result = encrypt(rawKey, cleartext.getBytes()); return toHex(result); } /** * AES解密 */ 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); } 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); 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); 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 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)); } }
这里要注意的是红色行,在android4.X的时候可能出席问题。很多地方都是写SecureRandow.getInstance("SHA1PRNG")
2. 使用DES加密
//这个现在有点怕了,也还半知半解
private static final String DES_EDE = "DESede/ECB/NoPadding"; //定义 加密算法,可用 DES,DESede,Blowfish //keybyte为加密密钥,长度为24字节 //src为被加密的数据缓冲区(源)
private static final String DES_EDE_CBC = "DESede/CBC/NoPadding"; //定义 加密算法,可用 DES,DESede,Blowfish //keybyte为加密密钥,长度为24字节 //src为被加密的数据缓冲区(源)
private static final String DES_CBC = "DES/CBC/NoPadding";
private static final String DES_ECB = "DES/ECB/PKCS5Padding";
// 还有"DES/CBC/PKCS5Padding"------------android常用
加密说明: 算法/工作模式/填充
主要涉及的几个问题:工作模式(如上:DES,DESede ...)、填充模式(PKCS5Padding, PKCS7Padding)、初始化向量(如下IvParameterSpec 这个东西容易出问题,注意很多地方初始化0000000,和12345678,这个东西只要有一位不同得到的结果肯定不同)
这几个变量如果你不指定的话,那么就要程序就要调用默认实现,java,android,iso。默认得到的结果肯定不同。
android可用模式,Ios去掉PKCS7Padding的方式得到的结果一样,能通用(Java中只能使用PKCS5Padding)
private static String encrypt(byte[] raw, byte[] clear) throws Exception { IvParameterSpec zeroIv = new IvParameterSpec(ivs); SecretKeySpec skeySpec = new SecretKeySpec(raw, "DES"); Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, zeroIv); byte[] encrypted = cipher.doFinal(clear); return toHex(encrypted); }
//走的弯路
1. 类似AES那样生成密钥key。
2. 使用DESkey
DESKeySpec dks = new DESKeySpec(raw); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); //key的长度不能够小于8位字节 Key secretKey = keyFactory.generateSecret(dks); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); IvParameterSpec iv = new IvParameterSpec(new byte[8]); AlgorithmParameterSpec paramSpec = iv; cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec); return cipher.doFinal(clear);
得到的结果总不对。可以和上面的比较一下,这个使用了DESKeySpec(这貌似用在ECB模式下),上面直接用的简单的SecretKeySpec。 本来也应该这样用的额,但互通性来说大家都简单的写了。
3. IvParameterSpec 这个类是很重要的, 这玩意是个初始化变量
很多地方可能使用示例new IvParamterSpec("12345678".getBytes()) ---------这其实在正常使用过程中常出现问题
很多都是用默认的{0,0,0,0,0,0,0,0}数组
我的整个代码
import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * AES加密器 * * @author Eric_Ni * */ public class AESEncryptor { public static void main(String[] args) { try { System.out.println(encryptDES("123456", "dfardfsf")); System.out.println(encrypt("dfardfsf", "123456")); System.out.println(decrypt("dfardfsf", "B8CF276AF590D8B9")); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * AES加密 */ public static String encrypt(String seed, String cleartext) throws Exception { return encrypt(seed.getBytes(), cleartext.getBytes()); } /** * AES解密 */ public static String decrypt(String seed, String encrypted) throws Exception { byte[] enc = toByte(encrypted); byte[] result = decrypt(seed, enc); return new String(result); } private static byte[] ivs = { 0, 0, 0, 0, 0, 0, 0, 0 }; public static String encryptDES(String encryptString, String encryptKey) throws Exception { IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]); SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "DES"); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv); byte[] encryptedData = cipher.doFinal(encryptString.getBytes()); return toHex(encryptedData); } private static String encrypt(byte[] raw, byte[] clear) throws Exception { IvParameterSpec zeroIv = new IvParameterSpec(ivs); SecretKeySpec skeySpec = new SecretKeySpec(raw, "DES"); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, zeroIv); byte[] encrypted = cipher.doFinal(clear); return toHex(encrypted); } private static byte[] decrypt(String raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw.getBytes(), "DES"); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); IvParameterSpec iv = new IvParameterSpec(ivs); cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); return cipher.doFinal(encrypted); } public static String toHex(String txt) { return toHex(txt.getBytes()); } public static String fromHex(String hex) { return new String(hex.getBytes()); } 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 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)); } }
JAVA中基本就只用这种了,如果需要使用其他的可以参考如下文章,未测试。
最后分享一下一位兄弟的总结,太多了没想去详细看
主要搞android,太复杂了还是用c做比较好点。不然容易被反编译
1.Base64 加密:org.apache.commons.codec.binary.Base64.encodeBase64(byte[] binaryData) 解密:org.apache.commons.codec.binary.Base64.decodeBase64(byte[] base64Data) 2.Md5 加密:org.apache.commons.codec.digest.md5Hex(byte[] data) 解密:无 3.DES(des-ecb,3des,des-cbc,cbc-mac) view plaincopy to clipboardprint? import java.io.ByteArrayOutputStream; import java.security.SecureRandom; import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.DESedeKeySpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.Mac; import org.bouncycastle.crypto.engines.DESEngine; import org.bouncycastle.crypto.macs.CBCBlockCipherMac; import org.bouncycastle.crypto.params.KeyParameter; import com.alibaba.common.lang.StringUtil; import com.huateng.commons.lang.convert.HexUtils; public class ShfftDes { //验证用密钥 private byte[] key = "000000000000000000000000".getBytes(); // private byte[] key = Hex.decode("00000000"); private byte[] ivs = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; private static final String DES_EDE = "DESede/ECB/NoPadding"; //定义 加密算法,可用 DES,DESede,Blowfish //keybyte为加密密钥,长度为24字节 //src为被加密的数据缓冲区(源) private static final String DES_EDE_CBC = "DESede/CBC/NoPadding"; //定义 加密算法,可用 DES,DESede,Blowfish //keybyte为加密密钥,长度为24字节 //src为被加密的数据缓冲区(源) private static final String DES_CBC = "DES/CBC/NoPadding"; private static final String DES_ECB = "DES/ECB/PKCS5Padding"; public byte[] CryptByDes(byte[] content, int mode) throws Exception { Cipher cipher = Cipher.getInstance(DES_ECB); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = keyFactory.generateSecret(new DESKeySpec(key)); cipher.init(mode, secretKey); return cipher.doFinal(content); } public byte[] CryptBy3Des(byte[] content, int mode) throws Exception { Cipher cipher = Cipher.getInstance(DES_EDE); SecretKey secretKey = new SecretKeySpec(key, "DESede"); cipher.init(mode, secretKey); return cipher.doFinal(content); } public byte[] CryptByDesCbc(byte[] content, int mode) throws Exception { Cipher cipher = Cipher.getInstance(DES_CBC); SecretKey secureKey = new SecretKeySpec(key, "DES"); IvParameterSpec iv = new IvParameterSpec(ivs); cipher.init(mode, secureKey, iv); return cipher.doFinal(HexUtils.fromHex(new String(content))); } public byte[] CryptBy3DesCbc(byte[] content, int mode) throws Exception { Cipher cipher = Cipher.getInstance(DES_EDE_CBC); SecretKey secureKey = new SecretKeySpec(key, "DESede"); IvParameterSpec iv = new IvParameterSpec(ivs); cipher.init(mode, secureKey, iv); return cipher.doFinal(content); } public byte[] CryptByDesCbcMac(byte[] content) throws Exception { BlockCipher engine = new DESEngine(); Mac mac = new CBCBlockCipherMac(engine, 64); byte[] macText = new byte[engine.getBlockSize()]; mac.init(new KeyParameter(key)); mac.update(Padding(content, 64), 0, content.length); mac.update(content, 0, content.length); mac.doFinal(macText, 0); return macText; } public byte[] ShFftCryptByDessdsCbc(byte[] content, int mode) throws Exception { byte[] ks1 = HexUtils.fromHex(new String(key)); byte[] ks = new byte[24]; System.arraycopy(ks1, 0, ks, 0, ks1.length); System.arraycopy(ks1, 0, ks, ks1.length, 8); Cipher cipher = Cipher.getInstance(DES_EDE_CBC); SecretKeyFactory keyFactory = null; keyFactory = SecretKeyFactory.getInstance("DESede"); SecretKey secretKey = null; secretKey = keyFactory.generateSecret(new DESedeKeySpec(ks)); IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }); cipher.init(mode, secretKey, iv); return cipher.doFinal(HexUtils.fromHex(new String(content))); } public byte[] mac(byte[] content) throws Exception { int len; byte plainData[]; byte encryptedData[]; len = (content.length / 8 + (content.length % 8 != 0 ? 1 : 0)) * 8; plainData = new byte[len]; encryptedData = new byte[8]; Arrays.fill(plainData, (byte) 32); System.arraycopy(content, 0, plainData, 0, content.length); SecureRandom sr = new SecureRandom(); DESKeySpec dks = new DESKeySpec(key); SecretKeyFactory keyFactory = null; keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = keyFactory.generateSecret(dks); Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding"); IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }); cipher.init(1, secretKey, iv, sr); System.arraycopy(cipher.doFinal(plainData), len - 8, encryptedData, 0, 8); return encryptedData; } public byte[] Padding(byte[] content, int block) { int contentLength = content.length; int mod = contentLength % block; if (mod != 0) { int size = contentLength + block - mod; // String s = new String(content); // StringUtil.alignLeft(s, size, " "); byte[] s = new byte[size]; System.arraycopy(content, 0, s, 0, content.length); for (int i = content.length; i < size; i++) { s[i] = 32; } return s; } return content; } public String Padding(String content, int block) { int contentLength = content.length(); int mod = contentLength % block; if (mod != 0) { int size = contentLength + block - mod; String s = new String(content); StringUtil.alignLeft(s, size, " "); return s; } return content; } public void println(byte[] bs) { for (byte b : bs) { System.out.print(b + " "); } System.out.println(); } public void printlnByte(byte[] bs) { for (byte b : bs) { if (b < 0) { System.out.print((int) b + 256 + " "); } else { System.out.print(b + " "); } } System.out.println(); } public void printlnByteInt16(byte[] bs) { for (byte b : bs) { System.out.print(Integer.toHexString((int) b) + " "); } System.out.println(); } public String dumpBytes(byte[] bytes) { int i; StringBuffer sb = new StringBuffer(); for (i = 0; i < bytes.length; i++) { int n = bytes[i] >= 0 ? bytes[i] : 256 + bytes[i]; String s = Integer.toHexString(n); if (s.length() < 2) { s = "0" + s; } if (s.length() > 2) { s = s.substring(s.length() - 2); } sb.append(s); } return sb.toString().toUpperCase(); //return new BASE64Encoder().encode(bytes); } // 一下程序将每2位16进制整数组装成一个字节 private String hexString = "0123456789ABCDEF"; public byte[] decode(String bytes) { ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2); for (int i = 0; i < bytes.length(); i += 2) baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString.indexOf(bytes .charAt(i + 1)))); return baos.toByteArray(); } public byte[] getKey() { return key; } public void setKey(byte[] key) { this.key = key; } public byte[] getIvs() { return ivs; } public void setIvs(byte[] ivs) { this.ivs = ivs; } }