First step
This commit is contained in:
parent
9cacb7a380
commit
c199732fa4
@ -4,7 +4,7 @@ android {
|
|||||||
compileSdkVersion 26
|
compileSdkVersion 26
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.nauk.coinfolio"
|
applicationId "com.nauk.coinfolio"
|
||||||
minSdkVersion 21
|
minSdkVersion 23
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
@ -41,6 +41,7 @@ dependencies {
|
|||||||
implementation 'com.squareup.retrofit2:converter-jackson:2.2.0'
|
implementation 'com.squareup.retrofit2:converter-jackson:2.2.0'
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'
|
implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'
|
||||||
implementation 'org.apache.commons:commons-lang3:3.6'
|
implementation 'org.apache.commons:commons-lang3:3.6'
|
||||||
|
implementation 'com.mattprecious.swirl:swirl:1.1.0'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.1'
|
androidTestImplementation 'com.android.support.test:runner:1.0.1'
|
||||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.nauk.coinfolio">
|
package="com.nauk.coinfolio">
|
||||||
|
|
||||||
|
<uses-feature android:name="android.hardware.fingerprint"
|
||||||
|
android:required="false"/>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
package com.nauk.coinfolio.Activities;
|
package com.nauk.coinfolio.Activities;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.KeyguardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
import android.media.Ringtone;
|
import android.media.Ringtone;
|
||||||
import android.media.RingtoneManager;
|
import android.media.RingtoneManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -15,14 +19,35 @@ import android.preference.PreferenceActivity;
|
|||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.preference.RingtonePreference;
|
import android.preference.RingtonePreference;
|
||||||
|
import android.security.keystore.KeyGenParameterSpec;
|
||||||
|
import android.security.keystore.KeyPermanentlyInvalidatedException;
|
||||||
|
import android.security.keystore.KeyProperties;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.nauk.coinfolio.FingerprintHelper.FingerprintHandler;
|
||||||
import com.nauk.coinfolio.R;
|
import com.nauk.coinfolio.R;
|
||||||
|
|
||||||
|
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.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link PreferenceActivity} that presents a set of application settings. On
|
* A {@link PreferenceActivity} that presents a set of application settings. On
|
||||||
* handset devices, settings are presented as a single list. On tablets,
|
* handset devices, settings are presented as a single list. On tablets,
|
||||||
@ -36,6 +61,14 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class SettingsActivity extends AppCompatPreferenceActivity {
|
public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||||
|
|
||||||
|
private static final String KEY_NAME = "NAUKEY";
|
||||||
|
private Cipher cipher;
|
||||||
|
private KeyStore keyStore;
|
||||||
|
private KeyGenerator keyGenerator;
|
||||||
|
private FingerprintManager.CryptoObject cryptoObject;
|
||||||
|
private FingerprintManager fingerprintManager;
|
||||||
|
private KeyguardManager keyguardManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A preference value change listener that updates the preference's summary
|
* A preference value change listener that updates the preference's summary
|
||||||
* to reflect its new value.
|
* to reflect its new value.
|
||||||
@ -131,6 +164,105 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setupActionBar();
|
setupActionBar();
|
||||||
|
|
||||||
|
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||||
|
{
|
||||||
|
keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
|
||||||
|
fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
|
||||||
|
|
||||||
|
if(!fingerprintManager.isHardwareDetected())
|
||||||
|
{
|
||||||
|
findViewById(R.id.fingerprint_switch).setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED)
|
||||||
|
{
|
||||||
|
findViewById(R.id.fingerprint_switch).setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!fingerprintManager.hasEnrolledFingerprints())
|
||||||
|
{
|
||||||
|
findViewById(R.id.fingerprint_switch).setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!keyguardManager.isKeyguardSecure())
|
||||||
|
{
|
||||||
|
findViewById(R.id.fingerprint_switch).setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
generateKey();
|
||||||
|
} catch (FingerprintException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(initCipher())
|
||||||
|
{
|
||||||
|
cryptoObject = new FingerprintManager.CryptoObject(cipher);
|
||||||
|
|
||||||
|
FingerprintHandler helper = new FingerprintHandler(this);
|
||||||
|
helper.startAuth(fingerprintManager, cryptoObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateKey() throws FingerprintException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||||
|
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
|
||||||
|
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 (KeyStoreException
|
||||||
|
| NoSuchAlgorithmException
|
||||||
|
| NoSuchProviderException
|
||||||
|
| InvalidAlgorithmParameterException
|
||||||
|
| CertificateException
|
||||||
|
| IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new FingerprintException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean initCipher()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
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;
|
||||||
|
} catch (KeyPermanentlyInvalidatedException e) {
|
||||||
|
return false;
|
||||||
|
} catch (KeyStoreException | CertificateException
|
||||||
|
| UnrecoverableKeyException | IOException
|
||||||
|
| NoSuchAlgorithmException | InvalidKeyException e) {
|
||||||
|
throw new RuntimeException("Failed to init Cipher", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FingerprintException extends Exception {
|
||||||
|
public FingerprintException(Exception e)
|
||||||
|
{
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.nauk.coinfolio.FingerprintHelper;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
import android.os.CancellationSignal;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Guitoune on 28/02/2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
|
||||||
|
|
||||||
|
private CancellationSignal cancellationSignal;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
public FingerprintHandler(Context context)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
19
app/src/main/res/layout/fragment_fingerprint_scanner.xml
Normal file
19
app/src/main/res/layout/fragment_fingerprint_scanner.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/edit_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/fingerprint_textview"
|
||||||
|
android:text="@string/pref_fingerprint"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<com.mattprecious.swirl.SwirlView
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp" />
|
||||||
|
</LinearLayout>
|
@ -79,6 +79,9 @@
|
|||||||
|
|
||||||
<string name="pref_title_vibrate">Vibrate</string>
|
<string name="pref_title_vibrate">Vibrate</string>
|
||||||
|
|
||||||
|
<!--Fingerprint authentification-->
|
||||||
|
<string name="fingerprint_verification">Verify your fingerprint</string>
|
||||||
|
|
||||||
|
|
||||||
<!--Exchange strings-->
|
<!--Exchange strings-->
|
||||||
<string name="pref_header_exchange">Exchanges settings</string>
|
<string name="pref_header_exchange">Exchanges settings</string>
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:id="@+id/fingerprint_switch"
|
||||||
|
android:key="enable_fingerprint"
|
||||||
|
android:title="@string/pref_fingerprint" />
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:title="@string/pref_title_exchange_hitbtc">
|
android:title="@string/pref_title_exchange_hitbtc">
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
|
Loading…
Reference in New Issue
Block a user