2015-02-23 53 views
0

我已經採取了這篇文章Simple ENCRYPTION參考,簡單加密的Android

我走在EditText上一些文字,然後使用自定義對話框以從用戶的鍵,然後創建它在文章中提到,加密原文,解密它,並顯示它在屏幕上Textview ..但運行後的異常顯示在logcat中,如代碼中所述..它確實很簡單,但我是一個Android和Java新手,所以面臨困難。可能我​​覺得我在做錯誤的變量傳遞

Java代碼

package com.example.encryptiondecryption; 

    import java.security.SecureRandom; 

    import javax.crypto.Cipher; 
    import javax.crypto.KeyGenerator; 
    import javax.crypto.spec.SecretKeySpec; 
    import android.app.Activity; 
    import android.app.Dialog; 
    import android.content.Context; 
    import android.os.Bundle; 
    import android.util.Base64; 
    import android.util.Log; 
    import android.view.View; 
    import android.view.View.OnClickListener; 
    import android.widget.Button; 
    import android.widget.EditText; 
    import android.widget.TextView; 

    public class MainActivity extends Activity implements OnClickListener { 

     static final String TAG = "SymmetricAlgorithmAES"; 
     static final String TAG1 = "encccccccc"; 
     EditText getData_edt, key_edt; 
     Button genkey_btn, encrypt_btn, decrypt_btn; 
     static String key_str = null; 
     static String getData_str = null; 

     static SecretKeySpec sks = null; 
     static byte[] encodedBytes = null; 

     static byte[] decodedBytes = null; 

     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_main); 

      getData_edt = (EditText) (findViewById(R.id.am_input_edt)); 
      genkey_btn = (Button) (findViewById(R.id.am_key_btn)); 
      encrypt_btn = (Button) (findViewById(R.id.am_encrypt_btn)); 
      decrypt_btn = (Button) (findViewById(R.id.am_decrypt_btn)); 
      getData_str = getData_edt.getText().toString(); 

      genkey_btn.setOnClickListener(this); 
      encrypt_btn.setOnClickListener(this); 
      decrypt_btn.setOnClickListener(this); 

     } 

     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      switch (v.getId()) { 

      case R.id.am_key_btn: 
       genKey(sks); 

       break; 
      case R.id.am_encrypt_btn: 
       encrypt(sks); 

       break; 
      case R.id.am_decrypt_btn: 
       decrypt(); 

       break; 

      default: 
       break; 
      } 

     } 

     private void genKey(SecretKeySpec sks) { 
      // TODO Auto-generated method stub 
      Context context = this; 
      final Dialog myDialog = new Dialog(context); 

      myDialog.setContentView(R.layout.dialog); 

      myDialog.setTitle("enter key"); 

      key_edt = (EditText) myDialog.findViewById(R.id.dg_key_tv); 
      Button ok_btn = (Button) myDialog.findViewById(R.id.dg_ok_btn); 
      Button cancel_btn = (Button) myDialog.findViewById(R.id.dg_cancel_btn); 

      Log.d(TAG1, key_str); 

      ok_btn.setOnClickListener(new OnClickListener() { 

       @Override 
       public void onClick(View v) { 
        // TODO Auto-generated method stub 

        key_str = key_edt.getText().toString(); 

       } 
      }); 
      try { 
       SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
       sr.setSeed(key_str.getBytes()); 

       KeyGenerator kg = KeyGenerator.getInstance("AES"); 
       kg.init(128, sr); 
       sks = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES"); 
       Log.i("encrypt", sks.toString()); 

      } catch (Exception e) { 
       Log.e(TAG, "AES secret key spec error"); 
      } 
      cancel_btn.setOnClickListener(new OnClickListener() { 

       @Override 
       public void onClick(View v) { 
        // TODO Auto-generated method stub 
        myDialog.dismiss(); 
       } 
      }); 
      myDialog.show(); 

     } 

     private void encrypt(SecretKeySpec sks) { 
      // TODO Auto-generated method stub 

      try { 
       Cipher c = Cipher.getInstance("AES"); 
       c.init(Cipher.ENCRYPT_MODE, sks); 
       encodedBytes = c.doFinal(getData_str.getBytes()); 
       String encoded = Base64 
         .encodeToString(encodedBytes, Base64.DEFAULT); 
       System.out.println(" " + encoded); 
      } catch (Exception e) { 
       Log.e(TAG, "AES encryption error"); 
      } 
     } 

     private void decrypt() { 
      // TODO Auto-generated method stub 

      try { 
       Cipher c = Cipher.getInstance("AES"); 
       c.init(Cipher.DECRYPT_MODE, sks); 
       decodedBytes = c.doFinal(encodedBytes); 
       System.out.println(" " + new String(decodedBytes)); 

      } catch (Exception e) { 
       Log.e(TAG, "AES decryption error"); 
       TextView tvdecoded = (TextView) findViewById(R.id.am_show_tv); 
       tvdecoded.setText("DECOD\n" + new String(decodedBytes) + "\n"); 
      } 
     } 
    } 

XML

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.example.encryptiondecryption.MainActivity" > 

    <EditText 
     android:id="@+id/am_input_edt" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentRight="true" 
     android:layout_alignParentTop="true" 


     android:ems="10" 
     android:inputType="textMultiLine" /> 

    <Button 
     android:id="@+id/am_key_btn" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignLeft="@+id/am_input_edt" 
     android:layout_below="@+id/am_input_edt" 
     android:text="enter your key" /> 

    <Button 
     android:id="@+id/am_encrypt_btn" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignLeft="@id/am_key_btn" 
     android:layout_below="@+id/am_key_btn" 
     android:text="Encrypt" /> 

    <Button 
     android:id="@+id/am_decrypt_btn" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignLeft="@id/am_encrypt_btn" 
     android:layout_below="@+id/am_encrypt_btn" 
     android:text="Decrypt" /> 

    <TextView 
     android:id="@+id/am_show_tv" 
     android:layout_width="match_parent" 
     android:layout_height="40dp" 
     android:layout_alignLeft="@+id/am_decrypt_btn" 
     android:layout_below="@+id/am_decrypt_btn" 
     android:layout_marginTop="15dp" 
     android:textAppearance="?android:attr/textAppearanceMedium" /> 

</RelativeLayout> 

XML佈局對話框...

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <EditText 
     android:id="@+id/dg_key_tv" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:ems="10" > 

     <requestFocus /> 
    </EditText> 

<Button 
    android:id="@+id/dg_ok_btn" 
    android:layout_width="61dp" 
    android:layout_height="wrap_content" 
    android:text="Ok" /> 

<Button 
    android:id="@+id/dg_cancel_btn" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="cancel" 
    /> 

logcat的錯誤

