.net的3DES加密解密代码:
public static string TripleDESDecrypt(string pToDecrypt, string sKey)
{
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.Zeros;
byte[] inputByteArray = new byte[pToDecrypt.Length / 2]; // pToDecrypt.Length / 2 = 8
for (int x = 0; x < pToDecrypt.Length / 2; x++) // pToDecrypt.Length = 16
{
string s = pToDecrypt.Substring(x * 2, 2);
int i = (Convert.ToInt32(s, 16));
inputByteArray[x] = (byte)i;
}
des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); // {byte[24]}
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
StringBuilder ret = new StringBuilder();
return System.Text.Encoding.Default.GetString(ms.ToArray());
}
public static string TripleDESEncrypt(string pToEncrypt, string sKey) // 加密
{
try {
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.Zeros;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
byte[] inputByteArray = Encoding.Default.GetBytes(pToEncrypt);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock(); ;
StringBuilder ret = new StringBuilder();
foreach (byte b in ms.ToArray()) {
ret.AppendFormat("{0:X2}", b);
}
ret.ToString();
return ret.ToString();
} catch (Exception ex) {
return ex.Message;
}
}
现在把上面的代码用java实现,要求加解密后的内容与.net一致.
使用cipher可以很容易的实现3des加密,但是跟其他平台开发的3des加密对接来说,通常会有一些问题。基本程序如下:
public static byte[] desEncrypt(String message, String key) throws Exception {
Cipher cipher = Cipher.getInstance("DESede");
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(message.getBytes("UTF-8"));
}
与其他平台对接发现对同样输入加密以后结果不同,看看jdk的文档,有如下描述:
A transformation is a string that describes the operation (or set of operations) to be performed on the given input, to produce some output.
A transformation is of the form:
- "algorithm/mode/padding" or
- "algorithm"
根据前面的代码,我们已经选择了正确的算法,那么加密不同的原因应该就是mode和padding了。
he SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. This means that in the case of the SunJCE provider,
Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding");
and
Cipher c1 = Cipher.getInstance("DES");
are equivalent statements.
对于其他语言开发的3des,一定要采用相同的mode和padding才能保证通信。
Appendix A of this document contains a list of standard names that can be used to specify the algorithm name, mode, and padding scheme components of a transformation.(Appendix A 此链接规定了java加密算法的 名称/加密运算模式/填充模式,可参考.)
从上面.net的代码可以看出,
des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); // 加密密匙
des.Mode = CipherMode.ECB; // 运算模式
des.Padding = PaddingMode.Zeros; //填充模式
因此,对应的java代码应该为:
Security.addProvider(new com.sun.crypto.provider.SunJCE());
SecretKey desKey = new SecretKeySpec("your key".getBytes("utf-8"), ALGORITHM_KEY);
Cipher tcipher = Cipher.getInstance("DESede/ECB/NoPadding");
tcipher.init(Cipher.DECRYPT_MODE, desKey);
完整的代码如下:
import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.util.Properties;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class TripleDesUtils {
private static final String ALGORITHM_KEY = "DESede";
private static final String ALGORITHM_CIPHER_INIT = "DESede/ECB/NoPadding";
/**
* 字节数组转化为大写16进制字符串
*
* @param b
* @return
*/
private 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;
}
}
return hs.toUpperCase();
}
public static void main(String[] args) throws Exception {
Properties pro = PropertiesUtils.getProperties("3des.properties");
String algorithm_key = pro.getProperty("3des_algorithm_key");
TripleDesUtils t = new TripleDesUtils();
t.key = algorithm_key;
System.out.println("加密后的:" + t.encrypt_ECB("2014-5-7"));
System.out.println("解密后的:" + t.decrypt_ECB("50E09194AB312A08").trim());
}
/**
* 字符串转字节数组
*
* @param s
* @return
*/
private static byte[] str2ByteArray(String s) {
int byteArrayLength = s.length() / 2;
byte[] b = new byte[byteArrayLength];
for (int i = 0; i < byteArrayLength; i++) {
byte b0 = (byte) Integer.valueOf(s.substring(i * 2, i * 2 + 2), 16).intValue();
b[i] = b0;
}
return b;
}
private Cipher cipher = null;
// 密钥
private String key = "";
private byte[] decrypt_ECB(byte[] src) {
cipher = initCipher(Cipher.DECRYPT_MODE);
try {
return cipher.doFinal(src);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public String decrypt_ECB(String src) {
byte[] b = decrypt_ECB(str2ByteArray(src));
return new String(b);
}
private byte[] encrypt_ECB(byte[] src) {
try {
cipher = initCipher(Cipher.ENCRYPT_MODE);
return cipher.doFinal(src);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public String encrypt_ECB(String src) {
byte[] b;
try {
b = encrypt_ECB(src.getBytes("utf-8"));
return byte2Hex(b);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public String getKey() {
return key;
}
private final Cipher initCipher(int mode) {
try {
Security.addProvider(new com.sun.crypto.provider.SunJCE());
// Security.addProvider(new BouncyCastleProvider());
SecretKey desKey = new SecretKeySpec(key.getBytes("utf-8"), ALGORITHM_KEY);
Cipher tcipher = Cipher.getInstance(ALGORITHM_CIPHER_INIT);
tcipher.init(mode, desKey);
return tcipher;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void setKey(String key) {
this.key = key;
}
}