· 5 years ago · Dec 01, 2019, 12:58 PM
1package com.example.bsm;
2
3import android.Manifest;
4import android.annotation.TargetApi;
5import android.app.AlertDialog;
6import android.app.KeyguardManager;
7import android.content.Context;
8import android.content.DialogInterface;
9import android.content.SharedPreferences;
10import android.content.pm.PackageManager;
11
12import androidx.annotation.NonNull;
13import androidx.biometric.BiometricManager;
14import androidx.biometric.BiometricPrompt;
15import android.hardware.fingerprint.FingerprintManager;
16import android.os.Build;
17import android.os.Bundle;
18
19import com.google.android.material.floatingactionbutton.FloatingActionButton;
20import com.google.android.material.snackbar.Snackbar;
21
22import androidx.appcompat.app.AppCompatActivity;
23import androidx.appcompat.widget.Toolbar;
24import androidx.core.content.ContextCompat;
25
26import android.security.keystore.KeyGenParameterSpec;
27import android.security.keystore.KeyPermanentlyInvalidatedException;
28import android.security.keystore.KeyProperties;
29import android.util.Log;
30import android.view.View;
31import android.widget.Button;
32import android.widget.EditText;
33import android.widget.ImageView;
34import android.widget.TextView;
35import android.widget.Toast;
36
37import java.io.FileNotFoundException;
38import java.io.FileOutputStream;
39import java.io.IOException;
40import java.nio.charset.Charset;
41import java.nio.charset.StandardCharsets;
42import java.security.InvalidAlgorithmParameterException;
43import java.security.InvalidKeyException;
44import java.security.KeyStore;
45import java.security.KeyStoreException;
46import java.security.NoSuchAlgorithmException;
47import java.security.NoSuchProviderException;
48import java.security.UnrecoverableKeyException;
49import java.security.cert.CertificateException;
50import java.security.spec.InvalidKeySpecException;
51import java.util.Arrays;
52import java.util.Base64;
53import java.util.concurrent.Executor;
54
55import javax.crypto.BadPaddingException;
56import javax.crypto.Cipher;
57import javax.crypto.IllegalBlockSizeException;
58import javax.crypto.KeyGenerator;
59import javax.crypto.NoSuchPaddingException;
60import javax.crypto.SecretKey;
61import javax.crypto.SecretKeyFactory;
62import javax.crypto.spec.IvParameterSpec;
63import javax.crypto.spec.PBEKeySpec;
64
65public class FingerprintActivity extends AppCompatActivity {
66
67 private TextView text;
68 private ImageView image;
69 private BiometricPrompt biometricPrompt;
70 private BiometricPrompt.PromptInfo promptInfo;
71 private FingerprintManager fingerprintManager;
72 private KeyguardManager keyguardManager;
73 private KeyStore keyStore;
74 private Cipher cipher;
75 private Cipher cipher2;
76 SecretKey secretKey;
77 SecretKey secretKey2;
78 SharedPreferences preferences;
79 SharedPreferences.Editor editor;
80 private String KEY_NAME = "klucz";
81 String nameFile;
82 String arrayResult[] = new String[2];
83 String key;
84 String salt;
85 byte[] keyb;
86 byte[] saltb;
87 byte[] iv;
88 Button button;
89 boolean decider = false;
90 @Override
91 protected void onCreate(Bundle savedInstanceState) {
92 super.onCreate(savedInstanceState);
93 setContentView(R.layout.activity_fingerprint);
94 final EditText fileName=new EditText(this);
95 final AlertDialog.Builder ad=new AlertDialog.Builder(this);
96 final Executor executor = ContextCompat.getMainExecutor(this);
97 BiometricManager biometricManager = BiometricManager.from(this);
98 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
99 switch (biometricManager.canAuthenticate()) {
100 case BiometricManager.BIOMETRIC_SUCCESS:
101 Log.d("MY_APP_TAG", "App can authenticate using biometrics.");
102 break;
103 case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
104 Log.e("MY_APP_TAG", "No biometric features available on this device.");
105 break;
106 case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
107 Log.e("MY_APP_TAG", "Biometric features are currently unavailable.");
108 break;
109 case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
110 Log.e("MY_APP_TAG", "The user hasn't associated " +
111 "any biometric credentials with their account.");
112 break;
113 }
114 }
115 try {
116 generateSecretKey(new KeyGenParameterSpec.Builder(
117 KEY_NAME,
118 KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
119 .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
120 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
121 .setUserAuthenticationRequired(true)
122 // Invalidate the keys if the user has registered a new biometric
123 // credential, such as a new fingerprint. Can call this method only
124 // on Android 7.0 (API level 24) or higher. The variable
125 // "invalidatedByBiometricEnrollment" is true by default.
126 .build());
127 } catch (NoSuchProviderException e) {
128 e.printStackTrace();
129 } catch (NoSuchAlgorithmException e) {
130 e.printStackTrace();
131 }
132
133 biometricPrompt = new BiometricPrompt(FingerprintActivity.this,
134 executor, new BiometricPrompt.AuthenticationCallback() {
135 @Override
136 public void onAuthenticationError(int errorCode,
137 @NonNull CharSequence errString) {
138 super.onAuthenticationError(errorCode, errString);
139 Toast.makeText(getApplicationContext(),
140 "Authentication error: " + errString, Toast.LENGTH_SHORT)
141 .show();
142 }
143
144 @Override
145 public void onAuthenticationSucceeded(
146 @NonNull BiometricPrompt.AuthenticationResult result) {
147 Log.d("RESULT!!", result.toString());
148 Log.d("CRYPTOPOBJ", result.getCryptoObject().toString());
149 // NullPointerException is unhandled; use Objects.requireNonNull();
150
151 if(decider == false) {
152 byte[] encryptedInfo = new byte[0];
153 try {
154 encryptedInfo = result.getCryptoObject().getCipher().doFinal(
155 "twoja stara".getBytes(Charset.defaultCharset()));
156 SharedPreferences xd = getSharedPreferences("DATA", 0);
157 SharedPreferences.Editor pref = getSharedPreferences("DATA", Context.MODE_PRIVATE).edit();
158// String ivs = Base64.getEncoder().encodeToString(result.getCryptoObject().getCipher().getIV());
159// pref.putString("iv", ivs);
160
161 } catch (BadPaddingException e) {
162 e.printStackTrace();
163 } catch (IllegalBlockSizeException e) {
164 e.printStackTrace();
165 }
166 Log.d("MY_APP_TAG", "Encrypted information: " +
167 Base64.getEncoder().encodeToString(encryptedInfo));
168 SharedPreferences.Editor editor = getSharedPreferences("DATA", 0).edit();
169 editor.putString("encrypted", Base64.getEncoder().encodeToString(encryptedInfo));
170 editor.apply();
171 } else if (decider == true) {
172 try {
173 SharedPreferences prefs = getSharedPreferences("DATA", 0);
174 String s = prefs.getString("encrypted", "");
175 byte[] encs = Base64.getDecoder().decode(s);
176 byte[] finito = result.getCryptoObject().getCipher().doFinal(encs);
177 String ss = new String(finito);
178 Log.d("ELOSZAAA", ss);
179 } catch (BadPaddingException e) {
180 e.printStackTrace();
181 } catch (IllegalBlockSizeException e) {
182 e.printStackTrace();
183 }
184 }
185 }
186
187
188
189 @Override
190 public void onAuthenticationFailed() {
191 super.onAuthenticationFailed();
192 Toast.makeText(getApplicationContext(), "Authentication failed",
193 Toast.LENGTH_SHORT)
194 .show();
195 }
196 });
197
198 promptInfo = new BiometricPrompt.PromptInfo.Builder()
199 .setTitle("Biometric login for my app")
200 .setSubtitle("Log in using your biometric credential")
201 .setNegativeButtonText("Cofnij")
202 .build();
203
204 // Prompt appears when user clicks "Log in".
205 // Consider integrating with the keystore to unlock cryptographic operations,
206 // if needed by your app.
207 image = findViewById(R.id.image);
208 image.setOnClickListener(view -> {
209 try {
210 decider = false;
211 cipher = getCipher();
212 secretKey = getSecretKey();
213 cipher.init(Cipher.ENCRYPT_MODE, secretKey);
214 iv = cipher.getIV();
215 Log.d("IVENCRYPT", Base64.getEncoder().encodeToString(iv));
216 SharedPreferences xd = getSharedPreferences("DATA", 0);
217 SharedPreferences.Editor pref = getSharedPreferences("DATA", Context.MODE_PRIVATE).edit();
218 String ivs = Base64.getEncoder().encodeToString(iv);
219 pref.putString("iv", ivs);
220 pref.apply();
221 Log.d("SK1", new String(secretKey.toString()));
222 biometricPrompt.authenticate(promptInfo,
223 new BiometricPrompt.CryptoObject(cipher));
224 } catch (NoSuchPaddingException e) {
225 e.printStackTrace();
226 } catch (NoSuchAlgorithmException e) {
227 e.printStackTrace();
228 } catch (IOException e) {
229 e.printStackTrace();
230 } catch (CertificateException e) {
231 e.printStackTrace();
232 } catch (UnrecoverableKeyException e) {
233 e.printStackTrace();
234 } catch (KeyStoreException e) {
235 e.printStackTrace();
236 } catch (InvalidKeyException e) {
237 e.printStackTrace();
238 }
239
240
241 });
242 button = findViewById(R.id.button);
243 button.setOnClickListener(view -> {
244 decider = true;
245 try {
246 SharedPreferences prefs = getSharedPreferences("DATA", 0);
247 String iv = prefs.getString("iv", "");
248 byte [] ivs = Base64.getDecoder().decode(iv);
249 cipher2 = getCipher();
250 secretKey2 = getSecretKey();
251 cipher2.init(Cipher.DECRYPT_MODE, secretKey2, new IvParameterSpec(ivs));
252 Log.d("SK2", secretKey2.toString());
253 biometricPrompt.authenticate(promptInfo,
254 new BiometricPrompt.CryptoObject(cipher2));
255 } catch (NoSuchAlgorithmException e) {
256 e.printStackTrace();
257
258 } catch (NoSuchPaddingException e) {
259 e.printStackTrace();
260 } catch (InvalidKeyException e) {
261 e.printStackTrace();
262 } catch (InvalidAlgorithmParameterException e) {
263 e.printStackTrace();
264 } catch (IOException e) {
265 e.printStackTrace();
266 } catch (CertificateException e) {
267 e.printStackTrace();
268 } catch (UnrecoverableKeyException e) {
269 e.printStackTrace();
270 } catch (KeyStoreException e) {
271 e.printStackTrace();
272 }
273
274
275 });
276
277// preferences = getSharedPreferences("DATA.xml", Context.MODE_PRIVATE);
278// if(preferences.getString("data", "") == "") {
279// ad.setView(fileName);
280// ad.setMessage("Utwórz klucz");
281// ad.setPositiveButton("Save", new DialogInterface.OnClickListener() {
282// @Override
283// public void onClick(DialogInterface dialogInterface, int i) {
284// nameFile = fileName.getText().toString();
285// editor = getSharedPreferences("DATA", Context.MODE_PRIVATE).edit();
286// try {
287// arrayResult = generateStorngPasswordHash(nameFile);
288// } catch (NoSuchAlgorithmException e) {
289// e.printStackTrace();
290// } catch (InvalidKeySpecException e) {
291// e.printStackTrace();
292// }
293// editor.putString("salt", arrayResult[0]);
294// editor.putString("data", arrayResult[1]);
295// editor.commit();
296//
297//
298// }
299// });
300// ad.setNegativeButton("Cancel",new DialogInterface.OnClickListener() {
301// @Override
302// public void onClick(DialogInterface dialog, int which) {
303// dialog.cancel();
304// }
305// });
306//
307// ad.show();
308// }
309// else {
310// preferences = getSharedPreferences("DATA", Context.MODE_PRIVATE);
311// key = preferences.getString("data", "");
312// salt = preferences.getString("salt", "");
313// saltb = java.util.Base64.getDecoder().decode(salt);
314// keyb = java.util.Base64.getDecoder().decode(key);
315// }
316// text = findViewById(R.id.text);
317// image = findViewById(R.id.image);
318// fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
319// keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
320//
321//
322// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
323// if(!fingerprintManager.isHardwareDetected()) {
324// text.setText("Scanner not found.");
325// }
326// else if(ContextCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
327// text.setText("Permission denied");
328// }
329// else if(!keyguardManager.isKeyguardSecure()) {
330// text.setText("Add Lock to your phone in settings.");
331// }
332// else if (!fingerprintManager.hasEnrolledFingerprints()) {
333// text.setText("You should add at least 1 Fingerprint to use this feature.");
334// }
335// else {
336// text.setText("Place your finger on Scanner to access the app.");
337// generateKey();
338// if(cipherInit()) {
339// FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
340// FingerprintHandler fingerprintHandler = new FingerprintHandler(this);
341// fingerprintHandler.startAuth(fingerprintManager, cryptoObject);
342// }
343//
344// }
345// }
346
347 }
348
349// private void generateKey() {
350// try {
351// keyStore = KeyStore.getInstance("AndroidKeyStore");
352// KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
353// keyStore.load(null);
354// keyGenerator.init(new
355// KeyGenParameterSpec.Builder(KEY_NAME,
356// KeyProperties.PURPOSE_ENCRYPT |
357// KeyProperties.PURPOSE_DECRYPT)
358// .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
359// .setUserAuthenticationRequired(true)
360// .setEncryptionPaddings(
361// KeyProperties.ENCRYPTION_PADDING_PKCS7)
362// .build());
363// keyGenerator.generateKey();
364//
365// } catch(KeyStoreException | IOException | CertificateException
366// | NoSuchAlgorithmException | InvalidAlgorithmParameterException
367// | NoSuchProviderException e) {
368// e.printStackTrace();
369// }
370// }
371//
372// public boolean cipherInit() {
373// try {
374// cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
375// } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
376// throw new RuntimeException("Failed to get Cipher", e);
377// }
378//
379// try {
380// keyStore.load(null);
381// SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
382// null);
383// cipher.init(Cipher.ENCRYPT_MODE, key);
384// return true;
385// } catch(InvalidKeyException | CertificateException | IOException | NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException e) {
386// return false;
387// }
388// }
389
390// private static String[] generateStorngPasswordHash(String password) throws NoSuchAlgorithmException, InvalidKeySpecException
391// {
392// char[] chars = password.toCharArray();
393// byte[] salt = Encryption.getSalt();
394//
395// PBEKeySpec spec = new PBEKeySpec(chars, salt, 10000, 256);
396// SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
397// byte[] hash = skf.generateSecret(spec).getEncoded();
398// String salt64 = Base64.getEncoder().encodeToString(salt);
399// String result64 = Base64.getEncoder().encodeToString(hash);
400// String array[] = new String[2];
401// array[0] = salt64;
402// array[1] = result64;
403// return array;
404// }
405//
406// private static boolean validatePassword(byte[] key, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException
407// {
408// String[] parts = storedPassword.split(":");
409// int iterations = Integer.parseInt(parts[0]);
410// byte[] salt = fromHex(parts[1]);
411// byte[] hash = fromHex(parts[2]);
412//
413// PBEKeySpec spec = new PBEKeySpec(originalPassword.toCharArray(), salt, iterations, hash.length * 8);
414// SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
415// byte[] testHash = skf.generateSecret(spec).getEncoded();
416//
417// int diff = hash.length ^ testHash.length;
418// for(int i = 0; i < hash.length && i < testHash.length; i++)
419// {
420// diff |= hash[i] ^ testHash[i];
421// }
422// return diff == 0;
423// }
424
425 private void generateSecretKey(KeyGenParameterSpec keyGenParameterSpec) throws NoSuchProviderException, NoSuchAlgorithmException {
426 KeyGenerator keyGenerator = KeyGenerator.getInstance(
427 KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
428 try {
429 keyGenerator.init(keyGenParameterSpec);
430 keyGenerator.generateKey();
431 } catch (InvalidAlgorithmParameterException e) {
432 e.printStackTrace();
433 }
434
435 }
436
437 private SecretKey getSecretKey() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException {
438 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
439
440 // Before the keystore can be accessed, it must be loaded.
441 keyStore.load(null);
442 return ((SecretKey)keyStore.getKey(KEY_NAME, null));
443 }
444
445 private Cipher getCipher() throws NoSuchPaddingException, NoSuchAlgorithmException {
446 return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
447 + KeyProperties.BLOCK_MODE_CBC + "/"
448 + KeyProperties.ENCRYPTION_PADDING_PKCS7);
449 }
450
451}