简体   繁体   中英

simple encryption in android

I've taken reference of this article for Simple ENCRYPTION ,

I am taking some text in edittext and then taking key from user using custom dialog and then creating it as mentioned in article,encrypting original text,decrypting it and showing it to Textview on screen..but after running exception are shown in logcat as described in code..It is very simple indeed but i am a newbie in android and java so facing difficulty.Probably i feel i am doing mistake in variable passing

Java code

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 layout for dialog box...

<?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 error

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)

I think one of your problems is a misunderstanding of what happens when you pass an object to a method. Within the method, you can modify a parameter object by calling its methods, but you cannot assign a value to it and expect it to affect the calling code in any way. For more details on this, read: Is Java "pass-by-reference" or "pass-by-value"?

This has caused you problems in your key generation method, where you pass in your sks field and hope that the following code will change the field value:

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

Instead, this only affects the value of the local method parameter variable. It has no affect on your sks field. To fix this problem, assign to the field directly with:

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

You can then adjust your method so that it doesn't require a parameter:

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

As the other answer points out, your sks variable's scope needs to be the whole class, not just the genkey() method. However, there is another bug in that method which is causing the spec error. It creates a dialog window and adds the listener to the OK button, but then tries to create the key then and there (while the TextView is still empty). The generation code should be part of the click listener.

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();

    }

Please also note that this should store your Keyspec as a class variable using this.sks . Otherwise it will be garbage collected once the clickListener ends. Your encrypt and decrypt functions should use this class variable to do their work, and show a toast or something if the key has not yet been generated.

For example with your encrypt() method:

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");
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM