from://http://my.oschina.net/u/269082/blog/56163
工作中需要和HPH对接,接口一些敏感信息,讨论后用3DES加密,由于我做的android邮件客户端是依附于php系统,所以我写加密算法对接HPH的加密,然后遇到一个棘手的问题,我的加密解密过程顺利,但是同样的密钥,同样的明文,java和php加密不一样,后来发现双方理解有误我理解的密钥是byte[]类型的,对方的密钥是通过类似String.getBytes()的方法出来的引此为戒
import java.security.SecureRandom;
import java.security.Security;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/*字符串 DESede(3DES) 加密*/
public class ThreeDes {
/**
* 3DS加密
*
* @author [email protected]
*/
private static final String Algorithm = "DESede/CBC/PKCS5Padding"; // 定义加密算法,可用
// DES,DESede,Blowfish,DESede/CBC/PKCS5Padding
// keybyte为加密密钥,长度为24字节
// src为被加密的数据缓冲区(源)
/*
* private static SecretKey deskey = null;
*
* public static void getKey(byte[] strKey) { try { KeyGenerator _generator
* = KeyGenerator.getInstance("DES"); _generator.init(new
* SecureRandom(strKey)); deskey = _generator.generateKey(); _generator =
* null; } catch (Exception e) { e.printStackTrace(); } }
*/
public static byte[] encryptMode(String iv, String key, String src) {
try {
byte[] keybyte = key.getBytes();
byte[] rand = new byte[8];
rand = iv.getBytes();
// 用随即数生成初始向量
/*
* Random r=new Random(); r.nextBytes(rand);
*/
IvParameterSpec ivp = new IvParameterSpec(rand);
// 生成密钥
// SecureRandom sr = new SecureRandom();
DESedeKeySpec dks = new DESedeKeySpec(keybyte);
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance("DESede");
SecretKey securekey = keyFactory.generateSecret(dks);
// IvParameterSpec iv = new IvParameterSpec(PASSWORD_IV.getBytes());
/*
* Cipher cipher = Cipher.getInstance("DESede");
* cipher.init(Cipher.ENCRYPT_MODE, securekey, ivp, sr); return new
* String(Hex.encodeHex(cipher.doFinal(str.getBytes())));
*/
// 加密
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE, securekey, ivp);
return c1.doFinal(src.getBytes());// 在单一方面的加密或解密
} catch (java.security.NoSuchAlgorithmException e1) {
// TODO: handle exception
e1.printStackTrace();
} catch (javax.crypto.NoSuchPaddingException e2) {
e2.printStackTrace();
} catch (java.lang.Exception e3) {
e3.printStackTrace();
}
return null;
}
// keybyte为加密密钥,长度为24字节
// src为加密后的缓冲区
public static byte[] decryptMode(String iv, String key, byte[] src) {
try {
byte[] srcbytes = src;
byte[] keybyte = key.getBytes();
byte[] rand = new byte[8];
rand = iv.getBytes();
// 用随即数生成初始向量
/*
* Random r=new Random(); r.nextBytes(rand);
*/
IvParameterSpec ivp = new IvParameterSpec(rand);
// 生成密钥
SecureRandom sr = new SecureRandom();
DESedeKeySpec dks = new DESedeKeySpec(keybyte);
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance("DESede");
SecretKey securekey = keyFactory.generateSecret(dks);
// 解密
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE, securekey, ivp);
/*
* int len = src.getBytes().length; byte[] zero = { 0x00, 0x00,
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; if (len < 8) { srcbytes =
* new byte[8]; System.arraycopy(src.getBytes(), 0, srcbytes, 0,
* len); System.arraycopy(zero, len, srcbytes, len, 8 - len); } else
* { srcbytes = src.getBytes(); }
*/
return c1.doFinal(srcbytes);
} catch (java.security.NoSuchAlgorithmException e1) {
// TODO: handle exception
e1.printStackTrace();
} catch (javax.crypto.NoSuchPaddingException e2) {
e2.printStackTrace();
} catch (java.lang.Exception e3) {
e3.printStackTrace();
}
return null;
}
// 转换成十六进制字符串
public static String byte2Hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
if (n < b.length - 1)
hs = hs + ":";
}
return hs.toUpperCase();
}
public static final String encodeHex(byte bytes[]) {
StringBuffer buf = new StringBuffer(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
if ((bytes[i] & 0xff) < 16)
buf.append("0");
buf.append(Long.toString(bytes[i] & 0xff, 16));
}
return buf.toString();
}
public static final byte[] decodeHex(String hex) {
char chars[] = hex.toCharArray();
byte bytes[] = new byte[chars.length / 2];
int byteCount = 0;
for (int i = 0; i < chars.length; i += 2) {
int newByte = 0;
newByte |= hexCharToByte(chars[i]);
newByte <<= 4;
newByte |= hexCharToByte(chars[i + 1]);
bytes[byteCount] = (byte) newByte;
byteCount++;
}
return bytes;
}
private static final byte hexCharToByte(char ch) {
switch (ch) {
case 48: // '0'
return 0;
case 49: // '1'
return 1;
case 50: // '2'
return 2;
case 51: // '3'
return 3;
case 52: // '4'
return 4;
case 53: // '5'
return 5;
case 54: // '6'
return 6;
case 55: // '7'
return 7;
case 56: // '8'
return 8;
case 57: // '9'
return 9;
case 97: // 'a'
return 10;
case 98: // 'b'
return 11;
case 99: // 'c'
return 12;
case 100: // 'd'
return 13;
case 101: // 'e'
return 14;
case 102: // 'f'
return 15;
case 58: // ':'
case 59: // ';'
case 60: // '<'
case 61: // '='
case 62: // '>'
case 63: // '?'
case 64: // '@'
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 91: // '['
case 92: // '\\'
case 93: // ']'
case 94: // '^'
case 95: // '_'
case 96: // '`'
default:
return 0;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
// 添加新安全算法,如果用JCE就要把它添加进去
// Security.addProvider(new com.sun.crypto.provider.SunJCE());
/*
* final byte[] keyBytes = { 0x01, 0x02, 0x03, 0x04,
*
* (byte) 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x01, 0x02,
*
* (byte) 0x03,
*
* (byte) 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
*
* (byte) 0x00, 0x01, 0x02, 0x03,
*
* (byte) 0x04
*
* }; // 24字节的密钥
*/
String szSrc = "1";
System.out.println("加密前的字符串:" + szSrc);
byte[] encoded = encryptMode("12345678", "123456789012345678943210",
szSrc);
System.out.println("加密后的字符串:" + encodeHex(encoded));
byte[] srcBytes = decryptMode("12345678", "123456789012345678943210",
"c5e8faaf1a0e52ae".getBytes());
System.out.println("解密后的字符串:" + (new String(srcBytes)));
}
}