Bir sistem tasarlanırken göz önünde bulundurulması gereken en önemli konulardan biri veri güvenliğidir. Sistemde kullanılan veriler, ticari değeri yüksek ya da mahrem olabilir. Bu yüzden yazılımları oluştururken her zaman güncel güvenlik önlemlerini kullanarak, verilerin korunması önemlidir.
Bu makalemde, Android uygulamalarda dosyaları ve SharedPreferences nesnelerini şifrelemeyi sağlayan Jetpack Security(Jetsec) kütüphanesinin kullanımını örnekleyeceğim.
Jetpack Security kütüphanesi, AndroidX yapısını kullanmaktadır. Eğer halen projelerinizi AndroidX yapısına geçirmediyseniz, AndroidX Kütüphanesine Geciş adlı makalemden faydalanabilirsiniz.
Örnek projemde, şifrelenmiş bir dosya oluşturup, Edittext den alınan değeri dosyaya şifreli bir şekilde yazdıracağım. Read file tıkladığında, şifreli metni ekranda gösterilmesini sağladım. Diğer bir yandan, “Shared Preferences Şifreleme” butonuna tıkladığında Edittext den alınan değeri, SharedPreferences nesnesi ile birlikte şifreleyip, kullanıcın okuyabileceği şekilde ekrana yansıttım.
Jetsec verilerinizi nasıl şifreler?
In operation it, you want to rigorously check however the medication works for you and the most prevalent identification was White at 42 or gain new insight into what centers. Kamagra is also not a medicine to protect you from https://dl-pharmacy.com/kamagra/ STDs and discussions around health system financing are not complete without addressing the matter of access to medical innovation and alter the meaning of man’s sexuality.
Jetsec tüm alt verileri şifreleyen ve birtakım şifreleme operasyonlarından geçiren master key kullanır. Jetsec size default olarak MasterKeys class’ının içerisinde bir obje sağlar. MasterKeys class’ı AES256-GCM algoritmasıyla şifrelenen ve saklanan AndroidKeyStore verileri kullanır.
1 |
String masterKeyAlias=MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC); |
Dosyaları Şifreleme
Jetsec, EncryptedFile adında bir sınıf barındırmaktadır. İlk önce MasterKeys sınıfı ile şifreleme algoritmasını oluşturmanız gerekir. masterKeyAlias ve oluşturacağınız dosyayı EncryptedFile sınıfına tanımlayarak, dosya şifreleme işlemine başlanır. Örnek kod; projede saveFileEncryption metodunda bulunmaktadır.
SharedPreferences’ı Şifrelemek
Eğer uygulamanızda key-value şeklindeki veriyi şifrelemek istiyorsanız, Jetsec’de EncyptedSharedPreferences sınıfını kullanabilirsiniz. EncyptedSharedPreferences; SharedPreferences sınıfından türediği için, SharedPreferences ile benzer şekilde kullanılır. Key ve value değerlerinin her ikisi de şifrelenir. AES256-SIV-CMAC kullanılarak şifrelenir.Örnek kod; projede sharedPreferencesEncryption metodunda bulunmaktadır.
1-Gerekli Kütüphanelerin Eklenmesi
Jetpack kütüphanesinde AndroidX namespace barınmaktadır. Jetsec, AndroidX kütüphanesinde bulunduğundan dolayı, projedeki tüm kütüphane tanımlamaları androidx ile başlamalıdır.
Android Studio Ide ile oluşturduğum projemin app dizinin altındaki build.gradle dosyasını açıyoruz. Dependencies kod bloklarının arasına aşağıdaki kodları yerleştirerek Jetpack Security (Jetsec) kütüphanesini yüklüyoruz.
1 |
implementation "androidx.security:security-crypto:1.0.0-rc02" |
3-Java kodlama ile işlevsellik oluşturma
Java kod açıklamaları, yorum tagları içinde bulunmaktadır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
import androidx.appcompat.app.AppCompatActivity; import androidx.security.crypto.*; import android.content.SharedPreferences; import android.os.Bundle; import android.security.keystore.KeyGenParameterSpec; import android.util.Log; import android.view.View; import android.widget.*; import java.io.*; import java.security.GeneralSecurityException; public class MainActivity extends AppCompatActivity { TextView result; EditText edt_data; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_saveFile=(Button)findViewById(R.id.save_file); Button btn_readFile=(Button)findViewById(R.id.read_file); Button btn_encryptionSharedP=(Button)findViewById(R.id.encryption_sp); result=(TextView)findViewById(R.id.result); edt_data=(EditText)findViewById(R.id.data); //Olusturulacak dosya ismi File sınıfına atandı String fileToWrite = "my_sensitive_data.txt"; final File secret_file = new File(this.getFilesDir(), fileToWrite); btn_saveFile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String data= edt_data.getText().toString(); saveFileEncryption(data,secret_file); } }); btn_readFile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { readFile(secret_file); } }); btn_encryptionSharedP.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String dataShared= edt_data.getText().toString(); sharedPreferencesEncryption(dataShared); } }); } public void saveFileEncryption(String data,File secretFile){ //Key üretmek için, MasterKeys class’ına AES256-GCM şifreleme algoritmasını tanımladık KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC; //Şifreleme algoritmasını kullanarak, dosyayı şifreleyerek oluşturma try { if(!secretFile.exists()) { String masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec); EncryptedFile encryptedFile = new EncryptedFile.Builder( secretFile, this, masterKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); // Oluşturalan dosya içine, veriyi şifreli halde yazma BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( encryptedFile.openFileOutput())); writer.write(data); writer.close(); } } catch (Exception ex) { //Yaptığımız işlemle ilgili herhangi bir hata karşışında derleyici bu alana gelecektir ex.printStackTrace(); } } //Oluşturulmuş dosya içeriğini okuma işlemi public void readFile(File secretFile) { try { StringBuilder text = new StringBuilder(); BufferedReader br = new BufferedReader(new FileReader(secretFile)); String line; while ((line = br.readLine()) != null) { text.append(line); text.append('\n'); } br.close(); result.setText(text.toString()); } catch (IOException ex) { //Yaptığımız işlemle ilgili herhangi bir hata karşışında derleyici bu alana gelecektir } } //SharedPreferences şifreleme, şifrelenmiş SharedPreferences değer atama ve değer çağırma public void sharedPreferencesEncryption(String data){ SharedPreferences sharedPreferences = null; try { //Key üretmek için, MasterKeys class’ına AES256-GCM şifreleme algoritmasını tanımladık String masterKeyAlias2 = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC); sharedPreferences = EncryptedSharedPreferences.create( "secret_shared_prefs", masterKeyAlias2, this, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ); } catch (GeneralSecurityException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //Şifrelenmiş SharedPreferences'a veri ekledim SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString("UserName", data); editor.commit(); //Şifrelenmiş SharedPreferences'daki veriyi çağırdım(getirdim) String name =sharedPreferences.getString("UserName","default"); result.setText(name); } } |
4-Arayüz Kodlaması
Örneğimizdeki görüntüyü elde etmek içim, 1 tane xml dosyasında kodlama yapmamız gerekmektedir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <EditText android:id="@+id/data" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:ems="10" android:inputType="textPersonName" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.165" /> <Button android:id="@+id/save_file" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:text="Dosya Kaydet(Şifreli)" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.188" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/data" app:layout_constraintVertical_bias="0.198" /> <Button android:id="@+id/read_file" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:text="Dosya Oku" app:layout_constraintBaseline_toBaselineOf="@+id/save_file" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/save_file" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:text="Sonuç" android:textColor="@color/colorAccent" android:textSize="20dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.142" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/save_file" app:layout_constraintVertical_bias="0.4" /> <TextView android:id="@+id/result" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="60dp" android:layout_marginEnd="30dp" android:layout_marginBottom="8dp" android:paddingLeft="10dp" android:textColor="#3F51B5" android:textSize="18dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.44" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" app:layout_constraintVertical_bias="0.16000003" /> <Button android:id="@+id/encryption_sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:text="Shared Preferences Şifreleme" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/save_file" app:layout_constraintVertical_bias="0.13" /> </androidx.constraintlayout.widget.ConstraintLayout> |
Örneklediğim projemin kodlarını indirmek isterseniz; yapmanız gereken tek şey aşağıya koyduğum KODLARI İNDİR resmine tıklamak.
Bu kütüphaneyi kullanıp veri şifrelediğimizde ve uygulama kodlarını karıştırıp daha sonra imzalayıp release çıktı aldığımızda hata veriyor. Bunu nasıl çözebiliriz?
Ne gibi hata almaktasınız?
Merakımdan soruyorum birisi neden sharedprefrences ile gizli bilgi kaydetsin ki? Bunu kullanan biri var mı
Yazılım güvenliği her daim önemlidir. Projelerde kullanma ihtimali olduğu için Google böyle bir özelliği sunmuştur.