modified README

This commit is contained in:
mikgaw@st.amu.edu.pl 2024-02-18 16:38:12 +01:00
parent 4244b714d4
commit f1dfa6c473
17 changed files with 63 additions and 39 deletions

View File

@ -1,3 +1,29 @@
# AES-secured-notepad # AES-secured-notepad
To bezpieczny notatnik szyfrujący dane algorytmem AES-256. Głównym celem projektu jest zastosowanie jak najlepszych mechanizmów szyfrujących do bezpiecznego przechowywania notatek. Dostęp do notatek wymaga każdorazowo zalogowania z użyciem hasła. Aplikacja jest przysotosowana do obsługi wielu użytkowników.
### Wykorzystane mechanizmy bezpieczeństwa
1. Maksymalnie 5 prób logowania na 1 minutę. Zabezpiecza to przed atakami brute-force.
2. Hasło użytkownika jest haszowane z wykorzystniem losowej soli oraz funkcji key-stretching która wynokuje 1000 iteracji.
3. Klucz do szyfrowania notatek algorymtm AES-256 jest generowany z hasła. Program wykorzystuje w tym celu PBKDF2 z HMAC-256. Liczba iteracji key-strethingu to 65536.
4. Szyforwanie notatni odbywa się w trybie CBC z losowym wektorem początkowym.
5. Przy każdej edycji/usunięciu/dodaniu notatni wszystkie dane zostają przeszyfrowane z wykorzystniem nowej soli oraz nowego wektora początkowego. Wpływa to co prawda na płynność działania aplikacji, lecz jej głównym celem jest zastosowanie mechanizmów krytpograficznych.
### Zrzuty ekranu z działania aplikacji
<img src="screenshots/register.png" alt="Register screen" style="width: 40%;" >
<img src="screenshots/main_screen.png" alt="Main screen" style="width: 40%;" >
<img src="screenshots/create_note.png" alt="Create note" style="width: 40%;" >
<img src="screenshots/change_password.png" alt="Change password" style="width: 40%;" >
<img src="screenshots/delete_note.png" alt="Delete note" style="width: 40%;" >

View File

@ -106,7 +106,7 @@ public class MainActivity extends AppCompatActivity {
return; return;
} }
if(!validatePassword(newPassword)){ if(!Utility.validatePassword(newPassword)){
Toast.makeText(MainActivity.this, "New password to weak!", Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, "New password to weak!", Toast.LENGTH_SHORT).show();
return; return;
} }
@ -240,13 +240,7 @@ public class MainActivity extends AppCompatActivity {
private boolean validatePassword(String password){
final String PASSWORD_PATTERN = "^(?=.*[0-9])(?=.*[A-Z])(.{8,})$";
Pattern pattern = Pattern.compile(PASSWORD_PATTERN);
Matcher matcher = pattern.matcher(password);
return matcher.matches();
}
private void updatePassword(String hashedEmail, String newPassword) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, InvalidKeyException { private void updatePassword(String hashedEmail, String newPassword) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, InvalidKeyException {
SharedPreferences sharedPreferences = getSharedPreferences(SHARED_NAME_CREDENTIALS, MODE_PRIVATE); SharedPreferences sharedPreferences = getSharedPreferences(SHARED_NAME_CREDENTIALS, MODE_PRIVATE);
@ -306,12 +300,10 @@ public class MainActivity extends AppCompatActivity {
} }
} }
//tutaj muszę wygenerować randomowy iv. Używam go do enkrypcji i zapisuje do shared jako string
IvParameterSpec iv = UtilityAES.generateIv(); IvParameterSpec iv = UtilityAES.generateIv();
String ivString = ivToString(iv); String ivString = ivToString(iv);
saveIvStringToShared(ivString); saveIvStringToShared(ivString);
//tutaj generuje randomową sól2 używam do enkrypcji i zapisuje do skared
byte[] salt2Bytes = Utility.generateSalt(); byte[] salt2Bytes = Utility.generateSalt();
String salt2String = bytesToSalt2String(salt2Bytes); String salt2String = bytesToSalt2String(salt2Bytes);
saveSalt2StringToPrefs(salt2String); saveSalt2StringToPrefs(salt2String);
@ -331,11 +323,9 @@ public class MainActivity extends AppCompatActivity {
SharedPreferences sharedPreferences = getSharedPreferences(SHARED_NAME_NOTES, MODE_PRIVATE); SharedPreferences sharedPreferences = getSharedPreferences(SHARED_NAME_NOTES, MODE_PRIVATE);
int noteCount = sharedPreferences.getInt("notecount_" + HASHED_EMAIL, 0); int noteCount = sharedPreferences.getInt("notecount_" + HASHED_EMAIL, 0);
//tutaj muszę pobrać iv z shared i skonvertować do dobrego formatu
String ivString = getIVStringFromShared(); String ivString = getIVStringFromShared();
IvParameterSpec iv = stringToIv(ivString); IvParameterSpec iv = stringToIv(ivString);
//tutaj pobieram sól2 z shared i używam do dekrypcji
String salt2String = getSalt2StringFromShared(); String salt2String = getSalt2StringFromShared();
byte[] salt2Bytes = Salt2StringToBytes(salt2String); byte[] salt2Bytes = Salt2StringToBytes(salt2String);

View File

@ -36,27 +36,24 @@ public class Register extends AppCompatActivity {
buttonReg = findViewById(R.id.btn_register); buttonReg = findViewById(R.id.btn_register);
loginNowTextView = findViewById(R.id.loginNow); loginNowTextView = findViewById(R.id.loginNow);
//goes to login page
loginNowTextView.setOnClickListener(view -> { loginNowTextView.setOnClickListener(view -> {
Intent intent = new Intent(getApplicationContext(), Login.class); Intent intent = new Intent(getApplicationContext(), Login.class);
startActivity(intent); startActivity(intent);
finish(); // finishes current activity finish();
}); });
//when register button is clicked
buttonReg.setOnClickListener(view -> { buttonReg.setOnClickListener(view -> {
String email, hashedEmail, password, hashedPassword; String email, hashedEmail, password, hashedPassword;
email = String.valueOf(editTextEmail.getText()); email = String.valueOf(editTextEmail.getText());
password = String.valueOf(editTextPassword.getText()); password = String.valueOf(editTextPassword.getText());
//checks if email field is not empty
if (TextUtils.isEmpty(email)){ if (TextUtils.isEmpty(email)){
Toast.makeText(Register.this, "Enter email!", Toast.LENGTH_SHORT).show(); Toast.makeText(Register.this, "Enter email!", Toast.LENGTH_SHORT).show();
return; return;
} }
//checks if password field is not empty
if (TextUtils.isEmpty(password)){ if (TextUtils.isEmpty(password)){
Toast.makeText(Register.this, "Enter password!", Toast.LENGTH_SHORT).show(); Toast.makeText(Register.this, "Enter password!", Toast.LENGTH_SHORT).show();
return; return;
@ -64,22 +61,22 @@ public class Register extends AppCompatActivity {
hashedEmail = Utility.hashEmail(email); hashedEmail = Utility.hashEmail(email);
//checks if given username is already registered in database
if (checkIfUserExists(hashedEmail)){ if (checkIfUserExists(hashedEmail)){
editTextEmail.setText(""); editTextEmail.setText("");
editTextPassword.setText(""); editTextPassword.setText("");
Toast.makeText(Register.this, "Account with this username already exists!", Toast.LENGTH_SHORT).show(); Toast.makeText(Register.this, "Account with this username already exists!", Toast.LENGTH_SHORT).show();
return; return;
} }
//checks if email has correct format
if (!validateEmail(email)){ if (!validateEmail(email)){
editTextPassword.setText(""); editTextPassword.setText("");
Toast.makeText(Register.this, "Email format not correct!", Toast.LENGTH_SHORT).show(); Toast.makeText(Register.this, "Email format not correct!", Toast.LENGTH_SHORT).show();
return; return;
} }
//checks password requirements
if (!validatePassword(password)){ if (!Utility.validatePassword(password)){
Toast.makeText(Register.this, "Password to weak!", Toast.LENGTH_SHORT).show(); Toast.makeText(Register.this, "Password to short! Must have at least 7 characters.", Toast.LENGTH_SHORT).show();
return; return;
} }

View File

@ -7,6 +7,8 @@ import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec; import java.security.spec.KeySpec;
import java.util.Base64; import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKeyFactory;
@ -59,5 +61,9 @@ public class Utility {
} }
} }
protected static boolean validatePassword(String password){
return password.length() > 6;
}
} }

View File

@ -24,9 +24,8 @@ public class UtilityAES {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256); KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return secret; return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
} }
public static String encrypt(String algorithm, String input, SecretKey key, IvParameterSpec iv) throws public static String encrypt(String algorithm, String input, SecretKey key, IvParameterSpec iv) throws

View File

@ -21,7 +21,7 @@
android:layout_weight="1" android:layout_weight="1"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:background="@drawable/rectangular_button_background" android:background="@drawable/rectangular_button_background"
android:text="Log Out" /> android:text="@string/log_out" />
<Button <Button
android:id="@+id/btn_change_password" android:id="@+id/btn_change_password"
@ -30,7 +30,7 @@
android:layout_weight="1" android:layout_weight="1"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:background="@drawable/rectangular_button_background" android:background="@drawable/rectangular_button_background"
android:text="Change Password" /> android:text="@string/change_password" />
<Button <Button
android:id="@+id/btn_add_note" android:id="@+id/btn_add_note"
@ -38,7 +38,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:background="@drawable/rectangular_button_background" android:background="@drawable/rectangular_button_background"
android:text="Add Note" /> android:text="@string/add_note" />
</LinearLayout> </LinearLayout>
@ -46,7 +46,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="18dp" android:layout_height="18dp"
android:layout_marginTop="15dp" android:layout_marginTop="15dp"
android:text="Notes:" android:text="@string/notes"
android:textStyle="bold"/> android:textStyle="bold"/>
<ScrollView <ScrollView

View File

@ -8,13 +8,13 @@
android:id="@+id/noteTitleEditText" android:id="@+id/noteTitleEditText"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Note Title"/> android:hint="@string/note_title"/>
<EditText <EditText
android:id="@+id/noteContentEditText" android:id="@+id/noteContentEditText"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Note Content" android:hint="@string/note_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:inputType="textMultiLine" android:inputType="textMultiLine"
android:minLines="5"/> android:minLines="5"/>

View File

@ -17,7 +17,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
android:text="Note Title" android:text="@string/note_title"
/> />
<TextView <TextView
@ -25,7 +25,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:text="Note Content" android:text="@string/note_content"
/> />
</LinearLayout> </LinearLayout>

View File

@ -8,21 +8,21 @@
android:id="@+id/editTextOldPassword" android:id="@+id/editTextOldPassword"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Enter Old Password" android:hint="@string/enter_old_password"
android:inputType="textPassword"/> android:inputType="textPassword"/>
<EditText <EditText
android:id="@+id/editTextNewPassword" android:id="@+id/editTextNewPassword"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Enter New Password" android:hint="@string/enter_new_password"
android:inputType="textPassword"/> android:inputType="textPassword"/>
<EditText <EditText
android:id="@+id/editTextConfirmPassword" android:id="@+id/editTextConfirmPassword"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Confirm New Password" android:hint="@string/confirm_new_password"
android:inputType="textPassword"/> android:inputType="textPassword"/>

View File

@ -1,7 +1,5 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.BSMnotatnik" parent="Theme.AppCompat.DayNight.NoActionBar"> <style name="Base.Theme.BSMnotatnik" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style> </style>
</resources> </resources>

View File

@ -9,4 +9,13 @@
<string name="click_to_login">Click to login</string> <string name="click_to_login">Click to login</string>
<string name="click_to_register">Click to register</string> <string name="click_to_register">Click to register</string>
<string name="logout_btn_txt">logout</string> <string name="logout_btn_txt">logout</string>
<string name="log_out">Log Out</string>
<string name="change_password">Change Password</string>
<string name="add_note">Add Note</string>
<string name="notes">Notes:</string>
<string name="note_title">Note Title</string>
<string name="note_content">Note Content</string>
<string name="enter_old_password">Enter Old Password</string>
<string name="enter_new_password">Enter New Password</string>
<string name="confirm_new_password">Confirm New Password</string>
</resources> </resources>

View File

@ -3,5 +3,4 @@
<style name="Base.Theme.BSMnotatnik" parent="Theme.AppCompat.Light.NoActionBar"> <style name="Base.Theme.BSMnotatnik" parent="Theme.AppCompat.Light.NoActionBar">
</style> </style>
</resources> </resources>

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

BIN
screenshots/create_note.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
screenshots/delete_note.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
screenshots/main_screen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
screenshots/register.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB