de.ub0r.android.otpdroid.OTPdroid.java Source code

Java tutorial

Introduction

Here is the source code for de.ub0r.android.otpdroid.OTPdroid.java

Source

package de.ub0r.android.otpdroid;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.FragmentActivity;
import android.telephony.TelephonyManager;
import android.text.ClipboardManager;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;

import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

import de.ub0r.android.lib.Market;

/**
 * OTPdroid's main {@link FragmentActivity}.
 * 
 * @author flx
 */
public class OTPdroid extends SherlockActivity implements BeerLicense {
    /** Tag for output. */
    // private static final String TAG = "OTPdroid";

    /** Dialog: about. */
    private static final int DIALOG_ABOUT = 0;
    /** Dialog: update. */
    private static final int DIALOG_UPDATE = 1;

    /** Pref: save passphrase. */
    public static final String PREF_SAVEPASSPHRASE = "savePassphrase";
    /** Pref: encrypt passphrase with boot time. */
    public static final String PREF_ENCRYPTPASSPHRASEBYBOOTTIME = // .
            "encryptByBoottime";
    /** Pref: saved passphrase. */
    public static final String PREF_SAVEDPASSPHRASE = "passphrase";
    /** Pref: save challenge. */
    public static final String PREF_SAVECHALLENGE = "saveChallenge";
    /** Pref: saved challenge. */
    public static final String PREF_SAVEDCHALENGE = "challenge";
    /** Pref: saved sequence. */
    public static final String PREF_SAVEDSEQUENCE = "sequence";
    /** Pref: saved hash method. */
    public static final String PREF_SAVEDHASHMETHOD = "hashMethod";
    /** Pref: auto decrement sequence. */
    public static final String PREF_AUTODECREMENT = "autoDecrement";
    /** Pref: number of responses to print. */
    public static final String PREF_NUMBEROFRESPONSES = "numberOfResponses";
    /** Pref: show time. */
    public static final String PREF_SHOWTIME = "showTime";
    /** Pref: copy response. */
    public static final String PREF_COPYRESPONSE = "copyResponse";
    /** Preference's name: last version run. */
    private static final String PREFS_LAST_RUN = "lastrun";

    /** Phone's imei. */
    private String imei = null;
    /** Phone's simid. */
    private String simid = null;

    /** EditText for passphrase. */
    private EditText passphrase;
    /** Spinner for hash method. */
    private Spinner hashMethod;
    /** EditText for count. */
    private EditText sequence;
    /** EditText for challenge. */
    private EditText challenge;
    /** EditText for response. */
    private EditText response;

    /** {@link MenuItem} showing calculation button. */
    private MenuItem miCalc = null;

    /** Did user pressed the calc button? */
    private static boolean didCalc;

    /**
     * {@inheritDoc}
     */
    @Override
    public final void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.main);

        this.passphrase = (EditText) this.findViewById(R.id.passphrase);
        this.hashMethod = (Spinner) this.findViewById(R.id.hash_method);
        this.sequence = (EditText) this.findViewById(R.id.sequence);
        this.challenge = (EditText) this.findViewById(R.id.challenge);
        this.response = (EditText) this.findViewById(R.id.response);

        final ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.hash_methods,
                android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(// .
                android.R.layout.simple_spinner_dropdown_item);
        this.hashMethod.setAdapter(adapter);

        if (this.imei == null || this.simid == null) {
            this.loadKeys();
        }

        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
        final String v0 = settings.getString(PREFS_LAST_RUN, "");
        final String v1 = this.getString(R.string.app_version);
        if (!v0.equals(v1)) {
            final SharedPreferences.Editor editor = settings.edit();
            editor.putString(PREFS_LAST_RUN, v1);
            editor.commit();
            this.showDialog(DIALOG_UPDATE);
        }
        this.loadPassphrase(settings);

        didCalc = false;
        this.decrementSequence();
    }

    /**
     * Switch to previous sequence.
     */
    private void prev() {
        this.response.setText("");
        try {
            final int seq = Integer.parseInt(this.sequence.getText().toString());
            this.sequence.setText(String.valueOf(seq - 1));
        } catch (Exception e) {
            this.response.setText(R.string.error_input);
        }
    }

    /**
     * Switch to next sequence.
     */
    private void next() {
        this.response.setText("");
        try {
            final int seq = Integer.parseInt(this.sequence.getText().toString());
            this.sequence.setText(String.valueOf(seq + 1));
        } catch (Exception e) {
            this.response.setText(R.string.error_input);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected final void onResume() {
        super.onResume();
        if (OTPdroid.didCalc) {
            this.decrementSequence();
        }
    }

    /**
     * Decrement sequence.
     */
    private void decrementSequence() {
        this.response.setText("");
        final SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(this);
        if (p.getBoolean(PREF_AUTODECREMENT, false)) {
            final String s = this.sequence.getText().toString();
            if (s.length() > 0) {
                final int i = Integer.parseInt(s);
                OTPdroid.this.sequence.setText("" + (i - 1));
            }
        }
        OTPdroid.didCalc = false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final boolean onCreateOptionsMenu(final Menu menu) {
        this.getSupportMenuInflater().inflate(R.menu.menu, menu);
        this.miCalc = menu.findItem(R.id.item_calculate);
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final boolean onOptionsItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
        case R.id.item_calculate:
            OTPdroid.this.calc();
            OTPdroid.didCalc = true;
            return true;
        case R.id.item_prev:
            this.prev();
            return true;
        case R.id.item_next:
            this.next();
            return true;
        case R.id.item_about: // start about dialog
            this.showDialog(DIALOG_ABOUT);
            return true;
        case R.id.item_settings: // start settings activity
            this.startActivity(new Intent(this, Preferences.class));
            return true;
        case R.id.item_more:
            Market.searchApp(this, "Felix+Bechstein", "http://code.google.com/u" + "/felix.bechstein/");
            return true;
        default:
            return false;
        }
    }

    /**
     * Calculate the response.
     */
    @SuppressWarnings("deprecation")
    private void calc() {
        final SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(this);
        int n;
        try {
            n = Integer.parseInt(p.getString(PREF_NUMBEROFRESPONSES, "1"));
        } catch (NumberFormatException e) {
            n = 1;
        }
        final int numberOfResponses = n;
        final boolean showTime = p.getBoolean(PREF_SHOWTIME, true);
        final boolean copyResponse = p.getBoolean(PREF_COPYRESPONSE, true);
        final String eol = System.getProperty("line.separator");
        final ClipboardManager cbmgr = (ClipboardManager) this.getSystemService(CLIPBOARD_SERVICE);

        byte algo = 0x00;

        switch ((int) this.hashMethod.getSelectedItemId()) {
        case 0:
            algo = Otp.SHA1;
            break;
        case 1:
            algo = Otp.MD5;
            break;
        case 2:
            algo = Otp.MD4;
            break;
        default:
            algo = Otp.SHA1;
            break;
        }
        final byte falgo = algo;
        new AsyncTask<Void, Void, String>() {
            private Dialog d = null;

            @Override
            protected String doInBackground(final Void... arg0) {
                try {
                    final long startTime = System.currentTimeMillis();
                    int seq = Integer.parseInt(OTPdroid.this.sequence.getText().toString());
                    String finalResponse = "";
                    for (int i = 0; i < numberOfResponses && seq >= 0; i++) {
                        final String seed = OTPdroid.this.challenge.getText().toString().toLowerCase();
                        final String pass = OTPdroid.this.passphrase.getText().toString();

                        final Otp otpwd = new Otp(seq, seed, pass, falgo);
                        otpwd.calc();
                        if (copyResponse && i == 0) {
                            cbmgr.setText(otpwd.toString());
                        }

                        if (numberOfResponses == 1) {
                            finalResponse += otpwd.toString() + eol;
                        } else {
                            finalResponse += seq + ": " + otpwd.toString() + eol;
                            seq--;
                        }
                    }
                    if (showTime) {
                        finalResponse += OTPdroid.this.getString(R.string.generated_in) + " "
                                + (System.currentTimeMillis() - startTime) / 1000F + " "
                                + OTPdroid.this.getString(R.string.seconds);
                    }
                    return finalResponse;
                } catch (Exception e) {
                    return null;
                }
            }

            @Override
            protected void onPreExecute() {
                this.d = ProgressDialog.show(OTPdroid.this, null, OTPdroid.this.getString(R.string.please_wait_),
                        false);

                if (OTPdroid.this.miCalc != null) {
                    OTPdroid.this.miCalc.setEnabled(false);
                }
            }

            @Override
            protected void onPostExecute(final String result) {
                if (result == null) {
                    OTPdroid.this.response.setText(R.string.error_input);
                } else {
                    OTPdroid.this.response.setText(result);
                }
                if (OTPdroid.this.miCalc != null) {
                    OTPdroid.this.miCalc.setEnabled(true);
                }
                if (this.d != null) {
                    this.d.cancel();
                }
            }

        } // .
                .execute((Void) null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected final void onStop() {
        super.onStop();

        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
        final Editor editor = settings.edit();

        final boolean savePassphrase = settings.getBoolean(OTPdroid.PREF_SAVEPASSPHRASE, false);
        final boolean saveSequence = settings.getBoolean(OTPdroid.PREF_SAVECHALLENGE, false);

        this.savePassphrase(editor, savePassphrase, saveSequence);

        editor.commit();
    }

    /**
     * Load passphrase from preferences.
     * 
     * @param settings
     *            preferences
     */
    private void loadPassphrase(final SharedPreferences settings) {
        AES aes;
        int l;

        aes = new AES();
        aes.genKey((this.imei + this.simid).getBytes());
        aes.setInputBase64(settings.getString(OTPdroid.PREF_SAVEDPASSPHRASE, ""));
        l = aes.decrypt();
        if (l > 0) {
            this.passphrase.setText(new String(aes.getOutput()));
            this.sequence.requestFocus();
        }

        aes = new AES();
        aes.genKey((this.imei + this.simid).getBytes());
        aes.setInputBase64(settings.getString(OTPdroid.PREF_SAVEDHASHMETHOD, ""));
        l = aes.decrypt();
        if (l > 0) {
            this.hashMethod.setSelection(Integer.parseInt(new String(aes.getOutput())));
        }

        aes = new AES();
        aes.genKey((this.imei + this.simid).getBytes());
        aes.setInputBase64(settings.getString(OTPdroid.PREF_SAVEDSEQUENCE, ""));
        l = aes.decrypt();
        if (l > 0) {
            this.sequence.setText(new String(aes.getOutput()));
            this.challenge.requestFocus();
        }

        aes = new AES();
        aes.genKey((this.imei + this.simid).getBytes());
        aes.setInputBase64(settings.getString(OTPdroid.PREF_SAVEDCHALENGE, ""));
        l = aes.decrypt();
        if (l > 0) {
            this.challenge.setText(new String(aes.getOutput()));
        }
    }

    /**
     * Save passphrase to preferences.
     * 
     * @param savePassphrase
     *            save passphase
     * @param saveChallange
     *            save challange
     * @param editor
     *            editor
     */
    private void savePassphrase(final Editor editor, final boolean savePassphrase, final boolean saveChallange) {
        if (!savePassphrase && !saveChallange) {
            editor.remove(PREF_SAVEDPASSPHRASE);
            editor.remove(PREF_SAVEDHASHMETHOD);
            editor.remove(PREF_SAVEDSEQUENCE);
            editor.remove(PREF_SAVEDCHALENGE);
            return;
        }
        AES aes;
        int l;

        if (savePassphrase) {
            aes = new AES();
            aes.genKey((this.imei + this.simid).getBytes());
            aes.setInput(this.passphrase.getText().toString().getBytes());
            l = aes.encrypt();
            if (l > -1) {
                editor.putString(PREF_SAVEDPASSPHRASE, aes.getOutputBase64());
            }
        } else {
            editor.remove(PREF_SAVEDPASSPHRASE);
        }

        if (saveChallange) {
            aes = new AES();
            aes.genKey((this.imei + this.simid).getBytes());
            aes.setInput((this.hashMethod.getSelectedItemId() + "").getBytes());
            l = aes.encrypt();
            if (l > -1) {
                editor.putString(PREF_SAVEDHASHMETHOD, aes.getOutputBase64());
            }

            aes = new AES();
            aes.genKey((this.imei + this.simid).getBytes());
            aes.setInput(this.sequence.getText().toString().getBytes());
            l = aes.encrypt();
            if (l > -1) {
                editor.putString(PREF_SAVEDSEQUENCE, aes.getOutputBase64());
            }

            aes = new AES();
            aes.genKey((this.imei + this.simid).getBytes());
            aes.setInput(this.challenge.getText().toString().getBytes());
            l = aes.encrypt();

            if (l > -1) {
                editor.putString(PREF_SAVEDCHALENGE, aes.getOutputBase64());
            }
        } else {
            editor.remove(PREF_SAVEDHASHMETHOD);
            editor.remove(PREF_SAVEDSEQUENCE);
            editor.remove(PREF_SAVEDCHALENGE);
        }
    }

    /**
     * Load IMEI and SIMID from phone.
     */
    private void loadKeys() {
        TelephonyManager phone = (TelephonyManager) this.getApplicationContext()
                .getSystemService(Context.TELEPHONY_SERVICE);

        this.imei = phone.getDeviceId();
        this.simid = phone.getSimSerialNumber();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected final Dialog onCreateDialog(final int id) {
        AlertDialog.Builder builder;
        switch (id) {
        case DIALOG_ABOUT:
            builder = new AlertDialog.Builder(this);
            builder.setTitle(this.getString(R.string.about_) + " v" + this.getString(R.string.app_version));
            builder.setPositiveButton(android.R.string.ok, null);
            builder.setView(View.inflate(this, R.layout.about, null));
            return builder.create();
        case DIALOG_UPDATE:
            builder = new AlertDialog.Builder(this);
            builder.setTitle(R.string.changelog_);
            final String[] changes = this.getResources().getStringArray(R.array.updates);
            final StringBuilder buf = new StringBuilder(changes[0]);
            for (int i = 1; i < changes.length; i++) {
                buf.append("\n\n");
                buf.append(changes[i]);
            }
            builder.setIcon(android.R.drawable.ic_menu_info_details);
            builder.setMessage(buf.toString());
            builder.setCancelable(true);
            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(final DialogInterface dialog, final int id) {
                    dialog.cancel();
                }
            });
            return builder.create();
        default:
            return null;
        }
    }
}