wszystko działa - przed sprzataniem

This commit is contained in:
mikgaw@st.amu.edu.pl 2023-12-05 21:56:27 +01:00
parent cca9f2c1da
commit 3b1d7039d0
3 changed files with 107 additions and 131 deletions

View File

@ -115,7 +115,7 @@ public class Login extends AppCompatActivity {
Intent intent = new Intent(getApplicationContext(), MainActivity.class); Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra("CURRENT_USER_EMAIL_HASH", hashedemail); intent.putExtra("CURRENT_USER_EMAIL_HASH", hashedemail);
//intent.putExtra("KEY", getKeyFromPassword(password, getSalt2(hashedemail))); //intent.putExtra("KEY", getKeyFromPassword(password, getSalt2(hashedemail)));
intent.putExtra("KEY", password); intent.putExtra("PAS", password);
startActivity(intent); startActivity(intent);
finish(); finish();

View File

@ -14,27 +14,21 @@ import android.widget.Toast;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64; import java.util.Base64;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException; import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException; import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
@ -42,7 +36,7 @@ public class MainActivity extends AppCompatActivity {
private static final String SHARED_NAME_CREDENTIALS = "Credentials"; private static final String SHARED_NAME_CREDENTIALS = "Credentials";
private static final String SHARED_NAME_NOTES = "Notes"; private static final String SHARED_NAME_NOTES = "Notes";
private static String HASHED_EMAIL = ""; private static String HASHED_EMAIL = "";
private static String KEY = ""; private static String PAS = "";
private List<Note> noteList; private List<Note> noteList;
private LinearLayout notesContainer; private LinearLayout notesContainer;
@ -55,25 +49,14 @@ public class MainActivity extends AppCompatActivity {
Intent intent = getIntent(); Intent intent = getIntent();
String current_username_hashed = intent.getStringExtra("CURRENT_USER_EMAIL_HASH"); String current_username_hashed = intent.getStringExtra("CURRENT_USER_EMAIL_HASH");
HASHED_EMAIL = current_username_hashed; HASHED_EMAIL = current_username_hashed;
KEY = intent.getStringExtra("KEY"); PAS = intent.getStringExtra("PAS");
notesContainer = findViewById(R.id.notesContainer); notesContainer = findViewById(R.id.notesContainer);
noteList = new ArrayList<>(); noteList = new ArrayList<>();
try { try {
loadNotesFromPreferencesToList(); loadNotesFromPreferencesToList();
} catch (NoSuchAlgorithmException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException(e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(e);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
} catch (BadPaddingException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -94,8 +77,6 @@ public class MainActivity extends AppCompatActivity {
private void logOut(){ private void logOut(){
Toast.makeText(getApplicationContext(), "Logout Successful!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getApplicationContext(), Login.class); Intent intent = new Intent(getApplicationContext(), Login.class);
startActivity(intent); startActivity(intent);
finish(); finish();
@ -137,23 +118,9 @@ public class MainActivity extends AppCompatActivity {
if (newPassword.equals(confirmPassword)) { if (newPassword.equals(confirmPassword)) {
try { try {
updatePassword(hashedEmail, newPassword); updatePassword(hashedEmail, newPassword);
} catch (InvalidAlgorithmParameterException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(e);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException(e);
} catch (BadPaddingException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
Toast.makeText(MainActivity.this, "Password Changed", Toast.LENGTH_SHORT).show();
} else { } else {
Toast.makeText(MainActivity.this, "New passwords don't match!", Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, "New passwords don't match!", Toast.LENGTH_SHORT).show();
} }
@ -189,19 +156,7 @@ public class MainActivity extends AppCompatActivity {
try { try {
saveNotesToPreferences("add"); saveNotesToPreferences("add");
} catch (NoSuchAlgorithmException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException(e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(e);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
} catch (BadPaddingException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
createNoteView(note); createNoteView(note);
@ -236,19 +191,7 @@ public class MainActivity extends AppCompatActivity {
if (!title.isEmpty() && !content.isEmpty()){ if (!title.isEmpty() && !content.isEmpty()){
try { try {
deleteNoteAndRefresh(note); deleteNoteAndRefresh(note);
} catch (InvalidAlgorithmParameterException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(e);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException(e);
} catch (BadPaddingException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -259,19 +202,7 @@ public class MainActivity extends AppCompatActivity {
try { try {
saveNotesToPreferences("add"); saveNotesToPreferences("add");
} catch (NoSuchAlgorithmException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException(e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(e);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
} catch (BadPaddingException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
createNoteView(note); createNoteView(note);
@ -279,7 +210,6 @@ public class MainActivity extends AppCompatActivity {
Toast.makeText(MainActivity.this, "Enter title and content!", Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, "Enter title and content!", Toast.LENGTH_SHORT).show();
} }
}); });
builder.setNegativeButton("Cancel", (dialogInterface, i) -> dialogInterface.dismiss()); builder.setNegativeButton("Cancel", (dialogInterface, i) -> dialogInterface.dismiss());
@ -296,19 +226,7 @@ public class MainActivity extends AppCompatActivity {
builder.setPositiveButton("Delete", (dialogInterface, i) -> { builder.setPositiveButton("Delete", (dialogInterface, i) -> {
try { try {
deleteNoteAndRefresh(note); deleteNoteAndRefresh(note);
} catch (InvalidAlgorithmParameterException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(e);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException(e);
} catch (BadPaddingException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
}); });
@ -340,14 +258,14 @@ public class MainActivity extends AppCompatActivity {
editor.putString("user_" + hashedEmail, hashedNewPassword); editor.putString("user_" + hashedEmail, hashedNewPassword);
editor.apply(); editor.apply();
KEY = newPassword; PAS = newPassword;
saveNotesToPreferences(""); saveNotesToPreferences("");
} }
private boolean validateOldPassword(String hashedEmail, String oldPassword){ private boolean validateOldPassword(String hashedEmail, String oldPassword){
byte[] salt = getSaltForUser(hashedEmail, false); byte[] salt = getSaltForUser(hashedEmail, false);
String hashedOldPassword = Utility.hashCredential(oldPassword, salt, 1000); String hashedOldPassword = Utility.hashCredential(oldPassword, salt, 1000);
String hashedCorrectPassword = gerPasswrodHashFromShared(hashedEmail); String hashedCorrectPassword = gerPasswordHashFromShared(hashedEmail);
assert hashedOldPassword != null; assert hashedOldPassword != null;
return hashedOldPassword.equals(hashedCorrectPassword); return hashedOldPassword.equals(hashedCorrectPassword);
@ -367,7 +285,7 @@ public class MainActivity extends AppCompatActivity {
} }
private String gerPasswrodHashFromShared(String hashedEmail){ private String gerPasswordHashFromShared(String hashedEmail){
SharedPreferences sharedPreferences = getSharedPreferences(SHARED_NAME_CREDENTIALS, MODE_PRIVATE); SharedPreferences sharedPreferences = getSharedPreferences(SHARED_NAME_CREDENTIALS, MODE_PRIVATE);
return sharedPreferences.getString("user_" + hashedEmail, "err"); return sharedPreferences.getString("user_" + hashedEmail, "err");
} }
@ -386,10 +304,15 @@ 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();
String ivString = ivToString(iv);
saveIvStringToShared(ivString);
editor.putInt("notecount_" + HASHED_EMAIL, noteList.size()); editor.putInt("notecount_" + HASHED_EMAIL, noteList.size());
for(int i=0; i<noteList.size(); i++){ for(int i=0; i<noteList.size(); i++){
Note note = noteList.get(i); Note note = noteList.get(i);
editor.putString(i + "_title_" + HASHED_EMAIL, encrypt("AES/CBC/PKCS5Padding", note.getTitle(), getKeyFromPassword(KEY, getSaltForUser(HASHED_EMAIL, true)), generateIv())); editor.putString(i + "_title_" + HASHED_EMAIL, UtilityAES.encrypt("AES/CBC/PKCS5Padding", note.getTitle(), UtilityAES.getKeyFromPassword(PAS, getSaltForUser(HASHED_EMAIL, true)), iv));
editor.putString(i + "_content_" + HASHED_EMAIL, note.getContent()); editor.putString(i + "_content_" + HASHED_EMAIL, note.getContent());
} }
@ -397,63 +320,57 @@ public class MainActivity extends AppCompatActivity {
editor.apply(); editor.apply();
} }
public static SecretKey getKeyFromPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return secret;
}
private void loadNotesFromPreferencesToList() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { private void loadNotesFromPreferencesToList() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
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();
IvParameterSpec iv = stringToIv(ivString);
for(int i=0; i<noteCount; i++){ for(int i=0; i<noteCount; i++){
String title = sharedPreferences.getString(i + "_title_" + HASHED_EMAIL, ""); String title = sharedPreferences.getString(i + "_title_" + HASHED_EMAIL, "");
String content = sharedPreferences.getString(i + "_content_" + HASHED_EMAIL, ""); String content = sharedPreferences.getString(i + "_content_" + HASHED_EMAIL, "");
Note note = new Note(); Note note = new Note();
note.setTitle(decrypt("AES/CBC/PKCS5Padding", title, getKeyFromPassword(KEY, getSaltForUser(HASHED_EMAIL, true)), generateIv()) ); note.setTitle(UtilityAES.decrypt("AES/CBC/PKCS5Padding", title, UtilityAES.getKeyFromPassword(PAS, getSaltForUser(HASHED_EMAIL, true)), iv) );
note.setContent(content); note.setContent(content);
noteList.add(note); noteList.add(note);
} }
} }
private static final byte[] FIXED_IV = { private void saveIvStringToShared(String ivString){
0x01, 0x02, 0x03, 0x04, SharedPreferences sharedPreferences = getSharedPreferences(SHARED_NAME_NOTES, MODE_PRIVATE);
0x05, 0x06, 0x07, 0x08, SharedPreferences.Editor editor = sharedPreferences.edit();
0x09, 0x0A, 0x0B, 0x0C,
0x0D, 0x0E, 0x0F, 0x10
};
public static IvParameterSpec generateIv() { editor.putString("iv_" + HASHED_EMAIL, ivString);
return new IvParameterSpec(Arrays.copyOf(FIXED_IV, FIXED_IV.length));
editor.apply();
} }
public static String encrypt(String algorithm, String input, SecretKey key, IvParameterSpec iv) throws private String getIVStringFromShared(){
NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, SharedPreferences sharedPreferences = getSharedPreferences(SHARED_NAME_NOTES, MODE_PRIVATE);
BadPaddingException, IllegalBlockSizeException { String ivString = sharedPreferences.getString("iv_" + HASHED_EMAIL, "err");
return ivString;
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] cipherText = cipher.doFinal(input.getBytes());
return Base64.getEncoder().encodeToString(cipherText);
} }
public static String decrypt(String algorithm, String cipherText, SecretKey key, IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException, private static IvParameterSpec stringToIv(String ivString) {
InvalidAlgorithmParameterException, InvalidKeyException, byte[] ivBytes = Base64.getDecoder().decode(ivString);
BadPaddingException, IllegalBlockSizeException{ return new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(cipherText));
return new String(plainText);
} }
private static String ivToString(IvParameterSpec ivParameterSpec) {
byte[] ivBytes = ivParameterSpec.getIV();
return Base64.getEncoder().encodeToString(ivBytes);
}
private void createNoteView(final Note note){ private void createNoteView(final Note note){
View noteView = getLayoutInflater().inflate(R.layout.note_item, null); View noteView = getLayoutInflater().inflate(R.layout.note_item, null);

View File

@ -0,0 +1,59 @@
package com.example.bsm_notatnik;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class UtilityAES {
public static SecretKey getKeyFromPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return secret;
}
public static String encrypt(String algorithm, String input, SecretKey key, IvParameterSpec iv) throws
NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] cipherText = cipher.doFinal(input.getBytes());
return Base64.getEncoder().encodeToString(cipherText);
}
public static String decrypt(String algorithm, String cipherText, SecretKey key, IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException{
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(cipherText));
return new String(plainText);
}
public static IvParameterSpec generateIv(){
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
}