آموزش رمز گذاری بروی دیتابیس sqlite در اندروید
سلام دوستان در این سری از آموزش برنامه نویسی اندروید به آموزش رمز گذاری بروی دیتابیس sqlite در اندروید می پردازیم حتما این آموزش را دنبال کنید به تازگی هر برنامه که در کافه بازار منتشر می شود بعد از چند ساعت یک اپ مشابه آن نیز انتشار پیدا می کند پس هر برنامه ای که دیتابیس داشته باشد به راحتی decompile می شود حالا سوال اینجاست چه طور decompile می شود و راه جلوگیری از چیست در ادامه با ما همراه باشید.
اگر برنامه شما کد (encrypt) نشده باشد اگر Extension آن منظور apk یا پسوند آخر آن است آن را تغییر دهید و بکنید .zip مشاهده می کنید که به بخشی از اپ دسترسی پیدا کردید یعنی اگر نام فایل برابر با test.apk بود به test.zip تغییرش دهید و آن را باز کنید ما کاری به این نداریم فقط یک آموزش بود شما این کار رو نکنید. (البته استفاده از آن دردسر دارد )
چه گونه جلوگیری کنیم ؟
قبل از اینکه راه جلوگیری آن را بگیم یک عیب این کار دارد . این کار باعث می شود حجم دیتابیس چند کیلوبایتی ما به چند مگ تبدیل شود ولی راهی برای کم حجم کردن آن هست شما باید خود دیتابیس را نیز فشرده کنید منظور فشرده سازی معمولی نیست و این نوع فشرده سازی کار هر کسی نیست باید حداقل چند سال در این زمینه کار کرده باشید روشی که ما استفاده می کنیم به نام sqlcipher است.
برای شروع ابتدا کتاب خانه زیر را اضافه کنید.
پس وارد فایل Build.gradle از نوع module شده و در بخش dependencies خط زیر را اضافه کنید.
1 | compile 'net.zetetic:android-database-sqlcipher:3.3.1-2@aar' |
دیگر در اینجا کد های تکراری را توضیح نخواهیم داد و فقط بخش مربوط به encryption رو توضیح می دهیم.
یک فایل جاوا به نام FeedReaderContract.java ایجاد کرده و کد های زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 | 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 ایجاد کنید و کد زیر را در آن قرار دهید.
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 | 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 زیر است
1 | onDowngrade() |
از این void برای بررسی api گوشی استفاده می شود چون sqlcipher از api 2.1 به بالا کار می کند البته فکر نمی کنم دیگر گوشی در این api وجود داشته باشد ولی در کل گفتم که بدونید.
حالا برویم به سراغ ادامه کار در MainActivity.java خود کد زیر را قرار دهید.
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 | 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 ساده انجام داده ایم ! بخش مهم کار که در هیچ سایتی نوشته نشده است خط زیر است.
1 | SQLiteDatabase.loadLibs(this); |
شاید اگر آموزش دیتابیس را خوانده باشید کد زیر برای شما آشنا باشد.
1 | db = FeedReaderDbHelper.getInstance(this).getWritableDatabase(""); |
این کار باعث میشه تا هم حجم دیتابیس بالا رود و هم با خطای زیر مواجه می شوید
1 | net.sqlcipher.database.SQLiteException: file is encrypted or is not a database: create locale table failed |
با بررسی که انجام دادم خود sqlcipher داری یک فشرده ساز فوق العاده است که در بالا بری شما کد آن را قرار دادم .
این آموزش هم به پایان رسید.
موفق و موید باشید.
سلام
اگر بخواییم در محیط eclipse این کار را انجام بدیم باید چه کتابخانه ای را به برنامه اضافه کنیم. فایل jar مربوط به sqlcipher رو اضافه کردم اما کلاس ها رو نمیشناسه
ممنون میشم راهنمایی کنید
سلام فایل jar مربوط به sqlcipher بروزرسانی نشده است یعنی متودهایی که ما در برنامه استفاده کردیم را نمی شنانسد باید حتما از گریدل استفاده کنید.
سلام من یه فایل دیتابیس با فرمت .sqlite دارم و الان رویه اپم داره کاره می کنه منظورم اینکه کلی تبل و فیلدو اطلاعات اولیه و اینجور چیزا داره حالا میخوام رو همین فایل دیتابیسم که تو پوشه asset اپم میاد رویه حافظه خارجی گوشی ینی کپی میشه میخام تبدیلش کنم به دیتابیس رمز نگاری میشه بگید باید چیکارش کنم منظورم خوده فایلی هستش که ابتدا به ساکنش رمز روش باشه و کسی نتونه بهش دسترسی داشته باشه
با سلام
برا دیتابیس که از اول در برنامه قرار بدیم این امکانش نیست؟؟
خیر ولی میشه خود داده های داخلش رو کد کرد.
سلام اگر میشه راهنمایی بیشتری بکنین مرسی
مثلا شما یک String به نام hossein بعد میاید این رو با یکسری کتاب خانه یا متود های رمزگذاری تبدیل می کنیدش به @sf%dGs و در دیتابیس خود insert می کنید از آنجایی که متود های رمزگذاری داری Deprecatory یا رمزنگار هستن موقع خواندن این را @sf%dGs به ورودی آن میدهد و خروجی به شما hossein تحویل میدهد.
موفق باشید.
ممنون 🙂
این متد ها میتونه دستی باشه یعنی میشه خودمون هم یک الگوریتم بنویسیم یا کلاس های آماده ای هم هستند؟؟
پ ن : یک موردی در سایت اگه اضافه کنین واقعا بسیار عالی میشه
مثلا من با نام کاربری خودم وارد سایت شدم در مثلا 12 مطلب میام نظر ارسال می کنم و سوالم رو مطرح می کنم و منتظر جواب می مونم ولی بعدا که بخوام چک کنم که من در چه مطالبی نظر ارسال کردم و دوباره برم چک کنم که آیا جوابی داده شده یا نه پیدا کردنشون واقعا سخت میشه
اگه بشه یک امکانی اضافه کنین مثلا من در این مطلب نظر ارسال کردم در پنل خودم یک لیستی از مطالبی که من در اون نظر ارسال کردم نمایش داده بشه
با تشکر
سلام بله می شود یک کلاس Encryption سفارشی خودتون درست کنید
از بخش زیر می تونید استفاده کنید.
https://programchi.ir/author/mojtaba1376/
سلام.
اگه ازین روش استفاده کنیم حجم دیتابیس و در حقیقت حجم اپمون بیشتر میشه؟ چقدر؟
سرعت کار ها (کویری ، در ج و دیلیت و آپدیت) چقدر کم میشه؟ خیلی محسوسه؟
من از content provider هم برای کار با دیتابیس استفاده میکنم. مشکلی که پیش نمیاد؟
—-
روش های دیگه چی؟ میشه کرک شده ی see و .. رو پیدا کرد؟
سلام و دورد
حجمش حدودا یک مگ میشه در بهترین حالت در بدترین جالت 4 تا 5 مگ سرعتش خوبه مشکلی با content provier نداره
موفق باشید.
سلام.
من از این روش استفاده کردم اما یکجا به ارور رسیدم که در اینترنت هم به جوابی نرسیدم
زمانی که میخوام
SQLiteDatabase db = ModelBus.getInstance(this).getWritableDatabase(“”);
بنویسم از قسمت زیر اشکال میگیرد که میکوید کانستراکتور این قسمت ورودی نمیپذیرد و نمیگذارد استیرینگی وارد شود
getWritableDatabase(“؟؟؟؟؟؟”)
ممنون میشم راهنمایی کنید مهندس جان
سلام
چرا داخل پرانتز خالیه؟
مگه بانکت پسورد نداره؟؟
من اینجور نوشتم و جواب گرفتم
SQLiteDatabase db = instance.getWritableDatabase(PASS_WORD);
سلام
وقت بخیر
من یه مشکل دارم؟؟
برنامه من روی شبیه ساز با ورژن اندروید 4.4.4 درست اجرا میشه ، اما روی گوشی با اندروید 7 درست اجرا نمیشه؟؟
ممنون میشم راهنمایی کنید
سلام
لطفا استفاده از sqlcipher برای دیتابیس آماده رو هم بفرمایید.
متشکر
میشه لطف کنید آموزش رمزنگاری روی دیتابیس آماده رو قرار بدید .
واقعا نیاز هست تشکر
سلام
چرا واقعا هیچ منبع فارسی در مورد رمز نگاری روی دیتابیس اماده صحبتی نکرده لطفااااااااا به موضوع به این مهمی بپردازید!!!!!!!!!!!!!!!!!