آموزش رمز گذاری بروی دیتابیس sqlite در اندروید

سلام دوستان در این سری از آموزش برنامه نویسی اندروید به آموزش رمز گذاری بروی دیتابیس sqlite در اندروید می پردازیم حتما این آموزش را دنبال کنید به تازگی هر برنامه که در کافه بازار منتشر می شود بعد از چند ساعت یک اپ مشابه آن نیز انتشار پیدا می کند پس هر برنامه ای که دیتابیس داشته باشد به راحتی decompile می شود حالا سوال اینجاست چه طور decompile می شود و راه جلوگیری از چیست در ادامه با ما همراه باشید.
اگر برنامه شما کد (encrypt) نشده باشد اگر Extension آن منظور apk یا پسوند آخر آن است آن را تغییر دهید و بکنید .zip مشاهده می کنید که به بخشی از اپ دسترسی پیدا کردید یعنی اگر نام فایل برابر با test.apk بود به test.zip تغییرش دهید و آن را باز کنید ما کاری به این نداریم فقط یک آموزش بود شما این کار رو نکنید. (البته استفاده از آن دردسر دارد )

چه گونه جلوگیری کنیم ؟

قبل از اینکه راه جلوگیری آن را بگیم یک عیب این کار دارد . این کار باعث می شود حجم دیتابیس چند کیلوبایتی ما به چند مگ تبدیل شود ولی راهی برای کم حجم کردن آن هست شما باید خود دیتابیس را نیز فشرده کنید منظور فشرده سازی معمولی نیست و این نوع فشرده سازی کار هر کسی نیست باید حداقل چند سال در این زمینه کار کرده باشید روشی که ما استفاده می کنیم به نام sqlcipher است.
برای شروع ابتدا کتاب خانه زیر را اضافه کنید.
پس وارد فایل Build.gradle از نوع module شده و در بخش dependencies خط زیر را اضافه کنید.

compile 'net.zetetic:android-database-sqlcipher:3.3.1-2@aar'

دیگر در اینجا کد های تکراری را توضیح نخواهیم داد و فقط بخش مربوط به encryption رو توضیح می دهیم.
یک فایل جاوا به نام FeedReaderContract.java ایجاد کرده و کد های زیر را در آن قرار دهید.

    package ir.programchi;
    import android.provider.BaseColumns;
    public final class FeedReaderContract {
        public FeedReaderContract() {}
        public static abstract class FeedEntry implements BaseColumns {
            public static final String TABLE_NAME = "news";
            public static final String COLUMN_NAME_ENTRY_ID = "news_id";
            public static final String COLUMN_NAME_TITLE = "title";
            public static final String COLUMN_NAME_SUBTITLE = "subtitle";
        }
    }

یک کلاس دیگر جاوا به نام FeedReaderDbHelper.java ایجاد کنید و کد زیر را در آن قرار دهید.

 package ir.programchi;
    import android.content.Context;
    import net.sqlcipher.database.SQLiteDatabase;
    import net.sqlcipher.database.SQLiteOpenHelper;
    public class FeedReaderDbHelper extends SQLiteOpenHelper {
        private static FeedReaderDbHelper instance;
        public static final int DATABASE_VERSION = 1;
        public static final String DATABASE_NAME = "FeedReader.db";
        private static final String TEXT_TYPE = " TEXT";
        private static final String SQL_CREATE_ENTRIES =
                "CREATE TABLE " + FeedReaderContract.FeedEntry.TABLE_NAME + " (" +
                        FeedReaderContract.FeedEntry._ID + " INTEGER PRIMARY KEY," +
                        FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + "," +
                        FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + "," +
                        FeedReaderContract.FeedEntry.COLUMN_NAME_SUBTITLE + TEXT_TYPE +
                        " )";
        private static final String SQL_DELETE_ENTRIES =
                "DROP TABLE IF EXISTS " + FeedReaderContract.FeedEntry.TABLE_NAME;
        public FeedReaderDbHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
        static public synchronized FeedReaderDbHelper getInstance(Context context) {
            if (instance == null) {
                instance = new FeedReaderDbHelper(context);
            }
            return instance;
        }
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(SQL_CREATE_ENTRIES);
        }
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL(SQL_DELETE_ENTRIES);
            onCreate(db);
        }
    }

در بالا SQLiteDatabase و SQLiteOpenHelper از net.sqlcipher.database نه از کلاس android.database.sqlite یه چیزی که در کد بالا استفاده نشده است void زیر است

onDowngrade()

از این void برای بررسی api گوشی استفاده می شود چون sqlcipher از api 2.1 به بالا کار می کند البته فکر نمی کنم دیگر گوشی در این api وجود داشته باشد ولی در کل گفتم که بدونید.
 
حالا برویم به سراغ ادامه کار در MainActivity.java خود کد زیر را قرار دهید.

package ir.programchi;
    import android.app.Activity;
    import android.content.ContentValues;
    import android.os.Bundle;
    import android.util.Log;
    import net.sqlcipher.Cursor;
    import net.sqlcipher.database.SQLiteDatabase;
    public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SQLiteDatabase.loadLibs(this);
        insertSthToDb();
    }
    private void insertSthToDb() {
        SQLiteDatabase db = FeedReaderDbHelper.getInstance(this).getWritableDatabase("somePass");
        ContentValues values = new ContentValues();
        values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID, 1);
        values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE, "Programchi.ir");
        values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_SUBTITLE, "The Best Programming Site !");
        db.insert(FeedReaderContract.FeedEntry.TABLE_NAME, null, values);
        Cursor cursor = db.rawQuery("SELECT * FROM '" + FeedReaderContract.FeedEntry.TABLE_NAME + "';", null);
        Log.d(MainActivity.class.getSimpleName(), "Rows count: " + cursor.getCount());
        cursor.close();
        db.close();
    }
}

در بالا ما یک insert ساده انجام داده ایم ! بخش مهم کار که در هیچ سایتی نوشته نشده است خط زیر است.

        SQLiteDatabase.loadLibs(this);

شاید اگر آموزش دیتابیس را خوانده باشید کد زیر برای شما آشنا باشد.

       db = FeedReaderDbHelper.getInstance(this).getWritableDatabase("");

این کار باعث میشه تا هم حجم دیتابیس بالا رود و هم با خطای زیر مواجه می شوید

net.sqlcipher.database.SQLiteException: file is encrypted or is not a database: create locale table failed

با بررسی که انجام دادم خود sqlcipher داری یک فشرده ساز فوق العاده است که در بالا بری شما کد آن را قرار دادم .
 
این آموزش هم به پایان رسید.
 
موفق و موید باشید.

مطالعه بیشتر