0

I'm using it to decrypt a password (said password is in a URI is in another class). If I hardcode the key, it works. I'm trying a dynamic approach, and this is where I struggle due to my lack of experience. I'm not able to get the two classes to work together.

public class Decrypt {

 
    public void myMethod(Context context) {
        try {
            context.getContentResolver().openInputStream(targURI);
        } catch (FileNotFoundException e1) {
                Toast.makeText(context.getApplicationContext(), "Could not read the content. Please check the URI is correct", Toast.LENGTH_LONG).show();
                return;
            }
            BufferedReader reader1 = new BufferedReader(new InputStreamReader(content));
            StringBuffer buffer = new StringBuffer();
            try {

                while ((line = reader1.readLine()) != null) {
                    md5key = md5key + line;
                }
                index = md5key.indexOf("\"MD5_PIN\"");
                md5key = md5key.substring(index + 10, index + 42);
                Log.i("Test:  ", md5key);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }

//Decrypts password
    public String encryppass(String pass) {
        return this.decrypt(pass);
    }

    private String decrypt(String paramString) {
        byte[] arrayOfByte = Base64.decode(paramString.getBytes(), 0);
        try {
            this.cipher = Cipher.getInstance("AES");
            this.cipher.init(2, this.keySpec);
            String str = new String(this.cipher.doFinal(arrayOfByte), "UTF-8");
            return str;
        }
        catch (Exception exception) {
            exception.printStackTrace();
            return null;
        }
    }
}

MainActivity:


    @Override
    public void onClick(View view) {

        switch (view.getId()) {

            case R.id.exploit1:
                String[] arrayOfString = {"name", "pwd"};
                Cursor cursor = getContentResolver().query(
                        Uri.parse(PWDMANAGER_URI), arrayOfString, null, null, null);

                Decrypt pp = new Decrypt();
                try {
                    if (cursor.moveToFirst()) {
                        do {
                            String name = cursor.getString(0);
                            String encrypted = cursor.getString(1);
                            String decrypted1 = pp.encryppass(encrypted);
                            Log.i("Title:     ", name);
                            Log.i("Password:  ", decrypted1);
                        } while (cursor.moveToNext());
                    }
                } catch (NullPointerException exception) {
                    exception.printStackTrace();
                }

   

Any suggestions on how to get these classes working together?

cbates79
  • 35
  • 7
  • Please edit with the Exception's stack trace, so we can see which line the `NullPointerException` is thrown at. – Luke Sykpe Sep 09 '20 at 03:27
  • Also, does the code - as posted here - work, or does it throw the exception? If not, what change(s) are you making between the posted code, and the code throwing the exception? – Luke Sykpe Sep 09 '20 at 03:36
  • The code posted above does not work as I need it to. If I made a slight change with hardcoding the key. If i hardcode the key here it works: "String md5key = "abcd1234"" - This is not the actual key, just an example. So I know the logic itself works. I know the code to pull the key from the XML file works as I can confirm in logcat. It's just I'm not sure how to get that key from logcat into "md5key" so that it will work with the entire app. I'm sure it's simple, but I'm still fairly new to java. – cbates79 Sep 09 '20 at 03:53
  • My bad, I read "Null Object Reference" in your title as `NullPointerException`. Regardless, the stack trace was necessary in order to answer your question – Luke Sykpe Sep 09 '20 at 04:09

1 Answers1

1

What you've got is an IllegalArgumentException thrown by the SecretKeySpec constructor, specifically in this line:

SecretKeySpec keySpec = new SecretKeySpec(this.md5key.getBytes(), "AES");

A bit of digging around in the documentation reveals that this exception is thrown

"if algorithm is null or key is null or empty".

In Java, String md5key = ""; is an empty String, thus throwing this exception when passed to the SecretKeySpec Constructor. In order to solve it, initialise your SecretKeySpec after md5key has a proper value. More specifically, change that line to:

SecretKeySpec keySpec;

and add this line where Log.i("Test: ", md5key); is:

keySpec = new SecretKeySpec(this.md5key.getBytes(), "AES");

MainActivity:

Before calling encryppass() in this line:

String decrypted1 = pp.encryppass(encrypted);

You'll need to run myMethod(), in order to obtain the md5key value from the xml file. Simply add, before the line mentioned above, the follwing:

pp.myMethod(this);

In this case, this is referring to MainActivity, and is the Context.


The following are a few more trivial mistakes (they won't cause any errors, but aren't really in good practice either - or are redundant):

  1. There is no need for a second switch with the exact same condition. Just add a second case to the original switch:

     switch(view.getId()){
         case R.id.exploit1:
         //code for exploit 1
         break; //is necessary, since switch is continuous, therefore, it will continue executing until it finds a break. Without it, it will also execute the next case(s)
    
         case R.id.exploit2:
         //code for exploit 2
         break;
     }
    
  2. In your database query code, if(cursor.moveToFirst()) is reduntant. The way you did it is also fine, but you could more simply do:

     while(cursor.moveToNext()){
         String name = cursor.getString(0);
         String encrypted = cursor.getString(1);
         String decrypted1 = pp.encryppass(encrypted);
         Log.i("Title:     ", name);
         Log.i("Password:  ", decrypted1);
     }
    

    The first time cursor.moveToNext() is called, it will move to the first position. Because of this, the statement needs to run at least once before the cursor is used so, naturally, this will not work with a do...while() statement.

Luke Sykpe
  • 311
  • 1
  • 11
  • I made the changes and got a different error, but feel that it's closer than it was: 09-08 23:22:23.692 4341-4341/com.example.cbates.myapplication2 W/System.err: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String java.security.Key.getAlgorithm()' on a null object reference – cbates79 Sep 09 '20 at 04:29
  • @cbates79 Make an edit to your original question with the full stack trace, and I'll take a look at it. – Luke Sykpe Sep 09 '20 at 04:45
  • Done. I really appreciate the help on this. – cbates79 Sep 09 '20 at 04:52
  • Is `decrypt()` ever called before `myMethod()`? Since now you're initialising keySpec inside `myMethod()`, before it is called, keySpec would be null, and it is used in `decrypt()`. Editing in your `OnClickListener` from your main Activity, so we can see where these methods are called would help. – Luke Sykpe Sep 09 '20 at 05:03
  • Also, bit of a nitpick - `this` in expressions such as `this.cipher.init(2, this.keySpec);` is not wrong, but redundant. In Java `this` is used to refer to class/instance variables that share a name with local variables, and, in this case, there are no local variables named `cipher` or `keySpec` - only instance ones, making `this` unnecessary! – Luke Sykpe Sep 09 '20 at 05:06
  • I'm not 100% sure if decrypt() is called before myMethod. This is where my inexperience is kicking in. I've posted the code from MainActivity. Maybe that will tell you. Anything after " case R.id.exploit2:" can probably be ignored, as that's another exploit I'm trying to run. That will be another challenge, but I'll try to figure out that one on my own, as I think I can take what I learn from this and apply it there. Thanks for the info/tips you provided. I'll take note of that and apply it in the future. – cbates79 Sep 09 '20 at 05:16
  • Indeed, not only is `decrypt()` called before `myMethod()`, but, in fact, `myMethod()` is never called at all! As such, `md5key` is null. I'll edit my answer with the necessary changes to your main. – Luke Sykpe Sep 09 '20 at 06:42
  • That makes sense now looking at it. I made the change, but it gives me a different error. I thin it's almost working. Just a minor issue somewhere. I updated with the new logs. – cbates79 Sep 09 '20 at 12:19
  • 1
    You're passing `InputStreamReader` a null `InputStream`. You initialise it in the line `InputStream content = null;` as null, and never give it a value. Specifically, your `context.getContentResolver().openInputStream(targURI);` line should be `content = context.getContentResolver().openInputStream(targURI);` – Luke Sykpe Sep 09 '20 at 12:26
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/221209/discussion-between-luke-sykpe-and-cbates79). – Luke Sykpe Sep 09 '20 at 12:43
  • That was it!! Thank you so much. I have to do something similar in the other decrypt class, but with what I've learned from you, I think I can get that working following a similar approach. – cbates79 Sep 09 '20 at 13:27