Search what you want

Tuesday, January 16, 2018

Secure your secret key on Android

(https://images.idgesg.net/images/article/2017/11/android-security-100741557-large.jpg)


Okeh kita mulai saja tulisan ada hari ini. Pada kesempatan kali ini saya akan mencoba membuat artikel tentang "secure your application in android phone". Beberapa bulan belakangan ini saya mendapatkan beberapa kendala tentang bagaimana mengamankan secret key yang diletakkan di aplikasi android. Sebenarnya saya sendiri bukan orang security yang memiliki pemahaman yang baik tentang ini, tapi setidaknya kita (sebagai seseorang application developer) bisa mengetahui bagaimana membuat applikasi yang "aman".

Beberapa hari belakangan ini beberapa blog, artikel, stackoverflow, dan sebagainya menemani saya untuk mengetahui bagaimana membuat aplikasi android yang "aman". Sebagai informasi, Google menjadikan OS android-nya menjadi open source dan kita bisa mendapatkan source code android dengan mudah. Artinya apa dari hal ini? setiap orang bisa mempelajari sistem dari android dengan secara bebas (kalau saya sih belum pernah. hehe). Tetapi Google tidak membuka secara bebas semua services aplikasi miliknya di android ke publik. Dengan artian, kalau kia merasa nyaman dengan android yang kita miliki sekarang, itu merupakan gabungan dari sistem utama android dan services aplikasi yang Google miliki.

oya, sebenernya kenapa harus di ada kata-kata secret key? dan buat apa key itu biasanya digunakan? hmmm.... biasanya sih key rahasia itu bisa berupa:
1. username & password
2. token API server
3. key enkripsi data
4. file enkripsi
5. dll (hmmm.. sebenernya ga tau lagi dan untuk itu saja penggunaan yang saya sudah gunakan)

oke langsung aja, sebenernya gimana sih cara orang-orang meletakkan secret key mereka pada aplikasi android. Sejauh yang saya tau (#CMIIW) ada beberapa cara meletakkan:
1. meletakkan di string.xml
2. meletakkan di sourcecode (java/kotlin)
3. meletakkan di BuildConfig
4. amankan menggunakan ProGuard
5. meletakkan di Native C/C++
6. meletakkannya di sourcecode dan encoding 
7. meletakkan key di sharedpreference
8. meng-enkripsi file rahasia menggunakan salsa20
9. meng-enkripsi key dengan kaystore android (AES & RSA)
10. melindungi aplikasi dari device yang di root
11. meletakkan key di server

note: [environment yang digunakan dalam membuat artikel ini]
OS: Linux (Ubuntu 16.04 LTS)
Android Studio: 3.0


========================================================================
1. Meletakkan key (string) di string.xml (code)
sebagai android programmer pasti sudah tak asing lagi dengan file resource ini. yap, string.xml digunakan untuk meletakkan teks di aplikasi android. lah kan kalau di kodingan langsung (java) juga bisa kan? nah di string.xml ini "lebih khusus" digunakan untuk meletakkan string yang digunakan untuk meng-konsistenkan data teks yang digunakan, biasanya digunakan oleh teks-teks yang berada di User Interface (UI). okelah langsung aja ya.

app/src/main/res/values/string.xml
<resources>
    <string name="app_name">HideStringXml</string>
    <string name="password">Passw0rdRahasi4</string>
</resources>
Buat projek baru -> masukkan string seperti diatas -> Build APK(s)

kenapa harus di buat APK dulu? yap, karena ketika kita ingin menggunakan aplikasi yang dibuat orang kita hanya mendapatkan APK nya saja, tanpa source code full dari aplikasi itu.

jika tidak mau repot membuat projek baru, bisa kita gunakan APK yang sudah dibuat dan bisa langsung uji coba ---> Download APK disini <---

$ string app-debug.apk | grep Pass
Passw0rdRahasi4
dengan cara tersebut kita baru saja mengetahui key rahasia yang diletakkan di string.xml. Jadi dengan mudah kita mendapatkan informasi tersebut.

oya, "grep" digunakan untuk melakukan filter hasil pencarian, jadi yang saya lakukan diatas hanya ingin mendapatkan string yang mengandung kata "Pass". 


_________________________________________________________________________________
2. Meletakkan key (string) di source code (Java/kotlin) (code)
kalau menyimpan string di source code pasti kita sering menggunakannya ya. nah sekarang bagaimana kita tau string rahasia yang digunakan oleh orang lain dalam aplikasi androidnya.

class MainActivity : AppCompatActivity() {
    companion object {
        lateinit var instance: String
        @JvmStatic lateinit var instance2: String
        lateinit var stringfromjava1: String
        lateinit var stringfromjava2: String
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onStart() {
        super.onStart()
        instance = "Passw0rdRahasi4_1"
        instance2 = "Passw0rdRahasi4_2"
        stringfromjava1 = Constant.data
        stringfromjava2 = String(Constant.databyte)


        Toast.makeText(this, stringfromjava2.toString(),Toast.LENGTH_SHORT).show()
    }
}
app/src/main/java/com/kirra/hidestringcode/Constant.java
public final static String data = "Passw0rdRahasi4_3";
public static final byte[] databyte = new byte[]{
            'P','a','s','s','w','0','r','d','R','a','h','a','s','i','4','_','5'};
Buat projek baru -> masukkan string di MainActivity.kt & Constant.java -> Build APK(s)

jika tidak mau repot membuat projek baru, bisa kita gunakan APK yang sudah dibuat dan bisa langsung uji coba ---> Download APK disini <---

$ unzip app-debug.apk
$ strings classes.dex | grep Pass
Passw0rdRahasi4_5
2Landroid/text/method/PasswordTransformationMethod;
Passw0rdRahasi4_1
Passw0rdRahasi4_2
Passw0rdRahasi4_3
isPassword
nah dari hasil ekstraksi string diatas kita dapat melihat bahwa string yang disimpan dalam kode program masih dapat kita lihat semuanya.


_________________________________________________________________________________
3. Meletakkan key (string) di BuildConfig (code)
sebagai seorang android programer pasti juga sudah tidak asing dengan file ini. BuildConfig merupakan file yang di hasilkan oleh androidstudio pada saat melakukan Build projek. file ini digunakan untuk melakukan setting terhadap suatu projek, semisal untuk mengatur application_id, version_code, version_name, dll. Setting ini bisa dilakukan di file build.gradle di dalam folder app.

app/build.gradle
defaultConfig {
        ....

        buildConfigField "String", "pass", "\"${hiddenPassword}\""

        ....
    }
gradle.properties
hiddenPassword=Passw0rdRahasi4
Buat project baru -> masukkan code di build.gradle & gradle.properties -> Build APK(s)

jika tidak mau repot membuat projek baru, bisa kita gunakan APK yang sudah dibuat dan bisa langsung uji coba ---> Download APK disini <---

$ unzip app-debug.apk
$ strings classes.dex | grep Pass
Passw0rdRahasi4
backwardPass
forwardPass
isPassword
needSolverPass
setPassword
skippedFirstPass
dengan cari ini pun, menyembunyikan di BuildConfig, masih dapat di ketahui semua string yang kita simpan secara hardcode.


_________________________________________________________________________________
4. Melakukan obfuscate terhadap kode program (code)
Cara yang selanjutnnya yaitu dengan melakukan obfuscate. Cara ini dilakukan (salah satunya) dengan tujuan untuk mengacak-acak kode program. eits... tenang aja walaupun udah di acak-acak aplikasi kita masih bisa berjalan dengan baik kok. Maksudnya diacak yaitu, sistem (builder) akan melakukan penggantian nama class, methode, dan variable terhadap program kita. Hal ini menjadikan kode kita yang sudah release ke publik lebih tidak mudah dibaca ketika di ekstrak oleh orang lain. Android studio memiliki fitur untuk obfuscate di ProGuard, jadi kita bisa gunakan itu dengan mudah.

Pertama-tama kita lakukan hal yang sama dengan meletakkan text di string.xml(1), source code(2), dan BuildConfig(3). kemudian kita langsung melakukan pengaturan pada ProGuard, seperti di bawah ini.

app/src/main/java/com/kirra/hidestringprogurd/MainActivity.java
public class MainActivity extends AppCompatActivity {
    private final static String data = "Passw0rdRahasi4_code_string";
    private static final byte[] databyte = new byte[]{
            'P','a','s','s','w','0','r','d','R','a','h','a','s','i','4','_','c','o','d','e','_','b','y','t','e'};
    private String dataBuildConfig;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dataBuildConfig = BuildConfig.pass;
    }
}

app/build.gradle
buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
app/proguard-rules.pro
-keep class !com.kirra.** { *; }
Setelah selesai melakukan pengaturan diatas kita bisa langsung melakukan build APK. Untuk informasi saja, kita melakukan setting ProGuard untuk Build Type release, dan sebelumnya kita harus melakukan sign apk dengan membuat file .jks terlebih dahulu.

untuk memudahkan mencobanya saya sudah siapkan APK untuk kita coba saja.
---> Download APK disini <---

app-debug.apk
$ strings app-debug.apk | grep Pass
Passw0rdRahasi4_xml

$ unzip app-debug.apk
$ strings classes.dex | grep Pass
Passw0rdRahasi4_code_byte
2Landroid/text/method/PasswordTransformationMethod;
Passw0rdRahasi4_buildconfig
Passw0rdRahasi4_code_string
backwardPass
forwardPass
isPassword
needSolverPass
setPassword
skippedFirstPass
app-release.apk
$ strings app-release.apk | grep Pass
Passw0rdRahasi4_xml

$ unzip app-release.apk
$ strings classes.dex | grep Pass
Passw0rdRahasi4_code_byte
2Landroid/text/method/PasswordTransformationMethod;
Passw0rdRahasi4_buildconfig
backwardPass
forwardPass
isPassword
setPassword
disini kita melihat bahwa dengan menggunakan ProGuard variabel dengan tipe data string tidak dapat dibaca menggunakan command ini. nah berarti sebaiknya kita menggunakan variabel ber-tipe string dan melakukan Obfuscate untuk menyimpan string key rahasia ya...  eits... bentar dulu, apakah memang string itu sudah tidak bisa terlihat lagi? kita boleh coba dengan cara lain.

sebenarnya yang dilakukan pada aplikasi di atas mugkin aja dikarenakan String yang kita cari tidak digunakan oleh fungsi utama aplikasi. Sehingga tidak diamggap penting oleh proguard. Sekarang kita akan mencoba, jika string tersebut kita masukkan ke string lain, dan kita lihat apa yang terjadi:

app/src/main/java/com/kirra/hidestringprogurd/MainActivity.java
public class MainActivity extends AppCompatActivity {
    private final static String data = "Passw0rdRahasi4_code_string";
    private static final byte[] databyte = new byte[]{
            'P','a','s','s','w','0','r','d','R','a','h','a','s','i','4','_','c','o','d','e','_','b','y','t','e'};
    private String dataBuildConfig;
    private String dataCode;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dataBuildConfig = BuildConfig.pass;
        dataCode = data;
    }
}
setelah ini kita coba lagi untuk melihat bagian app-release.apk -nya
---> Download APK disini <---

app-release.apk
$ strings app-release.apk | grep Pass
Passw0rdRahasi4_xml

$ unzip app-release.apk
$ strings classes.dex | grep Pass
Passw0rdRahasi4_code_byte
2Landroid/text/method/PasswordTransformationMethod;
Passw0rdRahasi4_buildconfig
Passw0rdRahasi4_code_string
backwardPass
forwardPass
isPassword
setPassword
ternyata tetap saja bukan karena bertipe data String yang membuatnya hilang sebelumnya, itu karena variabelnya yang tidak digunakan dan tidak dianggap penting.

jadi tetap saja menggunakan Proguard ini tidak bisa secara utuh untuk merahasiakan string yang kita buat. Lalu apa gunanya ProGuard dong? hmmmmm....
setelah saya amati dan cari tau ada beberapa keuntungan: pertama, ukuran APK menjadi lebih kecil; kedua class dan methode nya menjadi acak, jadi tidak mudak di baca dan ditelusuri alur programnya.

"ProGuard is an open source command-line tool that shrinks, optimizes and obfuscates Java code. It is able to optimize bytecode as well as detect and remove unused instructions. ProGuard is open source software." (wikipedia)

Saya menggunakan tool enjarify untuk melakukan reverse engineering. Berikut saya lampirkan .jar aplikasi yang sudah saya decompile -> download .jar aplikasi <- dan kita bisa lihat menggunakan tools jd-gui

<tidak menggunakan ProGuard>

<menggunakan ProGuard>

Sebenernya tidak terlalu terlihat ya kalau hanya segitu, tapi kalau aplikasi kita sudah besar dan terdapat beberapa algoritma, pasti akan lebih susah untuk orang lain membacanya.


_________________________________________________________________________________
5. Meletakkan di native C/C++ program (code)
Sekarang kita mencoba untuk meletakkan text rahasia di dalam code C/C++. Seperti yang kita tau bahwa salah satu bahasa pemrograman yang di support oleh Google didalam android studio adalah bahasa C/C++. Lalu bagaimanakah kita dapat menggunakannya. langsung saja kita lihat cara dibawah ini.

app/src/main/cpp/native-lib.cpp
#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring

JNICALL
Java_com_kirra_hidestringnativec_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Passw0rdRahasi4";
    return env->NewStringUTF(hello.c_str());
}

Buat projek baru (include C++ support) -> masukkan program diatas kedalam program .cpp -> build

untuk memudahkan mencobanya saya sudah siapkan APK untuk kita coba saja. ---> Download APK disini <---

$ unzip app-release.apk
$ strings lib/arm64-v8a/libnative-lib.so | grep Pass
Passw0rdRahasi4
nah kan benar saja, jika kita mencoba menyimpan string (yang telanjang) akan tetap bisa kita ketahui juga dengan cara mengekstrak string nya. nah terus apa gunanya dong kalau kita letakkan di C/C++ program.
sebenarnya jika kita letakkan algoritma di dalam C/C++ program, alur dari program yang kita buat tidak mudah untuk dibaca oleh orang lain.


_________________________________________________________________________________
6. Meletakkannya di sourcecode dan di encode (code)
nah sekarang jika semua cara diatas sudah tidak bisa kita gunakan, apakah ada cara lainnya untuk kita yang memang benar-benar mau menyimpan string didalam aplikasi kita. yap, salah satu caranya yaitu jangan sampai string yang kita letakkan itu telanjang bulat tanpa pengaman apapun, yaitu kita bisa encode terlebih dahulu string yang kita mau simpan.

app/src/main/java/com/kirra/hidestringdecoding/MainActivity.java
private static final String[] KEY = new String[]{
            "gtcbnuhrrwlapZHjXsVBLEUSmHh=","iogrngwhffBIHWLETtuykxPIXIV","oNQavjbaNNSgEqoCkT9Em4imeQQ"
    };
public void useXorStringHiding(String myHiddenMessage) {
        byte[] xorParts0 = Base64.decode(KEY[0],0);
        byte[] xorParts1 = Base64.decode(KEY[1], 0);

        byte[] xorKey = new byte[xorParts0.length];
        for(int i = 0; i < xorParts1.length; i++){
            xorKey[i] = (byte) (xorParts0[i] ^ xorParts1[i]);
        }
        doHiding(myHiddenMessage.getBytes(), xorKey, false);
    }

    public static void doHiding(byte[] msg, byte[] pwd, boolean isHidden){
        xorValues(msg, pwd);

        if(!isHidden){
            String hiddenMessage = Base64.encodeToString(msg, 0);
            Log.i(TAG, String.format("Hidden Message: %s", hiddenMessage));
            doHiding(msg, pwd, true);
        }else{
            Log.i(TAG, String.format("Unhidden Message: %s", new String(msg)));
        }
    }

    public static int xorValues(byte[] msg, byte[] pwd){
        int i;
        for(i = 0; i < msg.length; i++){
            int keyOffset = i % pwd.length;
            msg[i] = (byte) (msg[i] ^ pwd[keyOffset]);
        }
        return i;
    }
public void useXorStringShowing(String myHiddenMessage) {
        byte[] xorParts0 = Base64.decode(KEY[0],0);
        byte[] xorParts1 = Base64.decode(KEY[1], 0);

        byte[] xorKey = new byte[xorParts0.length];
        for(int i = 0; i < xorParts1.length; i++){
            xorKey[i] = (byte) (xorParts0[i] ^ xorParts1[i]);
        }
        doShow(myHiddenMessage, xorKey);
    }

    public static void doShow(String message, byte[] pwd){
        xorValues(message.getBytes(), pwd);
        Log.i(TAG, String.format("Unhidden Message: %s", new String(Base64.decode(message,0))));
    }
kita bisa langsung uji coba aplikasi yang sudah ada ---> Download APK disini <---

nah kalau sudah seperti ini bagaimana cara kita untuk bisa tau key yang sebenarnya? contoh dalam codingan yang sudah ada kita ingin mengetahui kata yang sebenarnya dari string ini:
bWF1bWVueWVtYnVueWlrYW5zdHJpbmc=
yang memiliki arti sebenarnya adalah
maumenyembunyikanstring
tanpa kata 'maumenyembunyikanstring' diberikan sebelumnya

hal seperti ini dapat kita ketahui ketika kita mengetahui alur dari program yang ada, dengan cara melakukan ekstraksi terhadap APK secara langsung. Pada tahap ini kita memerlukan tools lain untuk mempermudah kita melakukannya. Tools pertama adalah enjarify dan yang kedua adalah jd-gui. enjarify merupakan tools yang dibuat menggunakan bahasa pemrograma python, sedangkan jd-gui (java base) merupakan tools untuk melihat hasil ekstraksi yang dihasilkan dari enjarify. kali ini saya tidak akan membahas secara lanjut tentang kedua tools tersebut, dan saya anggap environment OS kita sudah terinstall tools tersebut.

untuk melakukan ekstraksi file .apk silahkan jalankan script ini
$ enjarify app-release.apk
setelah script tersebut dijalankan maka akan menghasilkan file "app-release-enjarify.jar". kemudian jalankan JD-GUI dan buka  file .jar tersebut
$ java -jar jd-gui-x.x.x.jar
hasil decompilasi app-release.apk
public class MainActivity
  extends AppCompatActivity
{
  private static final String[] KEY;
  private static final String TAG = MainActivity.class.getSimpleName();
  
  static
  {
    String[] arrayOfString = new String[3];
    arrayOfString[0] = "gtcbnuhrrwlapZHjXsVBLEUSmHh=";
    arrayOfString[1] = "iogrngwhffBIHWLETtuykxPIXIV";
    arrayOfString[2] = "oNQavjbaNNSgEqoCkT9Em4imeQQ";
    KEY = arrayOfString;
  }
  
  public static void doHiding(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2, boolean paramBoolean)
  {
    boolean bool = true;
    xorValues(paramArrayOfByte1, paramArrayOfByte2);
    String str2;
    Object[] arrayOfObject;
    String str3;
    if (!paramBoolean)
    {
      String str1 = Base64.encodeToString(paramArrayOfByte1, 0);
      str2 = TAG;
      arrayOfObject = new Object[bool];
      arrayOfObject[0] = str1;
      str3 = String.format("Hidden Message: %s", arrayOfObject);
      Log.i(str2, str3);
      doHiding(paramArrayOfByte1, paramArrayOfByte2, bool);
    }
    for (;;)
    {
      return;
      str2 = TAG;
      arrayOfObject = new Object[bool];
      String str4 = new java/lang/String;
      str4.<init>(paramArrayOfByte1);
      arrayOfObject[0] = str4;
      str3 = String.format("Unhidden Message: %s", arrayOfObject);
      Log.i(str2, str3);
    }
  }
  
  public static void doShow(String paramString, byte[] paramArrayOfByte)
  {
    xorValues(paramString.getBytes(), paramArrayOfByte);
    String str1 = TAG;
    Object[] arrayOfObject = new Object[1];
    String str2 = new java/lang/String;
    byte[] arrayOfByte = Base64.decode(paramString, 0);
    str2.<init>(arrayOfByte);
    arrayOfObject[0] = str2;
    String str3 = String.format("Unhidden Message: %s", arrayOfObject);
    Log.i(str1, str3);
  }
  
  public static int xorValues(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2)
  {
    int i = 0;
    for (;;)
    {
      int j = paramArrayOfByte1.length;
      if (i >= j) {
        break;
      }
      j = paramArrayOfByte2.length;
      int k = i % j;
      j = paramArrayOfByte1[i];
      int m = paramArrayOfByte2[k];
      j = (byte)(j ^ m);
      paramArrayOfByte1[i] = j;
      i += 1;
    }
    return i;
  }
  
  protected void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2131296283);
    useXorStringHiding("maumenyembunyikanstring");
    useXorStringShowing("bWF1bWVueWVtYnVueWlrYW5zdHJpbmc=");
  }
  
  public void useXorStringHiding(String paramString)
  {
    byte[] arrayOfByte1 = Base64.decode(KEY[0], 0);
    Object localObject = KEY;
    int i = 1;
    localObject = localObject[i];
    byte[] arrayOfByte2 = Base64.decode((String)localObject, 0);
    int j = arrayOfByte1.length;
    byte[] arrayOfByte3 = new byte[j];
    int k = 0;
    for (;;)
    {
      j = arrayOfByte2.length;
      if (k >= j) {
        break;
      }
      j = arrayOfByte1[k];
      i = arrayOfByte2[k];
      j = (byte)(j ^ i);
      arrayOfByte3[k] = j;
      k += 1;
    }
    doHiding(paramString.getBytes(), arrayOfByte3, false);
  }
  
  public void useXorStringShowing(String paramString)
  {
    byte[] arrayOfByte1 = Base64.decode(KEY[0], 0);
    Object localObject = KEY;
    int i = 1;
    localObject = localObject[i];
    byte[] arrayOfByte2 = Base64.decode((String)localObject, 0);
    int j = arrayOfByte1.length;
    byte[] arrayOfByte3 = new byte[j];
    int k = 0;
    for (;;)
    {
      j = arrayOfByte2.length;
      if (k >= j) {
        break;
      }
      j = arrayOfByte1[k];
      i = arrayOfByte2[k];
      j = (byte)(j ^ i);
      arrayOfByte3[k] = j;
      k += 1;
    }
    doShow(paramString, arrayOfByte3);
  }
}
dari hasil tersebut, kita masih bisa membaca codingan dari aplikasi yang kita decompile. nah dengan mudah kita bisa membaca kodingan tersebut dan mengetahui alur dari programnya.


_________________________________________________________________________________
7. Meletakkan key di sharedpreference (code)
Apalagi sih ini sharepreference, hmmm.... sharepreference ini meruakan salah satu tempat yang banyak digunakan android developer untuk meletakkan salah satu string agar user dapat berinteraksi dengan mudah.
Misalnya saat login aplikasi meminta username dan password dari seseorang untuk bisa melanjutkan aktivitas selanjutnya. nah username dan password ini harus selalu ada pada awal user berinteraksi. maka dari itu agar memudahkan user, developer memutuskan untuk menyimpan data tersebut di aplikasi. Sharpreference merupakan salah satu nya yang bisa digunakan untuk menyimpan data tersebut. kalian bisa mempelajari bagaimana menggunakan sharepreference dari code yang sudah tersedia.

kali ini saya akan langsung menjalankan program dari android studio. dengan menyimpan di preference kita bisa melihat seluruh string yang disimpan.

jika kita menggunakan divice yang sudah di Root  kita juga bisa melihatnya dengan mudah.
kita cukup menuju
1. ke explorer di HP;
2. data;
3. data;
4. packagename aplikasi;
5. buka file berakhiran "_preferences.xml"

/data/data/com.kirra.hidestringpreference/shared_prefs/com.kirra.hidestringpreference_preferences.xml

untuk memudahkan mencobanya saya sudah siapkan APK untuk kita coba saja.
---> Download APK disini <---

nah loh...

_________________________________________________________________________________
8. Enkripsi file rahasia menggunakan salsa20 (code)
Selanjutnya bagaimana kalau kita meletakkan key rahasia kita kedalah sebuah file kemudian file tersebut kita enkripsi. Lalu kenapa harus salsa20 ya, hmmmm... sebenarnya hanya untuk pilihan aja sih untuk kita-kita. hehe... bercanda deng.  Bisa dibilang salsa20 ini cukup layak untuk digunakan di device yang memiliki resource terbatas sepetdi handphone ini. saya coba lampirkan implementasi yang sudah dilakukan oleh Yukuku.

bisa kita lihat implementasinya di source code yang telah disediakan. Kode ini terdapat dua bagian, yaitu bagian implementasi menggunakan C/C++ dan yang kedua interface kedalam kode java nya

a. buat file dan letakkan di asset (coba.txt)
b. buat metode enkripsinya [writeFileEncode(String path)] {code}
c. buat metode decripsinya [writeFileDecode(String path)] {code}
d. buat key1 dan key2 nya (enkripsi ini memiliki dua key kalian bisa letakkan dimanapun kalian mau) {code}
e. jalankan aplikasinya
f. lihat file hasil keluaran di explorer dan didalam folder "Reader"
g. jangan lupa aktifkan permission "write storage" jika kalian menggunakan android API 22 keatas.

nah dengan cara ini aplikasi data kita bisa ter-enkripsi dengan baik dan dengan penggunaan resource yang tidak sangat besar. masalah selanjutnya adalah bagaimana mengamankan dua key yang kita miliki ini. kalian bisa gunakan cara-cara diatas dengan resikonya masing masing.

untuk memudahkan mencobanya saya sudah siapkan APK untuk kita coba saja.
---> Download APK disini <---


_________________________________________________________________________________
9. Meng-enkripsi key dengan kaystore android (code)
Selanjutnya kita akan mencoba menggunakan salah satu fitur yang terdapat pada android, yaitu Keystore. Keystore ini pertama kali diperkenalkan oleh google pada API 18. itu artinya fitur ini hanya bisa digunakan untuk OS dengan API 18 keatas. Sistem Keystore ini memungkinkan kita menyimpan key rahasia dalam device dan menjadikan seseorang lebih susah untuk melakukan ekstraksi key yang berada didalam device android kita.
Ada beberapa algoritma yang bisa digunakan untuk mengahasilkan chiper text dan mendapatkan teks aslinya kembali. AES dan RSA merupakan algoritma yang sudah diakui secara luas. Intinya AES merupakan symmetric encryption algorithm dimana kita hanya membutuhkan satu key untuk melakukan enkripsi dan dekripsi nya. Sedangkan, RSA merupakan asymmetric encryption algorithm, dimana kita membutuhkan dua kunci (private key dan public key) untuk melakukan enkripsi dan dekripsi secara berbeda.
nah, kalau menggunakan Keystrore ini kita tidak direpotkan untuk membuat implementasi dari algoritma ini, dan juga tidak harus direpotkan untuk memikirkan bagaimana cara menyimpan key-nya. Tujuan kita kan sebenarnya untuk menyimpan Key (rahasia) yang kita miliki ya? masa kita harus repot lagi untuk menyimpan key yang digunakan untuk melakukan enkripsi dari key yang akan kita gunakan. (hmmm... bingung ya bahasanya)
oke langsung saja ke pambahsan bagaimana cara menggunakan dan implementasi dari keystore ini. Jika kalian belum merasa puas mengenai pembahasan tentang Keystore ataupun AES/RSA kalian bisa menuju ke beberapa artikel yang membahas tentang hal ini, bisa artikel ini atau artikel ini ataupun artikel yang ini.
oya satu lagi, semakin lama Google pun melakukan pembaharuan terhadap OS buatannya (android), jadi ada beberapa hal yang berbeda pada implementasi keystore ini. Khususnya pada Android M (API 23) keatas, implementasi dibuat lebih mudah, jadi kita harus membedakan implemantasi untuk API 18 sampai API 22 dengan implementasi untuk API 23 keatas.

pada implementasi program ini (dengan enkripsi AES) saya membuat tampilan seperti login view, dengan skenario:
1. user mengetikkan username
2. user mengetikkan password
3. user meng-klik tombol submit
4. toast muncul dengan memberikan string hasil enkrpsi
5. user meng-klik tombol cek
6. toast muncul dengan memberikan text asli hasil dekripsi

kita bisa mencoba APK yang sudah saya buat sebelumnya, bisa di download disini.

saya mencoba memasukkan string:
username : kirra
password : mau.nyimpen.string.pake.keystore

dari salah satu contoh implementasi program di atas, kita dimudahkan untuk menyimpan teks rahasia dengan mudah. jadi cara ini salah satu alternatif yang bisa digunakan.


_________________________________________________________________________________
10. Melindungi aplikasi dari device yang di root
Hal ini merupakan salah satu cara untuk melindungi data dari aplikasi yang kita buat. Jadi bagaimana kita bisa mengetahui device dimana aplikasi kita diinstall itu root ataupun tidak. Sehingga ketika kita bisa tau device nya itu di root kita menolak aplikasi kita dijalankan di device itu.

ada beberapa library yang bisa kita gunakan (buat sendiri juga bisa) salah satunya yaitu:
1. rootbeer
2. RootManager

saya merekomendasikan menggunakan RootManager.

public static final String[] SU_BINARY_DIRS = {
            "/system/bin", "/system/sbin", "/system/xbin",
            "/vendor/bin", "/sbin"
    };
public boolean hasRooted() {
        if (hasRooted == null) {
            for (String path : Constants.SU_BINARY_DIRS) {
                File su = new File(path + "/su");
                if (su.exists()) {
                    hasRooted = true;
                    break;
                } else {
                    hasRooted = false;
                }
            }
        }

        return hasRooted;
    }

_________________________________________________________________________________
11. Meletakkan string rahasia di server
Nah sepertinya cara ini cara terakhir, tapi memang tidak termasuk pembahasan artikel ini yang membahas tentang menyimpan key di device android.




========================================================================
========================================================================

Kesimpulan:
Mungkin sekian pembahasan dari artikel ini. Jadi memang ada beberapa cara yang bisa kita lakukan untuk berusaha melindungi sesuatu yang rahasia. Bisa juga kita lakukan kombinasi cara-cara yang ada untuk menghasilkan cara yang baru. misalkan kita mau mengkombinasikan cara 9 dengan cara 7 atau cara 8 dengan cara 9.
Saya hanyalah software developer yang sedang belajar tentang keamanan aplikasi. Saya sangat mengharapkan masukkan kritik saran dikomentar bawah ini. terimakasih


Referensi:
1. https://id.wikipedia.org/wiki/Android_(sistem_operasi)
2. https://source.android.com/
3. https://rammic.github.io/2015/07/28/hiding-secrets-in-android-apps/
4. https://github.com/yukuku/kbbi4/tree/master/android
5. https://developer.android.com/training/articles/keystore.html
6. https://medium.com/@ericfu/securely-storing-secrets-in-an-android-application-501f030ae5a3
7. https://gist.github.com/Diederikjh/36ae22d5fde9d8f671a70b5d8cada90e
8. https://medium.com/@maheshwar.ligade/enabling-proguard-for-android-98e2b19e90a4
9. https://developer.android.com/studio/build/shrink-code.html

No comments:

Post a Comment