转载请注明出处,谢谢http://blog.csdn.net/harryweasley/article/details/47746521
最近在公司做一个项目,老大让我们实现加解密的方法,我把工作直接推给了java服务端,他们也是直接在网上copy的代码,说我直接放到我的android代码中就可以了,不需要太多的更改。我就照做了,但是在真正的测试的时候,发现两边输入的密码一致,但是加密结果不一致。这可折磨我们了好久,最终解决了这个问题,加以记录。
android和java加密结果不一样的原因,是因为他们的默认随机数序列不一致,所以解决他的办法是,不要使用默认的创建方法。
以下是正确的代码。android和java端的代码是一致的。
先看MainActivity中的代码。注意,这里的密码个数是16个数字。
package com.example.aesdemo;import android.app.Activity;import android.os.Bundle;import android.util.Log;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String content="thisistest"; String password="1259632153695615"; String jiamiresult=AesUtil.aesEncrypt(content, password); Log.i("tag", "加密结果"+jiamiresult); String jiemi=AesUtil.aesDecrypt(jiamiresult, password); Log.i("tag", "解密结果"+jiemi); }}
logcat中打印的结果是:
再看AesUtil中的代码。
package com.example.aesdemo;import java.io.UnsupportedEncodingException;import java.security.InvalidAlgorithmParameterException;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;public class AesUtil { public static final String VIPARA = "1269571569321021"; public static final String bm = "GBK"; /** * 字节数组转化为大写16进制字符串 * * @param b * @return */ private static String byte2HexStr(byte[] b) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < b.length; i++) { String s = Integer.toHexString(b[i] & 0xFF); if (s.length() == 1) { sb.append("0"); } sb.append(s.toUpperCase()); } return sb.toString(); } /** * 16进制字符串转字节数组 * * @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; } /** * AES 加密 * * @param content * 明文 * @param password * 生成秘钥的关键字 * @return */ public static String aesEncrypt(String content, String password) { try { IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes()); SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv); byte[] encryptedData = cipher.doFinal(content.getBytes(bm)); return Base64.encode(encryptedData);// return byte2HexStr(encryptedData); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * AES 解密 * * @param content * 密文 * @param password * 生成秘钥的关键字 * @return */ public static String aesDecrypt(String content, String password) { try { byte[] byteMi = Base64.decode(content);// byte[] byteMi= str2ByteArray(content); IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes()); SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key, zeroIv); byte[] decryptedData = cipher.doFinal(byteMi); return new String(decryptedData, "utf-8"); } 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(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }}
你们可以看到,我有两行是注释掉的,其实,也可以分别注释上面的base64的,把之前注释的释放,也是可以的。
这里没有注释的,是base64的方式。
不要用android自带的Base64类,用以下的这个。
package com.example.aesdemo;import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; public class Base64 { private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" .toCharArray(); 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; } }}
关于什么是Base64编码,你可以查看http://blog.csdn.net/harryweasley/article/details/47746533
版权声明:本文为博主原创文章,未经博主允许不得转载。