Skip to content

Commit

Permalink
Revert some unneeded changes where passing promptInfo around to a lot…
Browse files Browse the repository at this point in the history
… of decryption methods.
  • Loading branch information
Jens Kuhr Jørgensen committed Mar 5, 2020
1 parent 69cd87f commit f578d22
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 62 deletions.
6 changes: 3 additions & 3 deletions KeychainExample/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ export default class KeychainExample extends Component {
try {
const options = {
authenticationPrompt: "Authentification needed",
authenticationPromptTitle: "Android auth needed222",
authenticationPromptSubtitle: "" + new Date().getTime(),
authenticationPromptNegativeBtnText: "Cancel btn",
promptInfoTitle: "Authentication needed",
promptInfoSubtitle: "Some descriptive subtitle",
promptInfoNegativeBtnText: "Cancel",
}
const credentials = await Keychain.getGenericPassword(options);
if (credentials) {
Expand Down
69 changes: 38 additions & 31 deletions android/src/main/java/com/oblador/keychain/KeychainModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ public class KeychainModule extends ReactContextBaseJavaModule {
String PASSWORD = "password";
String STORAGE = "storage";

String AUTHENTICATION_PROMPT_TITLE = "authenticationPromptTitle";
String AUTHENTICATION_PROMPT_SUBTITLE = "authenticationPromptSubtitle";
String AUTHENTICATION_PROMPT_NEGATIVE_BTN_TEXT = "authenticationPromptNegativeBtnText";
String PROMPT_INFO_TITLE = "promptInfoTitle";
String PROMPT_INFO_SUBTITLE = "promptInfoSubtitle";
String PROMPT_INFO_NEGATIVE_BTN_TEXT = "promptInfoNegativeBtnText";
}

/** Known error codes. */
Expand Down Expand Up @@ -284,7 +284,7 @@ protected void getGenericPassword(@NonNull final String alias,
final CipherStorage current = getCipherStorageForCurrentAPILevel(useBiometry);
final String rules = getSecurityRulesOrDefault(options);

final PromptInfo promptInfo = getAuthenticationPrompt(options);
final PromptInfo promptInfo = getPromptInfo(options);
final DecryptionResult decryptionResult = decryptCredentials(alias, current, resultSet, rules, promptInfo);

final WritableMap credentials = Arguments.createMap();
Expand Down Expand Up @@ -533,27 +533,27 @@ private void addCipherStorageToMap(@NonNull final CipherStorage cipherStorage) {
cipherStorageMap.put(cipherStorage.getCipherStorageName(), cipherStorage);
}

/** Extract user specified authentication prompt title from options. */
/** Extract user specified prompt info from options. */
@NonNull
private static PromptInfo getAuthenticationPrompt(@Nullable final ReadableMap options) {
String authenticationPromptTitle = "Authentication required";
String authenticationPromptSubtitle = "Some descriptive subtitle";
String authenticationPromptNegativeBtnText = "Cancel";
private static PromptInfo getPromptInfo(@Nullable final ReadableMap options) {
String promptInfoTitle = "Authentication needed";
String promptInfoSubtitle = "Some descriptive subtitle";
String promptInfoNegativeButton = "Cancel";

if (null != options && options.hasKey(Maps.AUTHENTICATION_PROMPT_TITLE)) {
authenticationPromptTitle = options.getString(Maps.AUTHENTICATION_PROMPT_TITLE);
if (null != options && options.hasKey(Maps.PROMPT_INFO_TITLE)) {
promptInfoTitle = options.getString(Maps.PROMPT_INFO_TITLE);
}
if (null != options && options.hasKey(Maps.AUTHENTICATION_PROMPT_SUBTITLE)) {
authenticationPromptSubtitle = options.getString(Maps.AUTHENTICATION_PROMPT_SUBTITLE);
if (null != options && options.hasKey(Maps.PROMPT_INFO_SUBTITLE)) {
promptInfoSubtitle = options.getString(Maps.PROMPT_INFO_SUBTITLE);
}
if (null != options && options.hasKey(Maps.AUTHENTICATION_PROMPT_NEGATIVE_BTN_TEXT)) {
authenticationPromptNegativeBtnText = options.getString(Maps.AUTHENTICATION_PROMPT_NEGATIVE_BTN_TEXT);
if (null != options && options.hasKey(Maps.PROMPT_INFO_NEGATIVE_BTN_TEXT)) {
promptInfoNegativeButton = options.getString(Maps.PROMPT_INFO_NEGATIVE_BTN_TEXT);
}

final PromptInfo promptInfo = new PromptInfo.Builder()
.setTitle(authenticationPromptTitle)
.setSubtitle(authenticationPromptSubtitle)
.setNegativeButtonText(authenticationPromptNegativeBtnText)
.setTitle(promptInfo)
.setSubtitle(promptInfoSubtitle)
.setNegativeButtonText(promptInfoNegativeButton)
.build();

return promptInfo;
Expand All @@ -568,13 +568,13 @@ private DecryptionResult decryptCredentials(@NonNull final String alias,
@NonNull final CipherStorage current,
@NonNull final ResultSet resultSet,
@Rules @NonNull final String rules,
@NonNull final PromptInfo authenticationPromptTitle)
@NonNull final PromptInfo promptInfo)
throws CryptoFailedException, KeyStoreAccessException {
final String storageName = resultSet.cipherStorageName;

// The encrypted data is encrypted using the current CipherStorage, so we just decrypt and return
if (storageName.equals(current.getCipherStorageName())) {
return decryptToResult(alias, current, resultSet, authenticationPromptTitle);
return decryptToResult(alias, current, resultSet, promptInfo);
}

// The encrypted data is encrypted using an older CipherStorage, so we need to decrypt the data first,
Expand All @@ -585,7 +585,7 @@ private DecryptionResult decryptCredentials(@NonNull final String alias,
}

// decrypt using the older cipher storage
final DecryptionResult decryptionResult = decryptToResult(alias, oldStorage, resultSet, authenticationPromptTitle);
final DecryptionResult decryptionResult = decryptToResult(alias, oldStorage, resultSet, promptInfo);

if (Rules.AUTOMATIC_UPGRADE.equals(rules)) {
try {
Expand All @@ -604,10 +604,10 @@ private DecryptionResult decryptCredentials(@NonNull final String alias,
private DecryptionResult decryptToResult(@NonNull final String alias,
@NonNull final CipherStorage storage,
@NonNull final ResultSet resultSet,
@NonNull final PromptInfo authenticationPromptTitle)
@NonNull final PromptInfo promptInfo)
throws CryptoFailedException {
final DecryptionResultHandler handler = getInteractiveHandler(storage, authenticationPromptTitle);
storage.decrypt(handler, alias, resultSet.username, resultSet.password, SecurityLevel.ANY, authenticationPromptTitle);
final DecryptionResultHandler handler = getInteractiveHandler(storage, promptInfo);
storage.decrypt(handler, alias, resultSet.username, resultSet.password, SecurityLevel.ANY);

CryptoFailedException.reThrowOnError(handler.getError());

Expand All @@ -620,9 +620,9 @@ private DecryptionResult decryptToResult(@NonNull final String alias,

/** Get instance of handler that resolves access to the keystore on system request. */
@NonNull
protected DecryptionResultHandler getInteractiveHandler(@NonNull final CipherStorage current, @NonNull final PromptInfo authenticationPromptTitle) {
protected DecryptionResultHandler getInteractiveHandler(@NonNull final CipherStorage current, @NonNull final PromptInfo promptInfo) {
if (current.isBiometrySupported() /*&& isFingerprintAuthAvailable()*/) {
return new InteractiveBiometric(current, authenticationPromptTitle);
return new InteractiveBiometric(current, promptInfo);
}

return new NonInteractiveHandler();
Expand Down Expand Up @@ -781,13 +781,13 @@ private class InteractiveBiometric extends BiometricPrompt.AuthenticationCallbac
private DecryptionContext context;
private PromptInfo promptInfo;

private InteractiveBiometric(@NonNull final CipherStorage storage, @NonNull final PromptInfo authenticationPromptTitle) {
private InteractiveBiometric(@NonNull final CipherStorage storage, @NonNull final PromptInfo promptInfo) {
this.storage = (CipherStorageBase) storage;
this.promptInfo = authenticationPromptTitle;
this.promptInfo = promptInfo;
}

@Override
public void askAccessPermissions(@NonNull final DecryptionContext context, @NonNull final PromptInfo authenticationPromptTitle) {
public void askAccessPermissions(@NonNull final DecryptionContext context) {
this.context = context;

if (!DeviceAvailability.isPermissionsGranted(getReactApplicationContext())) {
Expand All @@ -796,7 +796,7 @@ public void askAccessPermissions(@NonNull final DecryptionContext context, @NonN

onDecrypt(null, failure);
} else {
startAuthentication(authenticationPromptTitle);
startAuthentication();
}
}

Expand Down Expand Up @@ -856,10 +856,17 @@ public void onAuthenticationFailed() {
}

/** trigger interactive authentication. */
public void startAuthentication(@NonNull final PromptInfo promptInfo) {
public void startAuthentication() {
final FragmentActivity activity = (FragmentActivity) getCurrentActivity();
if (null == activity) throw new NullPointerException("Not assigned current activity");

// code can be executed only from MAIN thread
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
activity.runOnUiThread(this::startAuthentication);
waitResult();
return;
}

final BiometricPrompt prompt = new BiometricPrompt(activity, executor, this);

prompt.authenticate(this.promptInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.biometric.BiometricPrompt.PromptInfo;

import com.oblador.keychain.SecurityLevel;
import com.oblador.keychain.exceptions.CryptoFailedException;
Expand Down Expand Up @@ -92,7 +91,7 @@ interface WithResults {
/** Handler that allows to inject some actions during decrypt operations. */
interface DecryptionResultHandler extends WithResults {
/** Ask user for interaction, often its unlock of keystore by biometric data providing. */
void askAccessPermissions(@NonNull final DecryptionContext context, @NonNull final PromptInfo authenticationPromptTitle);
void askAccessPermissions(@NonNull final DecryptionContext context);

/**
*
Expand Down Expand Up @@ -120,17 +119,15 @@ EncryptionResult encrypt(@NonNull final String alias,
DecryptionResult decrypt(@NonNull final String alias,
@NonNull final byte[] username,
@NonNull final byte[] password,
@NonNull final SecurityLevel level,
@NonNull final PromptInfo authenticationPromptTitle)
@NonNull final SecurityLevel level)
throws CryptoFailedException;

/** Decrypt the credentials but redirect results of operation to handler. */
void decrypt(@NonNull final DecryptionResultHandler handler,
@NonNull final String alias,
@NonNull final byte[] username,
@NonNull final byte[] password,
@NonNull final SecurityLevel level,
@NonNull final PromptInfo authenticationPromptTitle)
@NonNull final SecurityLevel level)
throws CryptoFailedException;

/** Remove key (by alias) from storage. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.biometric.BiometricPrompt.PromptInfo;

import com.facebook.android.crypto.keychain.AndroidConceal;
import com.facebook.android.crypto.keychain.SharedPrefsBackedKeyChain;
Expand Down Expand Up @@ -99,8 +98,7 @@ public EncryptionResult encrypt(@NonNull final String alias,
public DecryptionResult decrypt(@NonNull final String alias,
@NonNull final byte[] username,
@NonNull final byte[] password,
@NonNull final SecurityLevel level,
@NonNull final PromptInfo authenticationPromptTitle)
@NonNull final SecurityLevel level)
throws CryptoFailedException {

throwIfInsufficientLevel(level);
Expand All @@ -122,17 +120,16 @@ public DecryptionResult decrypt(@NonNull final String alias,
}
}

/** redirect call to default {@link #decrypt(String, byte[], byte[], SecurityLevel, String)} method. */
/** redirect call to default {@link #decrypt(String, byte[], byte[], SecurityLevel)} method. */
@Override
public void decrypt(@NonNull DecryptionResultHandler handler,
@NonNull String service,
@NonNull byte[] username,
@NonNull byte[] password,
@NonNull final SecurityLevel level,
@NonNull final PromptInfo authenticationPromptTitle) {
@NonNull final SecurityLevel level) {

try {
final DecryptionResult results = decrypt(service, username, password, level, authenticationPromptTitle);
final DecryptionResult results = decrypt(service, username, password, level);

handler.onDecrypt(results, null);
} catch (Throwable fail) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import android.security.keystore.KeyProperties;

import androidx.annotation.NonNull;
import androidx.biometric.BiometricPrompt.PromptInfo;

import com.oblador.keychain.KeychainModule.KnownCiphers;
import com.oblador.keychain.SecurityLevel;
Expand Down Expand Up @@ -127,8 +126,7 @@ public EncryptionResult encrypt(@NonNull final String alias,
public DecryptionResult decrypt(@NonNull final String alias,
@NonNull final byte[] username,
@NonNull final byte[] password,
@NonNull final SecurityLevel level,
@NonNull final PromptInfo authenticationPromptTitle)
@NonNull final SecurityLevel level)
throws CryptoFailedException {

throwIfInsufficientLevel(level);
Expand All @@ -151,16 +149,15 @@ public DecryptionResult decrypt(@NonNull final String alias,
}
}

/** Redirect call to {@link #decrypt(String, byte[], byte[], SecurityLevel, String)} method. */
/** Redirect call to {@link #decrypt(String, byte[], byte[], SecurityLevel)} method. */
@Override
public void decrypt(@NonNull final DecryptionResultHandler handler,
@NonNull final String service,
@NonNull final byte[] username,
@NonNull final byte[] password,
@NonNull final SecurityLevel level,
@NonNull final PromptInfo authenticationPromptTitle) {
@NonNull final SecurityLevel level) {
try {
final DecryptionResult results = decrypt(service, username, password, level, authenticationPromptTitle);
final DecryptionResult results = decrypt(service, username, password, level);

handler.onDecrypt(results, null);
} catch (Throwable fail) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.biometric.BiometricPrompt.PromptInfo;

import com.oblador.keychain.KeychainModule;
import com.oblador.keychain.SecurityLevel;
Expand Down Expand Up @@ -87,12 +86,11 @@ public EncryptionResult encrypt(@NonNull final String alias,
public DecryptionResult decrypt(@NonNull String alias,
@NonNull byte[] username,
@NonNull byte[] password,
@NonNull final SecurityLevel level,
@NonNull final PromptInfo authenticationPromptTitle)
@NonNull final SecurityLevel level)
throws CryptoFailedException {

final NonInteractiveHandler handler = new NonInteractiveHandler();
decrypt(handler, alias, username, password, level, authenticationPromptTitle);
decrypt(handler, alias, username, password, level);

CryptoFailedException.reThrowOnError(handler.getError());

Expand All @@ -109,8 +107,7 @@ public void decrypt(@NonNull DecryptionResultHandler handler,
@NonNull String alias,
@NonNull byte[] username,
@NonNull byte[] password,
@NonNull final SecurityLevel level,
@NonNull final PromptInfo authenticationPromptTitle)
@NonNull final SecurityLevel level)
throws CryptoFailedException {

throwIfInsufficientLevel(level);
Expand Down Expand Up @@ -138,7 +135,7 @@ public void decrypt(@NonNull DecryptionResultHandler handler,
@SuppressWarnings("ConstantConditions") final DecryptionContext context =
new DecryptionContext(safeAlias, key, password, username);

handler.askAccessPermissions(context, authenticationPromptTitle);
handler.askAccessPermissions(context);
} catch (final Throwable fail) {
// any other exception treated as a failure
handler.onDecrypt(null, fail);
Expand Down Expand Up @@ -269,7 +266,7 @@ public static class NonInteractiveHandler implements DecryptionResultHandler {
private Throwable error;

@Override
public void askAccessPermissions(@NonNull final DecryptionContext context, @NonNull final PromptInfo authenticationPromptTitle) {
public void askAccessPermissions(@NonNull final DecryptionContext context) {
final CryptoFailedException failure = new CryptoFailedException(
"Non interactive decryption mode.");

Expand Down

0 comments on commit f578d22

Please sign in to comment.