From b531cddc2b50490d0887d0013663cddb08585242 Mon Sep 17 00:00:00 2001 From: Mary Tran Date: Sun, 2 Dec 2018 11:21:08 -0500 Subject: [PATCH] Added hashing of passwords --- .../olympus/olympusservices/Admin.java | 4 + .../olympus/olympusservices/DBHelper.java | 38 +++++++-- .../olympus/olympusservices/HomeOwner.java | 15 ++++ .../olympusservices/HomeOwnerEditProfile.java | 4 +- .../olympus/olympusservices/LogIn.java | 3 +- .../olympusservices/PasswordEncryption.java | 80 +++++++++++++++++++ .../olympusservices/ServiceProvider.java | 39 +++++++++ .../ServiceProviderEditProfile.java | 7 +- .../olympus/olympusservices/UserType.java | 54 ++++++++++--- .../olympus/olympusservices/AdminTest.java | 3 +- .../olympusservices/DBIntegrationTest.java | 14 +++- .../olympusservices/HomeOwnerTest.java | 8 +- .../olympus/olympusservices/PasswordTest.java | 22 +++++ .../olympusservices/ServiceProviderTest.java | 8 +- .../olympus/olympusservices/UserTypeTest.java | 4 +- 15 files changed, 267 insertions(+), 36 deletions(-) create mode 100644 OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/PasswordEncryption.java create mode 100644 OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/PasswordTest.java diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Admin.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Admin.java index 8b658b4..7f8bdfa 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Admin.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Admin.java @@ -17,6 +17,10 @@ public class Admin extends UserType { super("admin", "admin", "Admin", "Admin"); } + Admin(String hash, String salt){ + super("admin", hash, salt, "Admin", "Admin"); + } + /** * The getRole() method returns a string "Admin" * the app gets role of user type objects for access diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java index 9f21cf0..9a32c55 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java @@ -27,7 +27,7 @@ import com.uottawa.olympus.olympusservices.Booking.Status; public class DBHelper extends SQLiteOpenHelper { //version of db used for update method - private static final int DB_VERSION = 6; + private static final int DB_VERSION = 7; //name of db in app data private static final String DB_NAME = "UsersDB.db"; @@ -265,7 +265,23 @@ public class DBHelper extends SQLiteOpenHelper { + ")"); case 5: db.execSQL("ALTER TABLE " + TABLE_BOOKINGS + " ADD COLUMN " + COLUMN_COMMENT + " TEXT DEFAULT ''"); + case 6: + Cursor cursor = db.query(TABLE_LOGIN, new String[]{COLUMN_USERNAME, COLUMN_PASSWORD}, null, null, + null, null, null); + if (cursor.moveToFirst()){ + for (int i = 0; i=5 && firstname.getText().toString().length()>0 + if(firstname.getText().toString().length()>0 && lastname.getText().toString().length()>0 && password.getText().toString().matches("[a-zA-Z0-9]*") && firstname.getText().toString().matches("[a-zA-Z]*") diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/LogIn.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/LogIn.java index 4fb387a..76688e1 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/LogIn.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/LogIn.java @@ -44,7 +44,8 @@ public class LogIn extends AppCompatActivity { if (dbHelper.findUserByUsername(username) != null) { UserType user = dbHelper.findUserByUsername(username); if (user.getUsername().equals(username) && - user.getPassword().equals(password)) { + PasswordEncryption.slowEquals(user.getHash(), + PasswordEncryption.encrypt(password, user.getSalt()))) { if(user.getRole()=="Admin"){ Intent intent = new Intent(getApplicationContext(),AdminWelcome.class); startActivity(intent); diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/PasswordEncryption.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/PasswordEncryption.java new file mode 100644 index 0000000..e0f91d5 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/PasswordEncryption.java @@ -0,0 +1,80 @@ +package com.uottawa.olympus.olympusservices; + +import android.os.Message; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.lang.Math; + +public class PasswordEncryption { + private static final MessageDigest MESSAGE_DIGEST; + private static final char[] POSSIBLE_CHARS; + private static final SecureRandom random; + + static{ + MessageDigest messageDigest; + try{ + messageDigest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e){ + messageDigest = null; + } + MESSAGE_DIGEST = messageDigest; + + POSSIBLE_CHARS = new char[94]; + for (int i = 33; i<127; i++){ + POSSIBLE_CHARS[i-33] = (char)i; + } + + random = new SecureRandom(); + } + + public static String encrypt(String password, String salt){ + password = salt + password; + + byte[] passwordBytes = password.getBytes(); + byte[] hashedPassword; + + MESSAGE_DIGEST.reset(); + MESSAGE_DIGEST.update(passwordBytes); + hashedPassword = MESSAGE_DIGEST.digest(); + + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < hashedPassword.length; i++) { + if ((hashedPassword[i] & 0xff) < 0x10) { + sb.append("0"); + } + + sb.append(Long.toString(hashedPassword[i] & 0xff, 16)); + } + return sb.toString(); + } + + public static String generateSalt(){ + long stringID = Math.abs(random.nextLong()); + String salt = ""; + + while(stringID > 0){ + //the least significant digit is added to nonce string first + int index = (int)(stringID%94); + salt += POSSIBLE_CHARS[index]; + stringID /= 94; + } + return salt; + } + + public static boolean slowEquals(String one, String two){ + byte[] first = one.getBytes(); + byte[] second = two.getBytes(); + + int length = first.length > second.length ? second.length : first.length; + boolean same = true; + for (int i = 0; i(); + availabilities = new int[7][4]; + this.address = address; + this.phonenumber = phonenumber; + this.companyname = companyname; + this.licensed = licensed; + this.description = description; + this.rating = 0; + } + + /** * gets the role of the UserType. * diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderEditProfile.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderEditProfile.java index cf3dc49..e91ee49 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderEditProfile.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderEditProfile.java @@ -37,15 +37,13 @@ public class ServiceProviderEditProfile extends AppCompatActivity { firstname.setText(user.getFirstname()); lastname.setText(user.getLastname()); - password.setText(user.getPassword()); + password.setText(""); companyname.setText(user.getCompanyname()); address.setText(user.getAddress()); phonenumber.setText(user.getPhonenumber()); description.setText(user.getDescription()); licensed.setChecked(user.isLicensed()); - - } /** @@ -76,7 +74,7 @@ public class ServiceProviderEditProfile extends AppCompatActivity { CheckBox licensed = findViewById(R.id.LicensedInput); //Checks for the fields - if(password.getText().toString().length()>=5 && firstname.getText().toString().length()>0 + if(firstname.getText().toString().length()>0 && lastname.getText().toString().length()>0 && companyname.getText().toString().length()>0 && address.getText().toString().length()>0 && phonenumber.getText().toString().length()>0 && password.getText().toString().matches("[a-zA-Z0-9]*") @@ -88,6 +86,7 @@ public class ServiceProviderEditProfile extends AppCompatActivity { && phonenumber.getText().toString().matches("^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?[\\s.-]?\\d{3}[\\s.-]?\\d{4}$") && address.getText().toString().replaceAll("\\s+","").length()>0) { + if(dbHelper.updateUserInfo(username, password.getText().toString(), firstname.getText().toString(), lastname.getText().toString(), address.getText().toString(), phonenumber.getText().toString(), companyname.getText().toString(), licensed.isChecked(), description.getText().toString())){ //add comment method here diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UserType.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UserType.java index 98f4766..cb6e502 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UserType.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UserType.java @@ -13,12 +13,14 @@ public abstract class UserType { //field for the username attached to the userType. String username; - //field for the password attached to the userType. - String password; + //field for the password hash attached to the userType. + String hash; //field for the firstname attached to the userType. String firstname; //field for the lastname attached to the userType. String lastname; + //field for the salt attached to the userType. + String salt; /** @@ -32,9 +34,30 @@ public abstract class UserType { */ UserType(String username, String password, String firstname, String lastname){ this.username = username; - this.password = password; this.firstname = firstname; this.lastname = lastname; + + this.salt = PasswordEncryption.generateSalt(); + this.hash = PasswordEncryption.encrypt(password, salt); + } + + /** + * Constructor filling out all the field values with given parameters + * entered by a new user for the app. + * + * @param username String object containing the username. + * @param hash String object containing the password hash. + * @param firstname String object containing the firstname. + * @param lastname String object containing the lastname. + * @param salt String object containing the salt. + */ + UserType(String username, String hash, String salt, String firstname, String lastname){ + this.username = username; + this.firstname = firstname; + this.lastname = lastname; + + this.salt = salt; + this.hash = hash; } /** @@ -54,12 +77,12 @@ public abstract class UserType { } /** - * Gets the password field of userType. + * Gets the hash field of userType. * - * @return String of the password. + * @return String of the hash. */ - public String getPassword() { - return password; + public String getHash() { + return hash; } /** @@ -80,6 +103,15 @@ public abstract class UserType { return lastname; } + /** + * Gets the salt field of userType. + * + * @return String of salt + */ + public String getSalt() { + return salt; + } + /** * Sets the username field with given parameters. * @@ -102,7 +134,8 @@ public abstract class UserType { //remember to call updateUser(String username, String password, String firstname, String lastname) //in activity whenever a setter is called. DBHelper requires a Context (Activity) to be initialized //so cannot be initialized in this class - this.password = password; + this.salt = PasswordEncryption.generateSalt(); + this.hash = PasswordEncryption.encrypt(password, salt); } /** @@ -130,8 +163,9 @@ public abstract class UserType { * @param other Usertype object that is compared to this userType. */ public boolean equals(UserType other){ - if(this.username.equals(other.username)&&this.password.equals(other.password)&& - this.firstname.equals(other.firstname)&&this.lastname.equals(other.lastname)){ + if(this.username.equals(other.username)&&this.hash.equals(other.hash)&& + this.firstname.equals(other.firstname)&&this.lastname.equals(other.lastname) + &&this.salt.equals(other.salt)){ return true; } return false; diff --git a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/AdminTest.java b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/AdminTest.java index 38008b6..f8cf183 100644 --- a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/AdminTest.java +++ b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/AdminTest.java @@ -14,13 +14,12 @@ public class AdminTest { public void testAdmin() { Admin admin = new Admin(); String username = admin.getUsername(); - String password = admin.getPassword(); String firstname = admin.getFirstname(); String lastname = admin.getLastname(); String role = admin.getRole(); assertEquals("Admin", role); assertEquals("admin", username); - assertEquals("admin", password); + assertEquals(PasswordEncryption.encrypt("admin", admin.getSalt()), admin.getHash()); assertEquals("Admin", firstname); assertEquals("Admin", lastname); } diff --git a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/DBIntegrationTest.java b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/DBIntegrationTest.java index 5370a70..89cdd5b 100644 --- a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/DBIntegrationTest.java +++ b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/DBIntegrationTest.java @@ -38,9 +38,9 @@ public class DBIntegrationTest { UserType dbUser = dbHelper.findUserByUsername("admin"); assertEquals("Admin", dbUser.getClass().getSimpleName()); assertEquals("admin", dbUser.getUsername()); - assertEquals("admin", dbUser.getPassword()); assertEquals("Admin", dbUser.getFirstname()); assertEquals("Admin", dbUser.getLastname()); + assertEquals(PasswordEncryption.encrypt("admin", dbUser.getSalt()), dbUser.getHash()); } @Test @@ -56,7 +56,8 @@ public class DBIntegrationTest { dbUser = dbHelper.findUserByUsername("mgarzon"); assertEquals("HomeOwner", dbUser.getClass().getSimpleName()); assertEquals("mgarzon", dbUser.getUsername()); - assertEquals("soccer", dbUser.getPassword()); + assertEquals(originalUser.getHash(), dbUser.getHash()); + assertEquals(originalUser.getSalt(), dbUser.getSalt()); assertEquals("Miguel", dbUser.getFirstname()); assertEquals("Garzon", dbUser.getLastname()); @@ -69,7 +70,8 @@ public class DBIntegrationTest { dbUser = dbHelper.findUserByUsername("jbO4aBF4dC"); assertEquals("ServiceProvider", dbUser.getClass().getSimpleName()); assertEquals("jbO4aBF4dC", dbUser.getUsername()); - assertEquals("seg2105", dbUser.getPassword()); + assertEquals(originalUser.getHash(), dbUser.getHash()); + assertEquals(originalUser.getSalt(), dbUser.getSalt()); assertEquals("Juan", dbUser.getFirstname()); assertEquals("Guzman", dbUser.getLastname()); @@ -171,7 +173,6 @@ public class DBIntegrationTest { dbUser = dbHelper.findUserByUsername("jbO4aBF4dC"); assertEquals("jbO4aBF4dC", dbUser.getUsername()); - assertEquals("soccer", dbUser.getPassword()); assertEquals("Juan", dbUser.getFirstname()); assertEquals("Guzman", dbUser.getLastname()); @@ -561,6 +562,11 @@ public class DBIntegrationTest { } + @Test + public void printUsersTable(){ + dbHelper.printTable("user"); + } + // Ever gotten tired of adding things at the start of a test just to delete it all again? // I have. // This is a work in progress diff --git a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/HomeOwnerTest.java b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/HomeOwnerTest.java index 47d33a8..8135894 100644 --- a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/HomeOwnerTest.java +++ b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/HomeOwnerTest.java @@ -14,9 +14,10 @@ public class HomeOwnerTest { public void testHomeOwner(){ UserType user = new HomeOwner( "John123", "1234567890", "John", "Doe" ); String role = user.getRole(); + String salt = user.getSalt(); assertEquals("HomeOwner", role); assertEquals("John123", user.getUsername()); - assertEquals("1234567890", user.getPassword()); + assertEquals( PasswordEncryption.encrypt("1234567890", salt), user.getHash()); assertEquals("John", user.getFirstname()); assertEquals("Doe", user.getLastname()); user.setUsername( "username" ); @@ -24,7 +25,10 @@ public class HomeOwnerTest { user.setFirstname( "firstname" ); user.setLastname( "lastname" ); assertNotEquals("John123", user.getUsername()); - assertNotEquals("1234567890", user.getPassword()); + assertNotEquals("1234567890", user.getHash()); + assertNotEquals("password", user.getHash()); + assertNotEquals( PasswordEncryption.encrypt("1234567890", salt), user.getHash()); + assertNotEquals(PasswordEncryption.encrypt("password", salt), user.getHash()); assertNotEquals("John", user.getFirstname()); assertNotEquals("Doe", user.getLastname()); } diff --git a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/PasswordTest.java b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/PasswordTest.java new file mode 100644 index 0000000..495e742 --- /dev/null +++ b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/PasswordTest.java @@ -0,0 +1,22 @@ +package com.uottawa.olympus.olympusservices; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class PasswordTest { + + @Test + public void testHashes(){ + String string1 = PasswordEncryption.encrypt("helloworld", "i]/S9evY\\,"); + String string2 = PasswordEncryption.encrypt("helloworld", "i]/S9evY\\,"); + + assertTrue(PasswordEncryption.slowEquals(string1, string2)); + + String string3 = PasswordEncryption.encrypt("helloworld", "i]/S9evY\\"); + assertTrue(!PasswordEncryption.slowEquals(string1, string3)); + + String string4 = PasswordEncryption.encrypt("helloworl", "i]/S9evY\\,"); + assertTrue(!PasswordEncryption.slowEquals(string1, string4)); + + } +} diff --git a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/ServiceProviderTest.java b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/ServiceProviderTest.java index 89527c1..c7bfbe5 100644 --- a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/ServiceProviderTest.java +++ b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/ServiceProviderTest.java @@ -17,8 +17,9 @@ public class ServiceProviderTest { @Test public void testServiceProvider() { + String salt = serviceprovider.getSalt(); assertEquals( "John123", serviceprovider.getUsername()); - assertEquals( "1234567890", serviceprovider.getPassword()); + assertEquals( PasswordEncryption.encrypt("1234567890", salt), serviceprovider.getHash()); assertEquals( "John", serviceprovider.getFirstname()); assertEquals( "Doe", serviceprovider.getLastname()); assertEquals( "ServiceProvider", serviceprovider.getRole()); @@ -27,7 +28,10 @@ public class ServiceProviderTest { serviceprovider.setFirstname("firstname"); serviceprovider.setLastname("lastname"); assertNotEquals("John123", serviceprovider.getUsername()); - assertNotEquals("1234567890", serviceprovider.getPassword()); + assertNotEquals("1234567890", serviceprovider.getHash()); + assertNotEquals("password", serviceprovider.getHash()); + assertNotEquals( PasswordEncryption.encrypt("1234567890", salt), serviceprovider.getHash()); + assertNotEquals(PasswordEncryption.encrypt("password", salt), serviceprovider.getHash()); assertNotEquals("John", serviceprovider.getFirstname()); assertNotEquals("Doe", serviceprovider.getLastname()); } diff --git a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/UserTypeTest.java b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/UserTypeTest.java index 8660968..a0eb09c 100644 --- a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/UserTypeTest.java +++ b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/UserTypeTest.java @@ -27,8 +27,8 @@ public class UserTypeTest { assertNotEquals( true, useradmin ); assertNotEquals( true, serviceadmin ); assertNotEquals( true, userservice ); - user.setFirstname(serviceprovider.getFirstname()); - user.setUsername(serviceprovider.getUsername()); + user = new HomeOwner(serviceprovider.getUsername(), serviceprovider.getHash(), serviceprovider.getSalt(), + serviceprovider.getFirstname(), serviceprovider.getLastname()); userservice = user.equals(serviceprovider); assertEquals( true, userservice ); }