From 942a58d396748a63d00f29bf4c8c776b3ca3f403 Mon Sep 17 00:00:00 2001 From: Ewan Sinclair Date: Tue, 26 Apr 2011 13:28:01 -0400 Subject: [PATCH 1/7] Application no longer logs sensitive data --- .../labs/falsesecuremobile/BankingApplication.java | 6 ------ .../labs/falsesecuremobile/TransferActivity.java | 3 --- 2 files changed, 9 deletions(-) diff --git a/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java b/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java index 0418c7b..ca46a6e 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java +++ b/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java @@ -370,12 +370,6 @@ public List getAccounts() throws JSONException, IOException, Authentica throw e; } - // Log the account details - String logString = "Accounts:\n"; - for (Account a : result) { - logString += a.toString() + "\n"; - } - Log.i(TAG, logString); return result; } diff --git a/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java b/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java index e5ca272..d84f836 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java @@ -153,8 +153,6 @@ private void updateAccounts() { */ private void performTransfer() { // TODO: Check status code and act accordingly if an error is present. - Log.i(TAG, "Member Accounts [" + mFromAccount.toString() + "] [" + mToAccount.toString() - + "]"); if (mFromAccount == mToAccount) { Toast.makeText(mCtx, R.string.error_transfer_same_account, Toast.LENGTH_SHORT).show(); } else { @@ -190,7 +188,6 @@ private void performTransfer() { Log.e(TAG, e.toString()); } - Log.i(TAG, "Transferred $" + amount + " from account " +mFromAccount.getAccountNumber()+" to account " +mToAccount.getAccountNumber()); updateAccounts(); Toast.makeText(mCtx, R.string.transferscreen_success, Toast.LENGTH_SHORT).show(); launchSummaryScreen(); From 4b87da6a8a6d7bb356298d79aeda120de901bdba Mon Sep 17 00:00:00 2001 From: Ewan Sinclair Date: Tue, 26 Apr 2011 15:22:11 -0400 Subject: [PATCH 2/7] Added a check for password strength --- res/values/strings.xml | 1 + .../SetLocalPasswordActivity.java | 79 +++++++++++-------- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index a00591c..a4bd26f 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -41,6 +41,7 @@ Can\'t transfer to same account Invalid amount Passwords don\'t match + Weak password. Needs to contain an uppercase letter, a lowercase letter, a special character and be at least 6 characters long. The password checking and setting mechanism has failed. Please see your application vendor, as this is unrecoverable. The SSL mechanism has failed due to an unsupported algorithm. Please see your application vendor, as this is unrecoverable. The SSL mechanism has failed due to a key management problem. Please see your application vendor, as this is unrecoverable. diff --git a/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java b/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java index 8660d79..bf46e52 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java @@ -24,7 +24,8 @@ import android.widget.EditText; import android.widget.Toast; -/** This class prompts the user to set their local unlock password +/** + * This class prompts the user to set their local unlock password * @author Ewan Sinclair */ public class SetLocalPasswordActivity extends Activity { @@ -34,76 +35,90 @@ public class SetLocalPasswordActivity extends Activity { private Button mDoneButton; private Context mCtx; private BankingApplication mThisApplication; - + private String restUser; private String restPass; - - private final static String TAG="SetLocalPasswordActivity"; - + + private final static String TAG = "SetLocalPasswordActivity"; + /** Called when the Activity is first created */ @Override - public void onCreate(Bundle savedInstanceState){ + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.setlocalpasswordactivity); - - mCtx=this; - mThisApplication=(BankingApplication) getApplication(); - - restUser=getIntent().getStringExtra("restUser"); - restPass=getIntent().getStringExtra("restPass"); - - mPasswordField=(EditText) findViewById(R.id.setupunlockactivity_password); - mConfirmPasswordField=(EditText) findViewById(R.id.setupunlockactivity_repeat_password); - mDoneButton=(Button) findViewById(R.id.setupunlockactivity_donebutton); - + + mCtx = this; + mThisApplication = (BankingApplication) getApplication(); + + restUser = getIntent().getStringExtra("restUser"); + restPass = getIntent().getStringExtra("restPass"); + + mPasswordField = (EditText) findViewById(R.id.setupunlockactivity_password); + mConfirmPasswordField = (EditText) findViewById(R.id.setupunlockactivity_repeat_password); + mDoneButton = (Button) findViewById(R.id.setupunlockactivity_donebutton); + mDoneButton.setOnClickListener(new OnClickListener() { - + @Override public void onClick(View v) { grabAndSetPassword(); } }); - + } - + /** Grabs the two passwords entered, and sets them as the local unlock password if they match */ - private void grabAndSetPassword(){ - String pass1=mPasswordField.getText().toString(); - String pass2=mConfirmPasswordField.getText().toString(); - if(!pass1.equals(pass2)){ + private void grabAndSetPassword() { + String pass1 = mPasswordField.getText().toString(); + String pass2 = mConfirmPasswordField.getText().toString(); + if (!pass1.equals(pass2)) { Toast.makeText(mCtx, R.string.error_passwords_not_matching, Toast.LENGTH_SHORT).show(); + } else if (!isValidPassword(pass2)) { + Toast.makeText(mCtx, R.string.error_weak_password, Toast.LENGTH_LONG).show(); } else { try { mThisApplication.setCredentials(pass2, restUser, restPass); mThisApplication.unlockApplication(pass2); - } catch (NoSuchAlgorithmException e){ + } catch (NoSuchAlgorithmException e) { Toast.makeText(mCtx, R.string.error_toast_hasherror, Toast.LENGTH_LONG).show(); Log.e(TAG, e.toString()); - } catch (UnsupportedEncodingException e){ + } catch (UnsupportedEncodingException e) { Toast.makeText(mCtx, R.string.error_toast_hasherror, Toast.LENGTH_LONG).show(); Log.e(TAG, e.toString()); - } catch (JSONException e){ + } catch (JSONException e) { Toast.makeText(mCtx, R.string.error_toast_json_problem, Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); - } catch (KeyManagementException e){ + } catch (KeyManagementException e) { Toast.makeText(mCtx, R.string.error_ssl_keymanagement, Toast.LENGTH_LONG).show(); Log.e(TAG, e.toString()); - } catch (IOException e) { + } catch (IOException e) { Toast.makeText(mCtx, R.string.error_toast_rest_problem, Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (GeneralSecurityException e) { Toast.makeText(mCtx, "Crypto failure", Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (HttpException e) { - Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), Toast.LENGTH_SHORT).show(); + Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), + Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } - + Toast.makeText(mCtx, R.string.initialsetup_success, Toast.LENGTH_SHORT).show(); Intent i = new Intent(mCtx, SummaryActivity.class); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(i); } } - + + /** + * Checks a String to see if it is a valid password. + * @param password The password to check. + * @return Whether the password was strong enough. + */ + public boolean isValidPassword(String password) { + boolean valid = (password.matches(".*[A-Z].*") && password.matches(".*[a-z].*") + && password.matches(".*[0-9].*") && password.matches(".*[@#$%\\^&+=].*") && password + .length() >= 6); + return valid; + } } From fb5a696dda40c43be63f9d5ca734fae33a05cd5e Mon Sep 17 00:00:00 2001 From: Ewan Sinclair Date: Wed, 27 Apr 2011 18:26:12 -0400 Subject: [PATCH 3/7] Bugfix: fixed crash that was happening on an HTTP error notification --- .../securitycompass/labs/falsesecuremobile/LoginActivity.java | 2 +- .../labs/falsesecuremobile/SetLocalPasswordActivity.java | 2 +- .../labs/falsesecuremobile/SetServerCredentialsActivity.java | 2 +- .../labs/falsesecuremobile/TransferActivity.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/securitycompass/labs/falsesecuremobile/LoginActivity.java b/src/com/securitycompass/labs/falsesecuremobile/LoginActivity.java index 5a6f5e3..0c951e0 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/LoginActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/LoginActivity.java @@ -108,7 +108,7 @@ private void performLogin() { Toast.makeText(mCtx, R.string.error_ssl_general, Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (HttpException e) { - Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), Toast.LENGTH_SHORT).show(); + Toast.makeText(mCtx, getString(R.string.error_toast_http_error) + e.getStatusCode(), Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (IOException e) { Toast.makeText(mCtx, R.string.error_toast_rest_problem, Toast.LENGTH_SHORT).show(); diff --git a/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java b/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java index bf46e52..b9e6600 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java @@ -98,7 +98,7 @@ private void grabAndSetPassword() { Toast.makeText(mCtx, "Crypto failure", Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (HttpException e) { - Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), + Toast.makeText(mCtx, getString(R.string.error_toast_http_error) + e.getStatusCode(), Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } diff --git a/src/com/securitycompass/labs/falsesecuremobile/SetServerCredentialsActivity.java b/src/com/securitycompass/labs/falsesecuremobile/SetServerCredentialsActivity.java index 2e9d5bd..ecbef54 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/SetServerCredentialsActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/SetServerCredentialsActivity.java @@ -78,7 +78,7 @@ private void setServerCredentials() { Toast.makeText(mCtx, R.string.error_ssl_algorithm, Toast.LENGTH_LONG).show(); Log.e(TAG, e.toString()); } catch (HttpException e) { - Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), + Toast.makeText(mCtx, getString(R.string.error_toast_http_error) + e.getStatusCode(), Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (IOException e) { diff --git a/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java b/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java index d84f836..b287b1c 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java @@ -179,7 +179,7 @@ private void performTransfer() { Toast.makeText(mCtx, R.string.error_ssl_algorithm, Toast.LENGTH_LONG).show(); Log.e(TAG, e.toString()); } catch (HttpException e) { - Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), + Toast.makeText(mCtx, getString(R.string.error_toast_http_error) + e.getStatusCode(), Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (IOException e) { From 15e1e12a80ce50a03c5c231570d444b811dce729 Mon Sep 17 00:00:00 2001 From: Ewan Sinclair Date: Mon, 16 May 2011 14:07:05 -0400 Subject: [PATCH 4/7] Bugfix: fixed crash that was happening on an HTTP error notification --- .../labs/falsesecuremobile/LoginActivity.java | 2 +- .../labs/falsesecuremobile/SetLocalPasswordActivity.java | 9 ++++----- .../falsesecuremobile/SetServerCredentialsActivity.java | 3 +-- .../labs/falsesecuremobile/TransferActivity.java | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/com/securitycompass/labs/falsesecuremobile/LoginActivity.java b/src/com/securitycompass/labs/falsesecuremobile/LoginActivity.java index 5a6f5e3..0c951e0 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/LoginActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/LoginActivity.java @@ -108,7 +108,7 @@ private void performLogin() { Toast.makeText(mCtx, R.string.error_ssl_general, Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (HttpException e) { - Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), Toast.LENGTH_SHORT).show(); + Toast.makeText(mCtx, getString(R.string.error_toast_http_error) + e.getStatusCode(), Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (IOException e) { Toast.makeText(mCtx, R.string.error_toast_rest_problem, Toast.LENGTH_SHORT).show(); diff --git a/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java b/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java index bf46e52..a99a1cc 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/SetLocalPasswordActivity.java @@ -88,7 +88,10 @@ private void grabAndSetPassword() { } catch (JSONException e) { Toast.makeText(mCtx, R.string.error_toast_json_problem, Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); - } catch (KeyManagementException e) { + } catch (HttpException e) { + Toast.makeText(mCtx, getString(R.string.error_toast_http_error) + e.getStatusCode(), Toast.LENGTH_SHORT).show(); + Log.e(TAG, e.toString()); + } catch (KeyManagementException e){ Toast.makeText(mCtx, R.string.error_ssl_keymanagement, Toast.LENGTH_LONG).show(); Log.e(TAG, e.toString()); } catch (IOException e) { @@ -97,10 +100,6 @@ private void grabAndSetPassword() { } catch (GeneralSecurityException e) { Toast.makeText(mCtx, "Crypto failure", Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); - } catch (HttpException e) { - Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), - Toast.LENGTH_SHORT).show(); - Log.e(TAG, e.toString()); } Toast.makeText(mCtx, R.string.initialsetup_success, Toast.LENGTH_SHORT).show(); diff --git a/src/com/securitycompass/labs/falsesecuremobile/SetServerCredentialsActivity.java b/src/com/securitycompass/labs/falsesecuremobile/SetServerCredentialsActivity.java index 2e9d5bd..f72c454 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/SetServerCredentialsActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/SetServerCredentialsActivity.java @@ -78,8 +78,7 @@ private void setServerCredentials() { Toast.makeText(mCtx, R.string.error_ssl_algorithm, Toast.LENGTH_LONG).show(); Log.e(TAG, e.toString()); } catch (HttpException e) { - Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), - Toast.LENGTH_SHORT).show(); + Toast.makeText(mCtx, getString(R.string.error_toast_http_error) + e.getStatusCode(), Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (IOException e) { Toast.makeText(mCtx, R.string.error_toast_rest_problem, Toast.LENGTH_SHORT).show(); diff --git a/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java b/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java index d84f836..b287b1c 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java +++ b/src/com/securitycompass/labs/falsesecuremobile/TransferActivity.java @@ -179,7 +179,7 @@ private void performTransfer() { Toast.makeText(mCtx, R.string.error_ssl_algorithm, Toast.LENGTH_LONG).show(); Log.e(TAG, e.toString()); } catch (HttpException e) { - Toast.makeText(mCtx, R.string.error_toast_http_error + e.getStatusCode(), + Toast.makeText(mCtx, getString(R.string.error_toast_http_error) + e.getStatusCode(), Toast.LENGTH_SHORT).show(); Log.e(TAG, e.toString()); } catch (IOException e) { From e8e699bba2f14b89d4cec259c8050916562ed7c6 Mon Sep 17 00:00:00 2001 From: Ewan Sinclair Date: Mon, 16 May 2011 19:08:36 -0400 Subject: [PATCH 5/7] Set BankingApplication's unlock method to blank all details --- .../falsesecuremobile/BankingApplication.java | 121 ++++++++++-------- 1 file changed, 69 insertions(+), 52 deletions(-) diff --git a/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java b/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java index ca46a6e..b2865e4 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java +++ b/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java @@ -38,7 +38,7 @@ public class BankingApplication extends Application { private boolean locked; private String cleartextServerUser; private String cleartextServerPass; - + private int foregroundedActivities; private Handler timingHandler; private CryptoTool mCipher; @@ -64,7 +64,7 @@ public class BankingApplication extends Application { public static final String PREF_REST_PASSWORD_IV = "serverpassiv"; /** The initialisation vector for the encrypted banking service username */ public static final String PREF_REST_USER_IV = "serveruseriv"; - public static String PREF_DERIVED_KEY_SALT="derivedkeysalt"; + public static String PREF_DERIVED_KEY_SALT = "derivedkeysalt"; /** A tag to identify the class if it logs anything */ public static final String TAG = "BankingApplication"; @@ -76,7 +76,7 @@ public void onCreate() { timingHandler = new Handler(); foregroundedActivities = 0; locked = true; - mCipher=new CryptoTool(); + mCipher = new CryptoTool(); } /** @@ -191,9 +191,17 @@ public int performLogin(String username, String password) throws JSONException, /** Performs all operations necessary to secure the application. */ public void lockApplication() { - cleartextServerUser=""; - cleartextServerPass=""; + cleartextServerUser = ""; + cleartextServerPass = ""; + sessionKey = ""; + sessionCreateDate = ""; + if (mCryptoKey != null) { + for (byte b : mCryptoKey) { + b = 'x'; + } + } locked = true; + System.gc(); } /** @@ -209,12 +217,16 @@ public void lockApplication() { * @throws HttpException if the HTTP/S request failed */ public int unlockApplication(String password) throws UnsupportedEncodingException, - NoSuchAlgorithmException, IOException, JSONException, KeyManagementException, GeneralSecurityException, HttpException { - + NoSuchAlgorithmException, IOException, JSONException, KeyManagementException, + GeneralSecurityException, HttpException { + if (checkPassword(password)) { - mCryptoKey=mCipher.genKeyPwkdf2(password, getPbkSalt(), CryptoTool.NUM_ITERATIONS).getEncoded(); - cleartextServerUser = mCipher.decryptB64String(getRestUsername(), mCryptoKey, getRestUserNameIv()); - cleartextServerPass = mCipher.decryptB64String(getRestPassword(), mCryptoKey, getRestPasswordIv()); + mCryptoKey = mCipher.genKeyPwkdf2(password, getPbkSalt(), CryptoTool.NUM_ITERATIONS) + .getEncoded(); + cleartextServerUser = mCipher.decryptB64String(getRestUsername(), mCryptoKey, + getRestUserNameIv()); + cleartextServerPass = mCipher.decryptB64String(getRestPassword(), mCryptoKey, + getRestPasswordIv()); int statusCode = performLogin(cleartextServerUser, cleartextServerPass); if (statusCode == RestClient.NULL_ERROR) { locked = false; @@ -232,21 +244,22 @@ public boolean isLocked() { return locked; } - - /**Returns the AES key currently in use. + /** + * Returns the AES key currently in use. * @return The AES key currently in use. */ - public byte[] getCryptoKey(){ + public byte[] getCryptoKey() { return mCryptoKey; } - - /** Returns the salt to be used for the password-generated AES key. + + /** + * Returns the salt to be used for the password-generated AES key. * @return The salt to be used for the password-generated AES key. */ - public byte[] getPbkSalt(){ + public byte[] getPbkSalt() { return Base64.decode(getSharedPrefs().getString(PREF_DERIVED_KEY_SALT, ""), Base64.DEFAULT); } - + /** * Returns the stored username for the REST service. * @return The stored username for the REST service. @@ -254,12 +267,12 @@ public byte[] getPbkSalt(){ public String getRestUsername() { return getSharedPrefs().getString(PREF_REST_USER, ""); } - + /** * Returns the IV for the stored username for the REST service. * @return The IV for the stored username for the REST service. */ - public byte[] getRestUserNameIv(){ + public byte[] getRestUserNameIv() { return Base64.decode(getSharedPrefs().getString(PREF_REST_USER_IV, ""), Base64.DEFAULT); } @@ -270,7 +283,7 @@ public byte[] getRestUserNameIv(){ public String getRestPassword() { return getSharedPrefs().getString(PREF_REST_PASSWORD, ""); } - + /** * Returns the IV for the stored password for the REST service. * @return The IV for the stored password for the REST service. @@ -285,14 +298,15 @@ public byte[] getRestPasswordIv() { * @param password The password to set. * @throws GeneralSecurityException if a cryptographic operation failed */ - public void setServerCredentials(String username, String password) throws GeneralSecurityException { - - byte[] userIv=mCipher.getIv(); - byte[] passwordIv=mCipher.getIv(); - - String cryptUsername=mCipher.encryptToB64String(username, mCryptoKey, userIv); - String cryptPassword=mCipher.encryptToB64String(password, mCryptoKey, passwordIv); - + public void setServerCredentials(String username, String password) + throws GeneralSecurityException { + + byte[] userIv = mCipher.getIv(); + byte[] passwordIv = mCipher.getIv(); + + String cryptUsername = mCipher.encryptToB64String(username, mCryptoKey, userIv); + String cryptPassword = mCipher.encryptToB64String(password, mCryptoKey, passwordIv); + Editor e = getSharedPrefs().edit(); e.putString(PREF_REST_USER, cryptUsername); e.putString(PREF_REST_PASSWORD, cryptPassword); @@ -300,7 +314,7 @@ public void setServerCredentials(String username, String password) throws Genera e.putString(PREF_REST_PASSWORD_IV, new String(Base64.encode(passwordIv, Base64.DEFAULT))); e.commit(); } - + /** * Sets the local password, accomplished by storing a hashcode. * @param password The plain String version of the password to set. @@ -309,45 +323,49 @@ public void setServerCredentials(String username, String password) throws Genera */ public void setLocalPassword(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { - + // First we generate a random salt SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); byte[] saltByteArray = new byte[32]; random.nextBytes(saltByteArray); - + // Perform the hash, getting a Base64 encoded String String hashString = hash(password, saltByteArray); - + // Base64 encode the salt, store our strings byte[] b64Salt = Base64.encode(saltByteArray, Base64.DEFAULT); String saltString = new String(b64Salt); - + Editor e = getSharedPrefs().edit(); e.putString(PREF_LOCALPASS_HASH, hashString); e.putString(PREF_LOCALPASS_SALT, saltString); e.commit(); } - /** Generates a key using PBKDF2 and uses it to encrypt and set the banking service credentials. Also sets the local password (which will be checked by hash before being used for generating a key). + /** + * Generates a key using PBKDF2 and uses it to encrypt and set the banking service credentials. + * Also sets the local password (which will be checked by hash before being used for generating + * a key). * @param localPass The local password to set. * @param restUser The username for the banking service. * @param restPass The password for the banking service. * @throws GeneralSecurityException if a cryptographic operation failed. - * @throws UnsupportedEncodingException if Base64 encoding is unavailable. + * @throws UnsupportedEncodingException if Base64 encoding is unavailable. */ - public void setCredentials(String localPass, String restUser, String restPass) throws GeneralSecurityException, UnsupportedEncodingException{ - - Editor e=getSharedPrefs().edit(); - byte[] salt=mCipher.getSalt(); - String b64Salt=new String(Base64.encode(salt, Base64.DEFAULT)); + public void setCredentials(String localPass, String restUser, String restPass) + throws GeneralSecurityException, UnsupportedEncodingException { + + Editor e = getSharedPrefs().edit(); + byte[] salt = mCipher.getSalt(); + String b64Salt = new String(Base64.encode(salt, Base64.DEFAULT)); e.putString(PREF_DERIVED_KEY_SALT, b64Salt); e.commit(); - - mCryptoKey=mCipher.genKeyPwkdf2(localPass, salt, CryptoTool.NUM_ITERATIONS).getEncoded(); - + + mCryptoKey = mCipher.genKeyPwkdf2(localPass, salt, CryptoTool.NUM_ITERATIONS).getEncoded(); + setLocalPassword(localPass); setServerCredentials(restUser, restPass); - + } /** @@ -374,8 +392,7 @@ public List getAccounts() throws JSONException, IOException, Authentica } /** - * Downloads a statement and displays it. - * within this class. + * Downloads a statement and displays it. within this class. * @throws IOException if network communication failed * @throws NoSuchAlgorithmException if the algorithm used to hash the password is unavilable * @throws KeyManagementException if the server's SSL certificate couldn't be trusted @@ -388,18 +405,18 @@ public void downloadStatement() throws IOException, NoSuchAlgorithmException, String statementHtml = restClient.getStatement(getRestServer(), getPort()); - CryptoTool cipher=new CryptoTool(); - byte[] iv=cipher.getIv(); + CryptoTool cipher = new CryptoTool(); + byte[] iv = cipher.getIv(); byte[] ciphertext = cipher.encrypt(statementHtml.getBytes(), mCryptoKey, iv); - - String timestamp=Long.toString(System.currentTimeMillis()); - + + String timestamp = Long.toString(System.currentTimeMillis()); + FileOutputStream outputFileStream = openFileOutput(timestamp + ".statement", MODE_PRIVATE); outputFileStream.write(ciphertext); outputFileStream.flush(); outputFileStream.close(); - + outputFileStream = openFileOutput(timestamp + ".iv", MODE_PRIVATE); outputFileStream.write(iv); From f73bbecb3ee4c29f80b9e37056990d83bd7c5295 Mon Sep 17 00:00:00 2001 From: Ewan Sinclair Date: Wed, 18 May 2011 16:37:07 -0400 Subject: [PATCH 6/7] Bugfix: Fixed null pointer problem when clearing empty statements dir --- .../labs/falsesecuremobile/BankingApplication.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java b/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java index b2865e4..b32d9c8 100644 --- a/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java +++ b/src/com/securitycompass/labs/falsesecuremobile/BankingApplication.java @@ -430,8 +430,10 @@ public void downloadStatement() throws IOException, NoSuchAlgorithmException, public void clearStatements() { File downloadDir = getFilesDir(); File[] directoryContents = downloadDir.listFiles(); - for (File f : directoryContents) { - f.delete(); + if (directoryContents != null) { + for (File f : directoryContents) { + f.delete(); + } } } From 8318d0136bc29ffc428bdfe6aa89db83c1ebd608 Mon Sep 17 00:00:00 2001 From: Maxim Veytsman Date: Wed, 6 Jul 2011 11:31:32 -0400 Subject: [PATCH 7/7] added license --- LICENSE | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e170fcc --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011, Security Compass +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by Security Compass. +4. Neither the name of Security Compass nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Security Compass ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL Security Compass BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE.