2012-05-05 50 views
1

我正在开发一个处理SMS的android应用程序。
我完成了应用程序,但最后一件事仍未解决:加密。解密时SMS加密给出异常

我该如何解决传入短信的加密问题?

public class enc { 

     private String iv = "fedcba"; 
     private IvParameterSpec ivspec; 
     private SecretKeySpec keyspec; 
     private Cipher cipher; 

     private String SecretKey = "abcdef"; 

     public enc() 
     { 
      ivspec = new IvParameterSpec(iv.getBytes()); 

      keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES"); 

      try { 
       cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
      } catch (NoSuchAlgorithmException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (NoSuchPaddingException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 

     public String encrypt(String text) throws Exception 
     { 
      if(text == null || text.length() == 0) 
       throw new Exception("Empty string"); 

      byte[] encrypted = null; 

      try { 
       cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); 

       encrypted = cipher.doFinal(padString(text).getBytes()); 
      } catch (Exception e) 
      {   
       throw new Exception("[encrypt] " + e.getMessage()); 
      } 
      String s = new String(encrypted); 
      Log.v("TAG", s); 


      return s; 
     } 

     public String decrypt(String code) throws Exception 
     { 
      if(code == null || code.length() == 0) 
       throw new Exception("Empty string"); 

      byte[] decrypted = null; 

      try { 
       cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); 

       decrypted = cipher.doFinal(hexToBytes(code)); 
      } catch (Exception e) 
      { 
       throw new Exception("[decrypt] " + e.getMessage()); 
      } 
      Log.v("TAG", decrypted.toString()); 
      String s = new String(decrypted); 
      Log.v("TAG", s); 
      return s; 
     } 



     public static String bytesToHex(byte[] data) 
     { 
      if (data==null) 
      { 
       return null; 
      } 

      int len = data.length; 
      String str = ""; 
      for (int i=0; i<len; i++) { 
       if ((data[i]&0xFF)<16) 
        str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF); 
       else 
        str = str + java.lang.Integer.toHexString(data[i]&0xFF); 
      } 
      return str; 
     } 


     public static byte[] hexToBytes(String str) { 
      if (str==null) { 
       return null; 
      } else if (str.length() < 2) { 
       return null; 
      } else { 
       int len = str.length()/2; 
       byte[] buffer = new byte[len]; 
       for (int i=0; i<len; i++) { 
        buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16); 
       } 
       return buffer; 
      } 
     } 



     private static String padString(String source) 
     { 
      char paddingChar = ' '; 
      int size = 16; 
      int x = source.length() % size; 
      int padLength = size - x; 

      for (int i = 0; i < padLength; i++) 
      { 
       source += paddingChar; 
      } 

      return source; 
     } 
    } 

我试过这个,但是解密时它给出了一个例外,它不能解析“A字符”。
通过一个字符,我的意思是一个像a,b,c这样的字母表,不能被解析。

任何帮助?

04-24 13:56:17.191: V/(2031): Message Recieved 
04-24 13:56:22.811: V/TAG(2031): [[email protected] 
04-24 13:56:22.811: V/Encrypted(2031): [[email protected] 
04-24 13:56:22.931: W/System.err(2031): java.lang.Exception: [decrypt] unable to parse '[B' as integer 
04-24 13:56:22.941: W/System.err(2031):  at sms.app.enc.decrypt(enc.java:86) 
04-24 13:56:22.951: W/System.err(2031):  at sms.app.SMSReceiver.onReceive(SMSReceiver.java:86) 
04-24 13:56:22.961: W/System.err(2031):  at android.app.ActivityThread.handleReceiver(ActivityThread.java:2810) 
04-24 13:56:22.961: W/System.err(2031):  at android.app.ActivityThread.access$3200(ActivityThread.java:125) 
04-24 13:56:22.970: W/System.err(2031):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2083) 
04-24 13:56:22.981: W/System.err(2031):  at android.os.Handler.dispatchMessage(Handler.java:99) 
04-24 13:56:22.981: W/System.err(2031):  at android.os.Looper.loop(Looper.java:123) 
04-24 13:56:22.991: W/System.err(2031):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
04-24 13:56:23.001: W/System.err(2031):  at java.lang.reflect.Method.invokeNative(Native Method) 
04-24 13:56:23.001: W/System.err(2031):  at java.lang.reflect.Method.invoke(Method.java:521) 
04-24 13:56:23.011: W/System.err(2031):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
04-24 13:56:23.021: W/System.err(2031):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
04-24 13:56:23.021: W/System.err(2031):  at dalvik.system.NativeStart.main(Native Method) 
+0

看起来您需要更好地理解Java字符和字节之间的差异,因为您的代码显示出根本性的误解。它没有任何意义,并且可能无法从加密输出中构造字符串。另外,使用'toString()'对于byte []'数组没有意义。 –

+1

@GregS如果我甚至不使用toString方法并使用字节数组itt仍然给出相同的异常 – kashifmehmood

+0

我明白,但我的观点是,您需要更熟悉字符和字节之间的差异。 –

回答

0

您可能想要发布完整的堆栈跟踪。如果您的代码存在三个问题:

  • 您的密钥很脆弱:您应该只从某些ASCII字符构造密钥。这严重限制了密钥空间,并且使得密钥的蛮力变得容易。不使用非标准填充的密钥不可用。使用Cipher.getInstance("AES/CBC/PKCS5Padding")得到适当的填充
  • 不使用固定的IV,产生一个随机对每个加密操作

此外,使用getBytes()可能给奇怪的结果,因为编码是不确定的(使用平台默认) 。它可能会在Android上一致,但使用getBytes("UTF-8")来确保您从相同的字符串中获得相同的字节。

+0

用logcat修改请检查出 – kashifmehmood

+0

检查你的输入和输出。您的加密代码似乎试图将加密(〜随机字节)转换为一个字符串,而解密代码似乎期望一个十六进制编码的字符串。 (主要是@GregS说的) –