// 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;

        String hash = Base64.encodeToString(hmac.doFinal(tag.getBytes()),
                Base64.NO_PADDING | Base64.NO_WRAP);

        int sum = 0;
        for (int i = 0; i < hash.length(); i++) {
            sum += hash.charAt(i);
        }

        /* Parse password to match the request type */
        if (type == PasswordType.NUMERIC) {
            hash = convertToDigits(hash, sum, length);
        } else {
            /* We force digits, punctuation characters and mixed case in
            order to provide compatibility with the Chrome extension */
            // Force digits
            hash = injectCharacter(hash, INJECT_OFFSET_NUMERIC, INJECT_RESERVED, sum, length, '0',
                    INJECT_NUMBER_OF_NUMERIC_CHARS);
            if (type == PasswordType.ALPHANUMERIC_AND_SPECIAL_CHARS) {
                // Force special chars
                hash = injectCharacter(hash, INJECT_OFFSET_SPECIAL, INJECT_RESERVED, sum, length,
                        '!', INJECT_NUMBER_OF_SPECIAL_CHARS);
            }
            // Force mixed case
            hash = injectCharacter(hash, INJECT_OFFSET_ALPHA_UPPERCASE, INJECT_RESERVED, sum,
                    length, 'A', INJECT_NUMBER_OF_ALPHA_CHARS);
            hash = injectCharacter(hash, INJECT_OFFSET_ALPHA_LOWERCASE, INJECT_RESERVED, sum,
                    length, 'a', INJECT_NUMBER_OF_ALPHA_CHARS);

            // Remove special chars if needed
// 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;


        String hash = Base64.encodeToString(hmac.doFinal(tag.getBytes()),
                Base64.NO_PADDING | Base64.NO_WRAP);

        int sum = 0;
        for (int i = 0; i < hash.length(); i++) {
            sum += hash.charAt(i);
        }

        /* Parse password to match the request type */
        if (type == PasswordType.NUMERIC) {
            hash = convertToDigits(hash, sum, length);
        } else {
            /* We force digits, punctuation characters and mixed case in
            order to provide compatibility with the Chrome extension */
            // Force digits
            hash = injectCharacter(hash, INJECT_OFFSET_NUMERIC, INJECT_RESERVED, sum, length, '0',
                    INJECT_NUMBER_OF_NUMERIC_CHARS);
            if (type == PasswordType.ALPHANUMERIC_AND_SPECIAL_CHARS) {
                // Force special chars
                hash = injectCharacter(hash, INJECT_OFFSET_SPECIAL, INJECT_RESERVED, sum, length,
                        '!', INJECT_NUMBER_OF_SPECIAL_CHARS);
            }
            // Force mixed case
            hash = injectCharacter(hash, INJECT_OFFSET_ALPHA_UPPERCASE, INJECT_RESERVED, sum,
                    length, 'A', INJECT_NUMBER_OF_ALPHA_CHARS);
            hash = injectCharacter(hash, INJECT_OFFSET_ALPHA_LOWERCASE, INJECT_RESERVED, sum,
                    length, 'a', INJECT_NUMBER_OF_ALPHA_CHARS);

            // Remove special chars if needed
            if (type == PasswordType.ALPHANUMERIC) {