-
Notifications
You must be signed in to change notification settings - Fork 8.3k
/
Copy pathFingerprintController.java
144 lines (124 loc) · 5.13 KB
/
FingerprintController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package org.telegram.messenger;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import androidx.annotation.RequiresApi;
import org.telegram.messenger.support.fingerprint.FingerprintManagerCompat;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.util.Locale;
import javax.crypto.Cipher;
@RequiresApi(api = Build.VERSION_CODES.M)
public class FingerprintController {
private final static String KEY_ALIAS = "tmessages_passcode";
private static KeyStore keyStore;
private static KeyPairGenerator keyPairGenerator;
private static Boolean hasChangedFingerprints;
private static KeyStore getKeyStore() {
if (keyStore != null) {
return keyStore;
}
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
return keyStore;
} catch (Exception e) {
FileLog.e(e);
}
return null;
}
private static KeyPairGenerator getKeyPairGenerator() {
if (keyPairGenerator != null) {
return keyPairGenerator;
}
try {
keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
return keyPairGenerator;
} catch (Exception e) {
FileLog.e(e);
}
return null;
}
private static void generateNewKey(boolean notifyCheckFingerprint) {
KeyPairGenerator generator = getKeyPairGenerator();
if (generator != null) {
try {
Locale realLocale = Locale.getDefault();
// A workaround for AndroidKeyStore bug in RTL languages
setLocale(Locale.ENGLISH);
generator.initialize(new KeyGenParameterSpec.Builder(KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
.setUserAuthenticationRequired(true)
.build());
generator.generateKeyPair();
setLocale(realLocale);
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didGenerateFingerprintKeyPair, notifyCheckFingerprint));
} catch (InvalidAlgorithmParameterException e) {
FileLog.e(e);
} catch (Exception e) {
if (e.getClass().getName().equals("android.security.KeyStoreException")) {
// Keystore is somehow broken?
} else {
FileLog.e(e);
}
}
}
}
public static void deleteInvalidKey() {
KeyStore keyStore = getKeyStore();
try {
keyStore.deleteEntry(KEY_ALIAS);
} catch (KeyStoreException e) {
FileLog.e(e);
}
hasChangedFingerprints = null;
checkKeyReady(false);
}
public static void checkKeyReady() {
checkKeyReady(true);
}
public static void checkKeyReady(boolean notifyCheckFingerprint) {
if (!isKeyReady() && AndroidUtilities.isKeyguardSecure() && FingerprintManagerCompat.from(ApplicationLoader.applicationContext).isHardwareDetected()
&& FingerprintManagerCompat.from(ApplicationLoader.applicationContext).hasEnrolledFingerprints()) {
Utilities.globalQueue.postRunnable(() -> generateNewKey(notifyCheckFingerprint));
}
}
public static boolean isKeyReady() {
try {
return getKeyStore().containsAlias(KEY_ALIAS);
} catch (KeyStoreException e) {
FileLog.e(e);
}
return false;
}
public static boolean checkDeviceFingerprintsChanged() {
if (hasChangedFingerprints != null) {
return hasChangedFingerprints;
}
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, keyStore.getKey(KEY_ALIAS, null));
return hasChangedFingerprints = false;
} catch (KeyPermanentlyInvalidatedException ignored) {
// Device fingerprints changed, then we should delete old key
return hasChangedFingerprints = true;
} catch (Exception e) {
FileLog.e(e);
}
return hasChangedFingerprints = false;
}
private static void setLocale(Locale locale) {
Locale.setDefault(locale);
Resources resources = ApplicationLoader.applicationContext.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(locale);
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
}