您的位置:首页 > 移动开发 > Android开发

Android平台和java平台 DES加密解密互通程序及其不能互通的原因

2014-12-24 15:18 309 查看
网上的demo一搜一大堆,但是,基本上都是一知半解(包括我)。为什么呢?我在尝试分别在两个平台加密的时候,竟然发现Android DES 加密和java DES加密的程序不能互通。就是加密的结果不一样,更不要说Android平台的加密输入作为java DES的解密输出了。这样的话,客户端和服务器端就不能进行通信了。我网上之前也发帖子问了不少人,但是回答都不满意。

今天部门的另外一个同事跟我说了一下,才解决了这个不能互通的问题。

调用DES加密算法包最精要的就是下面两句话:

Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);

CBC是工作模式,DES一共有电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)四种模式,

PKCS5Padding是填充模式,还有其它的填充模式:

然后,cipher.init()一共有三个参数:Cipher.ENCRYPT_MODE, key, zeroIv,zeroIv就是初始化向量,一个8为字符数组。

工作模式、填充模式、初始化向量这三种因素一个都不能少。否则,如果你不指定的话,那么就要程序就要调用默认实现。问题就来了,这就与平台有关了。难怪网上一搜"DES加密结果不一致“,出现n多网页结果。(之前我并没有指定IV,被折磨了2周)

源程序如下(从java平台到android平台,我根本没有更改一行代码):

另外,一般情况下,加密后的结果都会用base64编码进行传输。

java平台:

主程序

[java] view
plaincopy

public class testDES {



/**

* @param args

* @throws Exception

*/

public static void main(String[] args) throws Exception {

// TODO Auto-generated method stub

String key = "12345678";

String text = "12345678";

String result1 = DES.encryptDES(text,key);

String result2 = DES.decryptDES(result1, key);

System.out.println(result1);

System.out.println(result2);

}

}

用到的DES加密类

[java] view
plaincopy

import javax.crypto.Cipher;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

[java] view
plaincopy

public class DES {

private static byte[] iv = {1,2,3,4,5,6,7,8};

public static String encryptDES(String encryptString, String encryptKey) throws Exception {

// IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);

IvParameterSpec zeroIv = new IvParameterSpec(iv);

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 Base64.encode(encryptedData);

}

public static String decryptDES(String decryptString, String decryptKey) throws Exception {

byte[] byteMi = new Base64().decode(decryptString);

IvParameterSpec zeroIv = new IvParameterSpec(iv);

// IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);

SecretKeySpec key = new SecretKeySpec(decryptKey.getBytes(), "DES");

Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);

byte decryptedData[] = cipher.doFinal(byteMi);



return new String(decryptedData);

}

}

用到的BASE64工具类:

[java] view
plaincopy

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.OutputStream;







public class Base64 {

private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();

/**

* data[]进行编码

* @param data

* @return

*/

public static String encode(byte[] data) {

int start = 0;

int len = data.length;

StringBuffer buf = new StringBuffer(data.length * 3 / 2);



int end = len - 3;

int i = start;

int n = 0;



while (i <= end) {

int d = ((((int) data[i]) & 0x0ff) << 16)

| ((((int) data[i + 1]) & 0x0ff) << 8)

| (((int) data[i + 2]) & 0x0ff);



buf.append(legalChars[(d >> 18) & 63]);

buf.append(legalChars[(d >> 12) & 63]);

buf.append(legalChars[(d >> 6) & 63]);

buf.append(legalChars[d & 63]);



i += 3;



if (n++ >= 14) {

n = 0;

buf.append(" ");

}

}



if (i == start + len - 2) {

int d = ((((int) data[i]) & 0x0ff) << 16)

| ((((int) data[i + 1]) & 255) << 8);



buf.append(legalChars[(d >> 18) & 63]);

buf.append(legalChars[(d >> 12) & 63]);

buf.append(legalChars[(d >> 6) & 63]);

buf.append("=");

} else if (i == start + len - 1) {

int d = (((int) data[i]) & 0x0ff) << 16;



buf.append(legalChars[(d >> 18) & 63]);

buf.append(legalChars[(d >> 12) & 63]);

buf.append("==");

}



return buf.toString();

}



private static int decode(char c) {

if (c >= 'A' && c <= 'Z')

return ((int) c) - 65;

else if (c >= 'a' && c <= 'z')

return ((int) c) - 97 + 26;

else if (c >= '0' && c <= '9')

return ((int) c) - 48 + 26 + 26;

else

switch (c) {

case '+':

return 62;

case '/':

return 63;

case '=':

return 0;

default:

throw new RuntimeException("unexpected code: " + c);

}

}



/**

* Decodes the given Base64 encoded String to a new byte array. The byte

* array holding the decoded data is returned.

*/



public static byte[] decode(String s) {



ByteArrayOutputStream bos = new ByteArrayOutputStream();

try {

decode(s, bos);

} catch (IOException e) {

throw new RuntimeException();

}

byte[] decodedBytes = bos.toByteArray();

try {

bos.close();

bos = null;

} catch (IOException ex) {

System.err.println("Error while decoding BASE64: " + ex.toString());

}

return decodedBytes;

}



private static void decode(String s, OutputStream os) throws IOException {

int i = 0;



int len = s.length();



while (true) {

while (i < len && s.charAt(i) <= ' ')

i++;



if (i == len)

break;



int tri = (decode(s.charAt(i)) << 18)

+ (decode(s.charAt(i + 1)) << 12)

+ (decode(s.charAt(i + 2)) << 6)

+ (decode(s.charAt(i + 3)));



os.write((tri >> 16) & 255);

if (s.charAt(i + 2) == '=')

break;

os.write((tri >> 8) & 255);

if (s.charAt(i + 3) == '=')

break;

os.write(tri & 255);



i += 4;

}

}



}

adnroid平台的主函数:

[java] view
plaincopy

public class main extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);



String key = "12345678";

String text = "12345678";





try {

String result1 = DES.encryptDES(text,key);

String result2 = DES.decryptDES(result1, key);

Log.i("DES encode text is ", result1);

Log.i("DES encode text is ", result2);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

通过查看log日志就可以看到结果。

两个平台的结果是一样的,都是:

加密结果:X2p9Uo45Tzk6Ntu6W7Ev+Q==

解密结果:12345678
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: