// Path: app/src/main/java/com/reddyetwo/hashmypass/app/TwikApplication.java
// public class TwikApplication extends Application {
// 
//     public static final String LOG_TAG = "TWIK";
//     private char[] mCachedMasterKey;
//     private boolean mTutorialDismissed = false;
//     private static TwikApplication mInstance;
// 
//     @Override
//     public void onCreate() {
//         super.onCreate();
//         mInstance = this;
//         LeakCanary.install(this);
//     }
// 
//     /**
//      * Return the Singleton instance of the {@link android.app.Application}
//      * @return the Singleton instance of the {@link android.app.Application}
//      */
//     public static TwikApplication getInstance() {
//         return mInstance;
//     }
// 
//     /**
//      * Get the tutorial dismissed flag.
//      *
//      * @return true if the tutorial has been dismissed, false otherwise.
//      */
//     public boolean getTutorialDismissed() {
//         return mTutorialDismissed;
//     }
// 
//     /**
//      * Set the tutorial dismissed flag. Once the tutorial has been dismissed, it is never shown again.
//      *
//      * @param tutorialDismissed the flag value
//      */
//     public void setTutorialDismissed(boolean tutorialDismissed) {
//         mTutorialDismissed = tutorialDismissed;
//     }
// 
//     /**
//      * Get the cached master key
//      *
//      * @return the cached master key
//      */
//     public char[] getCachedMasterKey() {
//         if (mCachedMasterKey == null || Preferences.getRememberMasterKeyMins(this) == 0) {
//             mCachedMasterKey = new char[]{};
//         }
//         return mCachedMasterKey;
//     }
// 
//     /**
//      * Wipe the cached master key
//      */
//     public void wipeCachedMasterKey() {
//         if (mCachedMasterKey != null) {
//             Arrays.fill(mCachedMasterKey, ' ');
//             mCachedMasterKey = null;
//         }
//     }
// 
//     /**
//      * Save master key to cache if enabled by user
//      *
//      * @param masterKey the master key
//      */
//     public void cacheMasterKey(char[] masterKey) {
//         if (Preferences.getRememberMasterKeyMins(this) > 0) {
//             mCachedMasterKey = Arrays.copyOf(masterKey, masterKey.length);
//         }
//     }
// }
// 
// Path: app/src/main/java/com/reddyetwo/hashmypass/app/data/PasswordType.java
// public enum PasswordType {
//     ALPHANUMERIC_AND_SPECIAL_CHARS,
//     ALPHANUMERIC,
//     NUMERIC
// }
// 
// Path: app/src/main/java/com/reddyetwo/hashmypass/app/util/SecurePassword.java
// public class SecurePassword {
// 
//     private SecurePassword() {
// 
//     }
// 
//     /**
//      * Get the password stored in an {@link android.text.Editable} object
//      *
//      * @param s the {@link android.text.Editable} instance
//      * @return the password
//      */
//     public static char[] getPassword(Editable s) {
//         int length = s.length();
//         char[] password = new char[length];
//         for (int i = 0; i < length; i++) {
//             password[i] = s.charAt(i);
//         }
//         return password;
//     }
// 
//     /**
//      * Convert a password stored as a char array to a byte array
//      *
//      * @param chars the password as a char array
//      * @return the password as a byte array
//      */
//     public static byte[] toBytes(char[] chars) {
//         CharBuffer charBuffer = CharBuffer.wrap(chars);
//         ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
//         byte[] bytes =
//                 Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
// 
//         // Clear sensitive data
//         Arrays.fill(charBuffer.array(), '\u0000');
//         Arrays.fill(byteBuffer.array(), (byte) 0);
//         return bytes;
//     }
// }


import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
import android.util.Log;
import com.reddyetwo.hashmypass.app.TwikApplication;
import com.reddyetwo.hashmypass.app.data.PasswordType;
import com.reddyetwo.hashmypass.app.util.SecurePassword;
/*
 * Copyright 2014 Red Dye No. 2
 * Copyright (C) 2011-2013 TG Byte Software GmbH
 * Copyright (C) 2009-2011 Thilo-Alexander Ginkel.
 * Copyright (C) 2010-2014 Eric Woodruff
 * Copyright (C) 2006-2010 Steve Cooper
 *
 * This file is part of Twik.
 *
 * Twik is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Twik is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Twik.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.reddyetwo.hashmypass.app.hash;





/**
 * Generator of hashed passwords
 */
public class PasswordHasher {

    /**
     * Keyed-hash message authentication code (HMAC) used
     */
    private static final String HMAC_SHA1 = "HmacSHA1";

    /**
     * Message digest used to calculate key digest
     */
    private static final String DIGEST_MD5 = "MD5";

    private static final int INJECT_RESERVED = 4;
    private static final int INJECT_NUMBER_OF_NUMERIC_CHARS = 10;
    private static final int INJECT_NUMBER_OF_SPECIAL_CHARS = 15;
    private static final int INJECT_NUMBER_OF_ALPHA_CHARS = 26;
    private static final int INJECT_OFFSET_NUMERIC = 0;
    private static final int INJECT_OFFSET_SPECIAL = 1;
    private static final int INJECT_OFFSET_ALPHA_UPPERCASE = 2;
    private static final int INJECT_OFFSET_ALPHA_LOWERCASE = 3;
    private static final int INTERMEDIATE_HASH_SIZE = 24;

    private PasswordHasher() {

    }

// Path: app/src/main/java/com/reddyetwo/hashmypass/app/TwikApplication.java
// public class TwikApplication extends Application {
// 
//     public static final String LOG_TAG = "TWIK";
//     private char[] mCachedMasterKey;
//     private boolean mTutorialDismissed = false;
//     private static TwikApplication mInstance;
// 
//     @Override
//     public void onCreate() {
//         super.onCreate();
//         mInstance = this;
//         LeakCanary.install(this);
//     }
// 
//     /**
//      * Return the Singleton instance of the {@link android.app.Application}
//      * @return the Singleton instance of the {@link android.app.Application}
//      */
//     public static TwikApplication getInstance() {
//         return mInstance;
//     }
// 
//     /**
//      * Get the tutorial dismissed flag.
//      *
//      * @return true if the tutorial has been dismissed, false otherwise.
//      */
//     public boolean getTutorialDismissed() {
//         return mTutorialDismissed;
//     }
// 
//     /**
//      * Set the tutorial dismissed flag. Once the tutorial has been dismissed, it is never shown again.
//      *
//      * @param tutorialDismissed the flag value
//      */
//     public void setTutorialDismissed(boolean tutorialDismissed) {
//         mTutorialDismissed = tutorialDismissed;
//     }
// 
//     /**
//      * Get the cached master key
//      *
//      * @return the cached master key
//      */
//     public char[] getCachedMasterKey() {
//         if (mCachedMasterKey == null || Preferences.getRememberMasterKeyMins(this) == 0) {
//             mCachedMasterKey = new char[]{};
//         }
//         return mCachedMasterKey;
//     }
// 
//     /**
//      * Wipe the cached master key
//      */
//     public void wipeCachedMasterKey() {
//         if (mCachedMasterKey != null) {
//             Arrays.fill(mCachedMasterKey, ' ');
//             mCachedMasterKey = null;
//         }
//     }
// 
//     /**
//      * Save master key to cache if enabled by user
//      *
//      * @param masterKey the master key
//      */
//     public void cacheMasterKey(char[] masterKey) {
//         if (Preferences.getRememberMasterKeyMins(this) > 0) {
//             mCachedMasterKey = Arrays.copyOf(masterKey, masterKey.length);
//         }
//     }
// }
// 
// Path: app/src/main/java/com/reddyetwo/hashmypass/app/data/PasswordType.java
// public enum PasswordType {
//     ALPHANUMERIC_AND_SPECIAL_CHARS,
//     ALPHANUMERIC,
//     NUMERIC
// }
// 
// Path: app/src/main/java/com/reddyetwo/hashmypass/app/util/SecurePassword.java
// public class SecurePassword {
// 
//     private SecurePassword() {
// 
//     }
// 
//     /**
//      * Get the password stored in an {@link android.text.Editable} object
//      *
//      * @param s the {@link android.text.Editable} instance
//      * @return the password
//      */
//     public static char[] getPassword(Editable s) {
//         int length = s.length();
//         char[] password = new char[length];
//         for (int i = 0; i < length; i++) {
//             password[i] = s.charAt(i);
//         }
//         return password;
//     }
// 
//     /**
//      * Convert a password stored as a char array to a byte array
//      *
//      * @param chars the password as a char array
//      * @return the password as a byte array
//      */
//     public static byte[] toBytes(char[] chars) {
//         CharBuffer charBuffer = CharBuffer.wrap(chars);
//         ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
//         byte[] bytes =
//                 Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
// 
//         // Clear sensitive data
//         Arrays.fill(charBuffer.array(), '\u0000');
//         Arrays.fill(byteBuffer.array(), (byte) 0);
//         return bytes;
//     }
// }


// Path: app/src/main/java/com/reddyetwo/hashmypass/app/hash/PasswordHasher.java
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
import android.util.Log;
import com.reddyetwo.hashmypass.app.TwikApplication;
import com.reddyetwo.hashmypass.app.data.PasswordType;
import com.reddyetwo.hashmypass.app.util.SecurePassword;

/*
 * Copyright 2014 Red Dye No. 2
 * Copyright (C) 2011-2013 TG Byte Software GmbH
 * Copyright (C) 2009-2011 Thilo-Alexander Ginkel.
 * Copyright (C) 2010-2014 Eric Woodruff
 * Copyright (C) 2006-2010 Steve Cooper
 *
 * This file is part of Twik.
 *
 * Twik is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Twik is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Twik.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.reddyetwo.hashmypass.app.hash;





/**
 * Generator of hashed passwords
 */
public class PasswordHasher {

    /**
     * Keyed-hash message authentication code (HMAC) used
     */
    private static final String HMAC_SHA1 = "HmacSHA1";

    /**
     * Message digest used to calculate key digest
     */
    private static final String DIGEST_MD5 = "MD5";

    private static final int INJECT_RESERVED = 4;
    private static final int INJECT_NUMBER_OF_NUMERIC_CHARS = 10;
    private static final int INJECT_NUMBER_OF_SPECIAL_CHARS = 15;
    private static final int INJECT_NUMBER_OF_ALPHA_CHARS = 26;
    private static final int INJECT_OFFSET_NUMERIC = 0;
    private static final int INJECT_OFFSET_SPECIAL = 1;
    private static final int INJECT_OFFSET_ALPHA_UPPERCASE = 2;
    private static final int INJECT_OFFSET_ALPHA_LOWERCASE = 3;
    private static final int INTERMEDIATE_HASH_SIZE = 24;

    private PasswordHasher() {

    }

    private static String hashKey(String tag, char[] key, int length, PasswordType type) {