Skip to content

Commit 92aafec

Browse files
committed
enforce keyguard authentication and more logging
1 parent 90b4ac7 commit 92aafec

File tree

7 files changed

+60
-106
lines changed

7 files changed

+60
-106
lines changed

core/src/main/java/io/snabble/sdk/UserPreferences.java

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -206,34 +206,6 @@ public String getConsentVersion() {
206206
return sharedPreferences.getString(SHARED_PREFERENCES_CONSENT_VERSION, null);
207207
}
208208

209-
/**
210-
* Enables keyguard authentication for online payment using user credentials.
211-
* Requires the user to have a PIN, Fingerprint or other security locks.
212-
*
213-
* Payment credentials will then be securely stored using a generated key
214-
* using the Android KeyStore API.
215-
*
216-
* Removing the secure lock will cause the keys to be wiped and rendering the
217-
* stored payment credentials useless.
218-
*
219-
* Only supported for Android >= 4.3. For earlier Android versions the credentials will only
220-
* be stored using asynchronous RSA.
221-
*
222-
*/
223-
public void setRequireKeyguardAuthenticationForPayment(boolean enabled) {
224-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
225-
sharedPreferences.edit().putBoolean(SHARED_PREFERENCES_USE_KEYGUARD, enabled).apply();
226-
}
227-
}
228-
229-
public boolean isRequiringKeyguardAuthenticationForPayment() {
230-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
231-
return sharedPreferences.getBoolean(SHARED_PREFERENCES_USE_KEYGUARD, false);
232-
}
233-
234-
return false;
235-
}
236-
237209
public void addOnNewAppUserListener(OnNewAppUserListener onNewAppUserListener) {
238210
if (!onNewAppUserListeners.contains(onNewAppUserListener)) {
239211
onNewAppUserListeners.add(onNewAppUserListener);

core/src/main/java/io/snabble/sdk/payment/PaymentCredentialsStore.java

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,32 +62,27 @@ public void init(Context context, Environment environment) {
6262
@SuppressLint("NewApi")
6363
private void initializeKeyStore() {
6464
if (keyStoreCipher == null) {
65-
Snabble snabble = Snabble.getInstance();
66-
67-
// KeyStore is not available on Android < 4.3
68-
if (userPreferences.isRequiringKeyguardAuthenticationForPayment()) {
69-
keyStoreCipher = KeyStoreCipher.create(snabble.getApplication(), "SnabblePaymentCredentialsStore", true);
70-
}
65+
keyStoreCipher = KeyStoreCipher.create(Snabble.getInstance().getApplication(), "SnabblePaymentCredentialsStore", true);
7166
}
7267
}
7368

7469
private void ensureKeyStoreIsAccessible() {
7570
initializeKeyStore();
7671

77-
if (keyStoreCipher != null) {
78-
keyStoreCipher.validate();
72+
keyStoreCipher.validate();
7973

80-
String id = keyStoreCipher.id();
81-
if (id == null) {
82-
keyStoreCipher = null;
83-
return;
84-
}
74+
String id = keyStoreCipher.id();
75+
if (id == null) {
76+
Logger.errorEvent("Keystore has no id!");
77+
keyStoreCipher = null;
78+
return;
79+
}
8580

86-
if (!id.equals(data.id)) {
87-
data.id = keyStoreCipher.id();
88-
data.isKeyguarded = true;
89-
removeInvalidCredentials();
90-
}
81+
if (!id.equals(data.id)) {
82+
data.id = keyStoreCipher.id();
83+
data.isKeyguarded = true;
84+
Logger.errorEvent("Removing payment credentials, because key store id differs");
85+
removeInvalidCredentials();
9186
}
9287

9388
Context context = Snabble.getInstance().getApplication();
@@ -103,7 +98,8 @@ private void ensureKeyStoreIsAccessible() {
10398
}
10499
}
105100

106-
if (!secure || data.isKeyguarded != userPreferences.isRequiringKeyguardAuthenticationForPayment()) {
101+
if (!secure) {
102+
Logger.errorEvent("Removing payment credentials, because device is not secure. KeyguardManager is " + (keyguardManager != null ? "not null" : "null"));
107103
removeInvalidCredentials();
108104
}
109105
}
@@ -211,7 +207,7 @@ private void load() {
211207
try {
212208
data = gson.fromJson(json, Data.class);
213209
} catch (Exception e) {
214-
Logger.e("Could not read payment credentials: %s", e.getMessage());
210+
Logger.errorEvent("Could not read payment credentials: %s", e.getMessage());
215211
}
216212

217213
if (data.credentialsList == null) {

sample/src/main/java/io/snabble/testapp/App.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,6 @@ public void onReady() {
9595
// we invent one here
9696
project.setCustomerCardId("2206467131013");
9797

98-
// if you want to force keyguard authentication before online payment
99-
snabble.getUserPreferences().setRequireKeyguardAuthenticationForPayment(true);
100-
10198
// optional: preload assets
10299
project.getAssets().update();
103100

ui/src/main/java/io/snabble/sdk/ui/payment/CreditCardInputView.java

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -243,25 +243,21 @@ private void loadForm(HashResponse hashResponse) {
243243
private void authenticateAndSave(final CreditCardInfo creditCardInfo) {
244244
cancelPreAuth(creditCardInfo);
245245

246-
if (Snabble.getInstance().getUserPreferences().isRequiringKeyguardAuthenticationForPayment()) {
247-
Keyguard.unlock(UIUtils.getHostFragmentActivity(getContext()), new Keyguard.Callback() {
248-
@Override
249-
public void success() {
250-
save(creditCardInfo);
251-
}
246+
Keyguard.unlock(UIUtils.getHostFragmentActivity(getContext()), new Keyguard.Callback() {
247+
@Override
248+
public void success() {
249+
save(creditCardInfo);
250+
}
252251

253-
@Override
254-
public void error() {
255-
if (isShown()) {
256-
finish();
257-
} else {
258-
acceptedKeyguard = true;
259-
}
252+
@Override
253+
public void error() {
254+
if (isShown()) {
255+
finish();
256+
} else {
257+
acceptedKeyguard = true;
260258
}
261-
});
262-
} else {
263-
save(creditCardInfo);
264-
}
259+
}
260+
});
265261
}
266262

267263
private void save(CreditCardInfo info) {

ui/src/main/java/io/snabble/sdk/ui/payment/PaydirektInputView.java

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -222,25 +222,21 @@ public void error(Throwable t) {
222222
}
223223

224224
private void authenticateAndSave() {
225-
if (Snabble.getInstance().getUserPreferences().isRequiringKeyguardAuthenticationForPayment()) {
226-
Keyguard.unlock(UIUtils.getHostFragmentActivity(getContext()), new Keyguard.Callback() {
227-
@Override
228-
public void success() {
229-
save();
230-
}
225+
Keyguard.unlock(UIUtils.getHostFragmentActivity(getContext()), new Keyguard.Callback() {
226+
@Override
227+
public void success() {
228+
save();
229+
}
231230

232-
@Override
233-
public void error() {
234-
if (isShown()) {
235-
finish();
236-
} else {
237-
acceptedKeyguard = true;
238-
}
231+
@Override
232+
public void error() {
233+
if (isShown()) {
234+
finish();
235+
} else {
236+
acceptedKeyguard = true;
239237
}
240-
});
241-
} else {
242-
save();
243-
}
238+
}
239+
});
244240
}
245241

246242
private void save() {

ui/src/main/java/io/snabble/sdk/ui/payment/SEPACardInputView.java

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -258,28 +258,24 @@ private void saveCard() {
258258
}
259259

260260
if (ok) {
261-
if (Snabble.getInstance().getUserPreferences().isRequiringKeyguardAuthenticationForPayment()) {
262-
if (KeyguardUtils.isDeviceSecure()) {
263-
Keyguard.unlock(UIUtils.getHostFragmentActivity(getContext()), new Keyguard.Callback() {
264-
@Override
265-
public void success() {
266-
add(name, iban);
267-
}
261+
if (KeyguardUtils.isDeviceSecure()) {
262+
Keyguard.unlock(UIUtils.getHostFragmentActivity(getContext()), new Keyguard.Callback() {
263+
@Override
264+
public void success() {
265+
add(name, iban);
266+
}
268267

269-
@Override
270-
public void error() {
268+
@Override
269+
public void error() {
271270

272-
}
273-
});
274-
} else {
275-
new AlertDialog.Builder(getContext())
276-
.setMessage(R.string.Snabble_Keyguard_requireScreenLock)
277-
.setPositiveButton(R.string.Snabble_OK, null)
278-
.setCancelable(false)
279-
.show();
280-
}
271+
}
272+
});
281273
} else {
282-
add(name, iban);
274+
new AlertDialog.Builder(getContext())
275+
.setMessage(R.string.Snabble_Keyguard_requireScreenLock)
276+
.setPositiveButton(R.string.Snabble_OK, null)
277+
.setCancelable(false)
278+
.show();
283279
}
284280
}
285281
}

utils/src/main/java/io/snabble/sdk/utils/security/KeyStoreCipherMarshmallow.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import javax.crypto.KeyGenerator;
1818
import javax.crypto.spec.IvParameterSpec;
1919

20+
import io.snabble.sdk.utils.Dispatch;
2021
import io.snabble.sdk.utils.Logger;
2122
import io.snabble.sdk.utils.Utils;
2223

@@ -133,7 +134,7 @@ public byte[] encrypt(byte[] input) {
133134
c.init(Cipher.ENCRYPT_MODE, keyStore.getKey(alias, null), ivParameterSpec);
134135
return c.doFinal(input);
135136
} catch (KeyPermanentlyInvalidatedException e) {
136-
Logger.e("Key permanently invalidated");
137+
Logger.errorEvent("Key permanently invalidated " + e.getClass().getName() + ": " + e.getMessage());
137138
} catch (Exception e) {
138139
Logger.e("Could not encrypt data: %s", e.getMessage());
139140
}
@@ -148,7 +149,7 @@ public byte[] decrypt(byte[] encrypted) {
148149
c.init(Cipher.DECRYPT_MODE, keyStore.getKey(alias, null), ivParameterSpec);
149150
return c.doFinal(encrypted);
150151
} catch (KeyPermanentlyInvalidatedException e) {
151-
Logger.e("Key permanently invalidated");
152+
Logger.errorEvent("Key permanently invalidated " + e.getClass().getName() + ": " + e.getMessage());
152153
} catch (Exception e) {
153154
Logger.e("Could not decrypt data: %s", e.getMessage());
154155
}

0 commit comments

Comments
 (0)