modified README
This commit is contained in:
parent
4244b714d4
commit
f1dfa6c473
28
README.md
28
README.md
@ -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%;" >
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 ją 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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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"/>
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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"/>
|
||||||
|
|
||||||
|
|
||||||
|
@ -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>
|
@ -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>
|
@ -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>
|
BIN
screenshots/change_password.png
Normal file
BIN
screenshots/change_password.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 101 KiB |
BIN
screenshots/create_note.png
Normal file
BIN
screenshots/create_note.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
BIN
screenshots/delete_note.png
Normal file
BIN
screenshots/delete_note.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 97 KiB |
BIN
screenshots/main_screen.png
Normal file
BIN
screenshots/main_screen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
BIN
screenshots/register.png
Normal file
BIN
screenshots/register.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
Loading…
Reference in New Issue
Block a user