0

Im trying to implement fingerprint authentication inside app. while initializing KeyGenerator .it showing this error.

  protected void generateKey() {
    try {
        keyStore = KeyStore.getInstance("AndroidKeyStore");
    } catch (Exception e) {
        e.printStackTrace();
    }

    try {
        keyGenerator = KeyGenerator.getInstance(
                          KeyProperties.KEY_ALGORITHM_AES, 
                          "AndroidKeyStore");
    } catch (NoSuchAlgorithmException | 
                    NoSuchProviderException e) {
        throw new RuntimeException(
        "Failed to get KeyGenerator instance", e);
    }

    try {
        keyStore.load(null);
        keyGenerator.init(new  
           KeyGenParameterSpec.Builder(KEY_NAME,
                KeyProperties.PURPOSE_ENCRYPT |
                KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setEncryptionPaddings(
                     KeyProperties.ENCRYPTION_PADDING_PKCS7)
                        .build());
        keyGenerator.generateKey();
    } catch (NoSuchAlgorithmException | 
              InvalidAlgorithmParameterException
            | CertificateException | IOException e) {
        throw new RuntimeException(e);
    }

Error:'KeyGenParameterSpec()' is not public in 'android.security.keystore.KeyGenParameterSpec'. Cannot be accessed from outside package

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Ragavendra M
  • 442
  • 5
  • 15

1 Answers1

0

Below are two classes which you can use to authenticate with finger print. Their will be minor issues like permsission handling or any import. but this is working code of finger print authentication. FingerPrintHandler class

import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.Manifest;
import android.os.Build;
import android.os.CancellationSignal;
import android.support.v4.app.ActivityCompat;

import yasiriqbal.ethereum.R;
import yasiriqbal.ethereum.util.SessionManager;

@TargetApi(Build.VERSION_CODES.M)
public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
// You should use the CancellationSignal method whenever your app can no longer process user input, for example when your app goes
// into the background. If you don’t use this method, then other apps will be unable to access the touch sensor, including the lockscreen!//

private CancellationSignal cancellationSignal;
private Context context;

public FingerprintHandler(Context mContext) {
    context = mContext;
}

//Implement the startAuth method, which is responsible for starting the fingerprint authentication process//

public void startAuth(FingerprintManager manager, FingerprintManager.CryptoObject cryptoObject) {

    cancellationSignal = new CancellationSignal();
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    manager.authenticate(cryptoObject, cancellationSignal, 0, this, null);
}

public void StopListener() {
    try {
        if (cancellationSignal != null)
            cancellationSignal.cancel();
        cancellationSignal = null;
    }catch (Exception e)
    {}

}

@Override
//onAuthenticationError is called when a fatal error has occurred. It provides the error code and error message as its parameters//

public void onAuthenticationError(int errMsgId, CharSequence errString) {

    //I’m going to display the results of fingerprint authentication as a series of toasts.
    //Here, I’m creating the message that’ll be displayed if an error occurs//

}

@Override

//onAuthenticationFailed is called when the fingerprint doesn’t match with any of the fingerprints registered on the device//

public void onAuthenticationFailed() {
}

@Override

//onAuthenticationHelp is called when a non-fatal error has occurred. This method provides additional information about the error,
//so to provide the user with as much feedback as possible I’m incorporating this information into my toast//
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
}

@Override

//onAuthenticationSucceeded is called when a fingerprint has been successfully matched to one of the fingerprints stored on the user’s device//
public void onAuthenticationSucceeded(
        FingerprintManager.AuthenticationResult result) {

    if (new SessionManager(context).getUsername() != null && !new SessionManager(context).getUsername().isEmpty()) {
        String userName = new SessionManager(context).getUsername();
        String pass = new SessionManager(context).getPass();

        if (pass != null) {
            ((SigninActivity) context).requestLoginToServer(userName, pass);
            ((SigninActivity) context).isSignInButtonClicked = false;
        }
    }
    //context.startActivity(new Intent(context, DashboardActivity.class));
}

}

Signin Class

import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Handler;
import android.provider.ContactsContract;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.widget.AppCompatTextView;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.method.PasswordTransformationMethod;
import android.text.style.ForegroundColorSpan;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.gson.Gson;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

import yasiriqbal.ethereum.EthereumApplication;
import yasiriqbal.ethereum.PermissionActivity;
import yasiriqbal.ethereum.R;
import yasiriqbal.ethereum.dashboad.DashboardActivity;
import yasiriqbal.ethereum.models.EthUserModel;
import yasiriqbal.ethereum.models.ServerMessage;
import yasiriqbal.ethereum.network.VolleyRequestHelper;
import yasiriqbal.ethereum.settings.ChangePasswordActivity;
import yasiriqbal.ethereum.signup.MobileCodeVerifyActivity;
import yasiriqbal.ethereum.signup.MobileNumberActivity;
import yasiriqbal.ethereum.signup.SignUpActivity;
import yasiriqbal.ethereum.util.Constants;
import yasiriqbal.ethereum.util.DialogErrorFragment;
import yasiriqbal.ethereum.util.DialogHelper;
import yasiriqbal.ethereum.util.Fonts;
import yasiriqbal.ethereum.util.MyUtils;
import yasiriqbal.ethereum.util.PermissionHandler;
import yasiriqbal.ethereum.util.SessionManager;

public class SigninActivity extends AccountAuthenticatorActivity implements View.OnClickListener, Response.Listener<JSONObject>, Response.ErrorListener {

    public static final String PARAM_USER_PASS = "userpassword";
    private static final int CODE_EMAIL_NOT_VERIFIED = 408;
    private AppCompatTextView txt_loginscreen_not_register_member, txt_loginscreen_header,
            txt_loginscreen_forgetpassword, txt_loginscreen_touchid;
    private TextInputEditText edit_loginscreen_username, edit_loginscreen_password;
    Button btn_loginscreen_signin;
    PermissionHandler permissionHandler;
    private TextInputLayout layout_loginscreen_password, layout_loginscreen_username;
    private KeyStore keyStore;
    private Cipher cipher;

    private final int CODE_WRONG_PASSWORD = 401;
    private final int CODE_INVALID_USER = 400;
    private final int CODE_LOGIN_SUCCESS = 200;
    public final int CODE_PROFILE_STATUS_COMPLETE = 2;
    public final int CODE_MOBILE_NOT_VERIFY = 1;
    private DialogHelper dialogHelper;
    private final int ACCOUNT_PERMISSION_ID = 1234;
    boolean isFromSetting = false;
    private static final String KEY_NAME = "ethereum";
    private Typeface qanelasRegularTypeFace;
    private Typeface qanelasSemiBoldTypeFace;
    private String previousUserName = "";
    FingerprintHandler handler;
    FingerprintManager mFingerprintManager;
    public boolean isSignInButtonClicked = false;
    FingerprintManager.CryptoObject cryptoObject;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sign_in);
        if (permissionHandler.isMarshMallow()) {
            authenticateWithFingerPrint();
            if (permissionHandler.isPermissionAvailable(Manifest.permission.USE_FINGERPRINT)) {
                setFingerprintConfig();
            } else {
                permissionHandler.requestPermission(Manifest.permission.USE_FINGERPRINT);
            }
        }//end of if is marshmallow


        //dialogErrorFragment.show(getFragmentManager(),"dialog");
    }//end of onCreate


    @TargetApi(Build.VERSION_CODES.M)
    private void authenticateWithFingerPrint() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        mFingerprintManager = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);
        if (mFingerprintManager.isHardwareDetected()) {
            KeyguardManager mKeyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
            if (mKeyguardManager.isKeyguardSecure()) {
                generateKey();
                if (initCipher()) {
                    cryptoObject = new FingerprintManager.CryptoObject(cipher);
                    handler = new FingerprintHandler(this);
                    handler.startAuth(mFingerprintManager, cryptoObject);
                }
            } else {
                Toast.makeText(this, "Lock Screen Security not enabled in Settings.", Toast.LENGTH_LONG).show();
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    protected void generateKey() {
        try {
            keyStore = KeyStore.getInstance("AndroidKeyStore");
        } catch (Exception e) {
            e.printStackTrace();
        }


        KeyGenerator keyGenerator;
        try {
            keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
            throw new RuntimeException("Failed to get KeyGenerator instance", e);
        }


        try {
            keyStore.load(null);
            keyGenerator.init(new
                    KeyGenParameterSpec.Builder(KEY_NAME,
                    KeyProperties.PURPOSE_ENCRYPT |
                            KeyProperties.PURPOSE_DECRYPT)
                    .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                    .setUserAuthenticationRequired(true)
                    .setEncryptionPaddings(
                            KeyProperties.ENCRYPTION_PADDING_PKCS7)
                    .build());
            keyGenerator.generateKey();
        } catch (NoSuchAlgorithmException |
                InvalidAlgorithmParameterException
                | CertificateException | IOException e) {
            throw new RuntimeException(e);
        }
    }


    //Create a new method that we’ll use to initialize our cipher//
    @TargetApi(Build.VERSION_CODES.M)
    public boolean initCipher() {
        try {
            //Obtain a cipher instance and configure it with the properties required for fingerprint authentication//
            cipher = Cipher.getInstance(
                    KeyProperties.KEY_ALGORITHM_AES + "/"
                            + KeyProperties.BLOCK_MODE_CBC + "/"
                            + KeyProperties.ENCRYPTION_PADDING_PKCS7);
        } catch (NoSuchAlgorithmException |
                NoSuchPaddingException e) {
            throw new RuntimeException("Failed to get Cipher", e);
        }

        try {
            keyStore.load(null);
            SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
                    null);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //Return true if the cipher has been initialized successfully//
            return true;
        } catch (KeyPermanentlyInvalidatedException e) {

            //Return false if cipher initialization failed//
            return false;
        } catch (KeyStoreException | CertificateException
                | UnrecoverableKeyException | IOException
                | NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("Failed to init Cipher", e);
        }
    }



    //xml initalization
    private void initResources() {
        //textViews initalize


    }//end of initResources

    @Override
    protected void onResume() {
        super.onResume();

    }//end of onResume

    //here to discover fingerprint hardware and set views
    @TargetApi(Build.VERSION_CODES.M)
    @SuppressWarnings("MissingPermission")
    private void setFingerprintConfig() {
        FingerprintManager mFingerprintManager = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);
        if (mFingerprintManager.isHardwareDetected()) {
            if (getPreviousUsername() != null && !getPreviousUsername().isEmpty() && mFingerprintManager.hasEnrolledFingerprints()) {
              //TODO show finger print icon that this device support
            } else {
                //here means user is not enrolled for fingerpring
                //TODO handle case when fingerprint not supported
            }
        }
    }//end of setFingerprint

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (permissionHandler.PERMISSIONS_REQUEST == requestCode && grantResults.length > 0 && grantResults[0] > -1) {
            setFingerprintConfig();
        }
    }

    //onclick reciver for signin activity
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            default:
                throw new IllegalArgumentException(v.getId() + " is not handle in onclick of signing activity");
        }//end f switch
    }//end of onClick

    @Override
    protected void onPause() {
        super.onPause();

    }



    //here check if user profile complete then redirect to dashboard or then mobile verify
    private void redirectUserAfterSuccessLogin(String data) throws JSONException {
        if (!data.isEmpty()) {
            Gson gsonForUser = new Gson();
            new SessionManager(this).adToken(new JSONObject(data).getString("authenticationToken"));
            EthUserModel ethUserModel = gsonForUser.fromJson(data, EthUserModel.class);
            EthereumApplication.getInstance().setEthUserLoginObj(ethUserModel);
            insertEthUserToContentProvider(ethUserModel);

            if (!previousUserName.equals(ethUserModel.getEthUserName()) && !removeAccountFromAccountManager(ethUserModel, edit_loginscreen_password.getText().toString())) {
                addAccountToAuthenticator(ethUserModel, edit_loginscreen_password.getText().toString());
                startOtherActivity(ethUserModel);
                //startSyncAdapter();
            }//end of if for removeAccount return false
            else {

                startOtherActivity(ethUserModel);
                //startSyncAdapter();

            }//end of else

        } else {
            //here to show retry login
        }

    }//end of function


    private void startOtherActivity(EthUserModel ethUserModel) {
        if (isSignInButtonClicked)
            new SessionManager(this).addData(edit_loginscreen_username.getText().toString(), edit_loginscreen_password.getText().toString());
        if (txt_loginscreen_touchid.getVisibility() == View.VISIBLE)
            try {
                handler.StopListener();
            } catch (Exception e) {
            }
        if (ethUserModel.getProfileStatus() == CODE_MOBILE_NOT_VERIFY) {
            //redirect to mobile screen
            startActivity(new Intent(this, MobileNumberActivity.class));
        } else {
            //redirect to dashboard if user not from setting
            if (!getIntent().getBooleanExtra(Constants.ARG_IS_USER_FROM_SETTING, false)) {
                if (EthereumApplication.getInstance().getEthUserLoginObj().getEthUserDoubleAuthenticationStatus() == Constants.ResultCode.CODE_DOUBLE_AUTHENTICATION_TRUE)
                    startActivity(new Intent(this, MobileCodeVerifyActivity.class)
                            .putExtra(Constants.MobileCodeVerifyActivity.IS_FROM_SIGNIN, true)
                            .putExtra(Constants.MobileNumberActivity.EXTRA_MOBILE_NUMBER, EthereumApplication.getInstance().getEthUserLoginObj().getMobileNum()));
                else
                    startActivity(new Intent(this, DashboardActivity.class));
                finish();
            }
        }//end of else
    }//end of function




    @Override
    protected void onStop() {
        super.onStop();

    }






}//end of activity
yasiriqbal776
  • 406
  • 3
  • 15