02-23 23:50:17.245: E/SymmetricAlgorithmAES(12735): AES secret key spec error 
02-23 23:50:17.245: W/System.err(12735): java.lang.NullPointerException 
02-23 23:50:17.265: W/System.err(12735): at com.example.encryptiondecryption.MainActivity.genKey(MainActivity.java:99) 
02-23 23:50:17.265: W/System.err(12735): at com.example.encryptiondecryption.MainActivity.onClick(MainActivity.java:56) 
02-23 23:50:17.265: W/System.err(12735): at android.view.View.performClick(View.java:4439) 
02-23 23:50:17.265: W/System.err(12735): at android.widget.Button.performClick(Button.java:139) 
02-23 23:50:17.265: W/System.err(12735): at android.view.View$PerformClick.run(View.java:18395) 
02-23 23:50:17.265: W/System.err(12735): at android.os.Handler.handleCallback(Handler.java:725) 
02-23 23:50:17.265: W/System.err(12735): at android.os.Handler.dispatchMessage(Handler.java:92) 
02-23 23:50:17.265: W/System.err(12735): at android.os.Looper.loop(Looper.java:176) 
02-23 23:50:17.265: W/System.err(12735): at android.app.ActivityThread.main(ActivityThread.java:5317) 
02-23 23:50:17.265: W/System.err(12735): at java.lang.reflect.Method.invokeNative(Native Method) 
02-23 23:50:17.265: W/System.err(12735): at java.lang.reflect.Method.invoke(Method.java:511) 
02-23 23:50:17.265: W/System.err(12735): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102) 
02-23 23:50:17.265: W/System.err(12735): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869) 
02-23 23:50:17.265: W/System.err(12735): at dalvik.system.NativeStart.main(Native Method) 
02-23 23:50:21.579: E/ViewRootImpl(12735): sendUserActionEvent() mView == null 
02-23 23:50:23.491: E/SymmetricAlgorithmAES(12735): AES encryption error 
02-23 23:50:24.932: E/SymmetricAlgorithmAES(12735): AES decryption error 
02-23 23:50:24.932: W/System.err(12735): java.lang.NullPointerException 
02-23 23:50:24.942: W/System.err(12735): at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(BaseBlockCipher.java:385) 
02-23 23:50:24.942: W/System.err(12735): at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(BaseBlockCipher.java:625) 
02-23 23:50:24.952: W/System.err(12735): at javax.crypto.Cipher.init(Cipher.java:519) 
02-23 23:50:24.952: W/System.err(12735): at javax.crypto.Cipher.init(Cipher.java:479) 
02-23 23:50:24.952: W/System.err(12735): at com.example.encryptiondecryption.MainActivity.decrypt(MainActivity.java:141) 
02-23 23:50:24.952: W/System.err(12735): at com.example.encryptiondecryption.MainActivity.onClick(MainActivity.java:64) 
02-23 23:50:24.952: W/System.err(12735): at android.view.View.performClick(View.java:4439) 
02-23 23:50:24.952: W/System.err(12735): at android.widget.Button.performClick(Button.java:139) 
02-23 23:50:24.952: W/System.err(12735): at android.view.View$PerformClick.run(View.java:18395) 
02-23 23:50:24.952: W/System.err(12735): at android.os.Handler.handleCallback(Handler.java:725) 
02-23 23:50:24.952: W/System.err(12735): at android.os.Handler.dispatchMessage(Handler.java:92) 
02-23 23:50:24.952: W/System.err(12735): at android.os.Looper.loop(Looper.java:176) 
02-23 23:50:24.952: W/System.err(12735): at android.app.ActivityThread.main(ActivityThread.java:5317) 
02-23 23:50:24.952: W/System.err(12735): at java.lang.reflect.Method.invokeNative(Native Method) 
02-23 23:50:24.952: W/System.err(12735): at java.lang.reflect.Method.invoke(Method.java:511) 
02-23 23:50:24.952: W/System.err(12735): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102) 
02-23 23:50:24.952: W/System.err(12735): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869) 
02-23 23:50:24.952: W/System.err(12735): at dalvik.system.NativeStart.main(Native Method) 
02-23 23:50:24.952: D/AndroidRuntime(12735): Shutting down VM 
02-23 23:50:24.952: W/dalvikvm(12735): threadid=1: thread exiting with uncaught exception (group=0x412b3930) 
02-23 23:50:24.962: E/AndroidRuntime(12735): FATAL EXCEPTION: main 
02-23 23:50:24.962: E/AndroidRuntime(12735): java.lang.NullPointerException 
02-23 23:50:24.962: E/AndroidRuntime(12735): at java.lang.String.<init>(String.java:141) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at com.example.encryptiondecryption.MainActivity.decrypt(MainActivity.java:148) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at com.example.encryptiondecryption.MainActivity.onClick(MainActivity.java:64) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at android.view.View.performClick(View.java:4439) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at android.widget.Button.performClick(Button.java:139) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at android.view.View$PerformClick.run(View.java:18395) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at android.os.Handler.handleCallback(Handler.java:725) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at android.os.Handler.dispatchMessage(Handler.java:92) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at android.os.Looper.loop(Looper.java:176) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at android.app.ActivityThread.main(ActivityThread.java:5317) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at java.lang.reflect.Method.invokeNative(Native Method) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at java.lang.reflect.Method.invoke(Method.java:511) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869) 
02-23 23:50:24.962: E/AndroidRuntime(12735): at dalvik.system.NativeStart.main(Native Method) 
+0

後從logcat的 – Yazan 2015-02-23 14:47:12

+0

@Yazan張貼在最後的錯誤... – user3519331 2015-02-23 15:03:35

+0

在任何你使用log.e,也使用的printStackTrace()的異常,這會顯示實際的錯誤,e.printStacktrace()會更有用。現在你的日誌說發生了錯誤與產生密鑰發生,所以使用'printStacktrace'併發布錯誤 – Yazan 2015-02-23 15:07:27

回答

0

我想你的問題之一是當你通過會發生什麼誤會一個方法的對象。在這個方法中,你可以通過調用它的方法來修改一個參數對象,但是你不能給它賦值,並且期望它以任何方式影響調用代碼。有關這方面的更多信息,請閱讀:Is Java "pass-by-reference" or "pass-by-value"?

這導致你在你的密鑰生成方法,你在你的sks場傳遞,希望下面的代碼將更改字段值的問題:

sks = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES"); 

相反,這隻影響本地方法參數變量的值。它對您的sks字段沒有影響。要解決此問題,分配到外地直接:

this.sks = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES"); 

然後,您可以調整你的方法,以便它不需要參數:

private void genKey() { 
    // .... 
} 
+0

thnx對於寶貴的建議...不能夠運行代碼..但現在非常清楚... – user3519331 2015-02-23 19:50:53

0

至於對方的回答指出,您的sks變量的作用域必須是整個類,而不僅僅是genkey()方法。但是,該方法存在導致規格錯誤的另一個錯誤。它創建一個對話框窗口並將偵聽器添加到OK按鈕,但隨後嘗試創建該鍵(而TextView仍爲空)。生成代碼應該是click監聽器的一部分。

private void genKey() { 
     // TODO Auto-generated method stub 
     Context context = this; 
     final Dialog myDialog = new Dialog(context); 

     myDialog.setContentView(R.layout.dialog); 

     myDialog.setTitle("enter key"); 

     key_edt = (EditText) myDialog.findViewById(R.id.dg_key_tv); 
     Button ok_btn = (Button) myDialog.findViewById(R.id.dg_ok_btn); 
     Button cancel_btn = (Button) myDialog.findViewById(R.id.dg_cancel_btn); 

     Log.d(TAG1, key_str); 

     ok_btn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // TODO Auto-generated method stub 

       key_str = key_edt.getText().toString(); 

       // only try to create the Key Spec now we have our key string 
       // first check to make sure it's not blank 
       if(key_str != null && !key_str.isEmpty()){ 
        try { 
         SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
         sr.setSeed(key_str.getBytes()); 

         KeyGenerator kg = KeyGenerator.getInstance("AES"); 
         kg.init(128, sr); 
         this.sks = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES"); 
         Log.i("encrypt", sks.toString()); 

        } catch (Exception e) { 
         Log.e(TAG, "AES secret key spec error"); 
        } 
       } 
       else{ // string is empty 
        // make some toast to alert user 
       } 
      } 
     }); 

     cancel_btn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // TODO Auto-generated method stub 
       myDialog.dismiss(); 
      } 
     }); 
     myDialog.show(); 

    } 

另請注意,這應該使用this.sks將Keyspec存儲爲類變量。否則,一旦clickListener結束,它將被垃圾收集。你的加密和解密函數應該使用這個類變量來完成他們的工作,並且如果還沒有生成密鑰,則顯示敬酒或其他東西。

例如與encrypt()方法:

private void encrypt() { 
    if (this.sks == null){ 
     // make toast and tell user to generate the key 
    } else { 
     try { 
      Cipher c = Cipher.getInstance("AES"); 
      // use the class key spec to encrypt 
      c.init(Cipher.ENCRYPT_MODE, this.sks); 
      encodedBytes = c.doFinal(getData_str.getBytes()); 
      String encoded = Base64 
        .encodeToString(encodedBytes, Base64.DEFAULT); 
      System.out.println(" " + encoded); 
     } catch (Exception e) { 
      Log.e(TAG, "AES encryption error"); 
     } 
    } 
} 
+0

我試着按照你的建議...但是當我試圖把代碼放到點擊列表代碼時,它再次說到在點擊列表器方法中生成keyspec字段...爲什麼我在全局聲明它時,它是否會再次影響我的代碼...?..也請告訴如何在加密和解密方法中使用相同的聲明的Spec鍵變量...我很困惑,請幫忙 – user3519331 2015-02-23 19:56:31

+0

當你說「它再次說在點擊列表器方法中產生keyspec字段」時,你是否真的得到一個錯誤日誌或告訴你的東西?如果是這樣,請在你的問題中發佈。您正在使用onClickListener方法生成它,它用於彈出對話框中的「確定」按鈕。 至於如何在加密和解密方法中使用它,我編輯了我的答案以提供示例。當你生成密鑰時,它應該保存爲一個類實例變量,以便它可以被所有方法使用。如果你不這樣做,只要你的方法結束,它就會被銷燬。 – 2015-02-24 04:53:07