Android डेटाबेस एन्क्रिप्शन


79

एंड्रॉइड डेटा को स्टोर करने के लिए SQLite डेटाबेस का उपयोग करता है, मुझे SQLite डेटाबेस को एन्क्रिप्ट करने की आवश्यकता है, यह कैसे किया जा सकता है? मैं समझता हूं कि एप्लिकेशन डेटा निजी है। हालाँकि मुझे अपने एप्लिकेशन का उपयोग करने वाले SQLite डेटाबेस को आसानी से एन्क्रिप्ट करना होगा।

जवाबों:


68

SQLCipher एक SQLite एक्सटेंशन है जो डेटाबेस फ़ाइलों का पारदर्शी 256-बिट एईएस एन्क्रिप्शन प्रदान करता है।

पहले sqlcipher जो कि SQLite के लिए खुला स्रोत पूर्ण डेटाबेस एन्क्रिप्शन है, Android के लिए उपलब्ध नहीं था। लेकिन अब यह एंड्रॉइड प्लेटफॉर्म के लिए अल्फा रिलीज के रूप में उपलब्ध है। डेवलपर्स ने SQLCipher का उपयोग करने के लिए मानक एंड्रॉइड एप्लिकेशन 'नोटपैडबॉट' को अपडेट किया है।

तो यह निश्चित रूप से अब तक का सबसे अच्छा और सरल विकल्प है।


2
Android के लिए SQLCIpher अब ऑफिशियल SQLCipher प्रोजेक्ट का हिस्सा है: sqlcipher.net/sqlcipher-for-android
डिस्प्ले का नाम

1
लाइसेंस की जानकारी github पेज github.com/sqlcipher/android-database-sqlcipher/blob/master/…
vaichidrewar

2
@vaichidrewar आप पाएंगे कि विशेष लाइसेंस फ़ाइल केवल Android समर्थन भाग पर लागू होती है, SQLCIPHER सामान ( github.com/sqlcipher/android-database-sqlcipher.blob/master/… ) के साथ-साथ अतिरिक्त लाइसेंस फ़ाइलें भी हैं IBM सामग्री ( github.com/sqlcipher/android-database-sqlcipher/blob/master/… )।
हामिद

1
Android में SQLCipher पर सरल उदाहरण के लिए, यहाँ लिंक myownandroid.blogspot.in/2013/09/sqlcipher-in-android.html
jrhamza

SQLCipher उस @vaichidrewar के लिए किसी भी समाधान को धीमा कर देता है ??
अर्श कौशल

28

रोकने के लिए डेटाबेस को एन्क्रिप्ट किया गया है INDIRECT ATTACKS। यह शब्द और कक्षाएं: KeyManager.java , Crypto.java को Sheran Gunasekera की पुस्तक Android Apps Security से लिया गया है । मैं यह सब पुस्तक पढ़ने की सलाह देता हूं।

INDIRECT ATTACKSइसलिए इसका नाम रखा गया है, क्योंकि वायरस सीधे आपके आवेदन के बाद नहीं जाता है। इसके बजाय, यह एंड्रॉइड ओएस के बाद जाता है। उद्देश्य सभी SQLite डेटाबेस को इस उम्मीद में कॉपी करना है कि वायरस लेखक वहां संग्रहीत किसी भी संवेदनशील जानकारी को कॉपी कर सकता है। यदि आपने सुरक्षा की एक और परत जोड़ दी है, तो सभी वायरस लेखक को डेटा की गड़बड़ी दिखाई देगी। आइए एक क्रिप्टोग्राफिक लाइब्रेरी का निर्माण करें जिसे हम अपने सभी अनुप्रयोगों में पुन: उपयोग कर सकते हैं। चलो विनिर्देशों का एक संक्षिप्त सेट बनाकर शुरू करते हैं:

  • सममित एल्गोरिदम का उपयोग करता है: हमारा पुस्तकालय हमारे डेटा को एन्क्रिप्ट और डिक्रिप्ट करने के लिए एक सममित एल्गोरिथ्म या सिफर का उपयोग करेगा। हम एईएस पर समझौता करेंगे, हालांकि हमें बाद की तारीख में इसे संशोधित करने में सक्षम होना चाहिए।

  • एक निश्चित कुंजी का उपयोग करता है: हमें एक कुंजी को शामिल करने में सक्षम होना चाहिए जिसे हम उस डिवाइस पर संग्रहीत कर सकते हैं जिसका उपयोग डेटा एन्क्रिप्ट और डिक्रिप्ट करने के लिए किया जाएगा।

  • डिवाइस पर संग्रहीत कुंजी: डिवाइस पर कुंजी निवास करेगी। हालांकि यह प्रत्यक्ष हमलों के परिप्रेक्ष्य से हमारे आवेदन के लिए एक जोखिम है, लेकिन हमें अप्रत्यक्ष हमलों से बचाने के लिए यह पर्याप्त होना चाहिए।

आइए हमारे प्रमुख प्रबंधन मॉड्यूल के साथ शुरू करें ( सूची 1 देखें )। क्योंकि हम एक निश्चित कुंजी का उपयोग करने की योजना बनाते हैं, इसलिए हमें एक यादृच्छिक उत्पन्न करने की आवश्यकता नहीं होगी जैसा कि हमने पिछले उदाहरणों में किया था। KeyManager इसलिए निम्न कार्य करने होंगे:

  1. पैरामीटर ( setId(byte[] data)विधि) के रूप में एक कुंजी स्वीकार करें
  2. एक पैरामीटर ( setIv(byte[] data) विधि) के रूप में एक प्रारंभिक वेक्टर को स्वीकार करें
  3. इंटरनल स्टोर में फाइल के अंदर की को स्टोर करें
  4. आंतरिक स्टोर ( getId(byte[] data) विधि) में एक फ़ाइल से कुंजी प्राप्त करें
  5. आंतरिक स्टोर में एक फ़ाइल से IV प्राप्त करें ( getIv(byte[] data) विधि)

(लिस्टिंग 1. कीमैनगर मॉड्यूल KeyManager.java )

    package com.yourapp.android.crypto;

    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import android.content.Context;
    import android.util.Log;

    public class KeyManager {

       private static final String TAG = "KeyManager";
       private static final String file1 = "id_value";
       private static final String file2 = "iv_value";
       private static Context ctx;

       public KeyManager(Context cntx) {
         ctx = cntx;
       }

       public void setId(byte[] data){
         writer(data, file1);
       }

       public void setIv(byte[] data){
         writer(data, file2);
       }

       public byte[] getId(){
         return reader(file1);
       }

       public byte[] getIv(){
         return reader(file2);
       }

       public byte[] reader(String file){
         byte[] data = null;
         try {
           int bytesRead = 0;
           FileInputStream fis = ctx.openFileInput(file);
           ByteArrayOutputStream bos = new ByteArrayOutputStream();
           byte[] b = new byte[1024];
           while ((bytesRead = fis.read(b)) != -1){
             bos.write(b, 0, bytesRead);
           }
           data = bos.toByteArray();
         } catch (FileNotFoundException e) {
           Log.e(TAG, "File not found in getId()");
         } catch (IOException e) {
           Log.e(TAG, "IOException in setId(): " + e.getMessage());
         }
         return data;
       }

       public void writer(byte[] data, String file) {
         try {
           FileOutputStream fos = ctx.openFileOutput(file,
           Context.MODE_PRIVATE);
           fos.write(data);
           fos.flush();
           fos.close();
         } catch (FileNotFoundException e) {
           Log.e(TAG, "File not found in setId()");
         } catch (IOException e) {
           Log.e(TAG, "IOException in setId(): " + e.getMessage());
         }
     }
}

अगला, हम क्रिप्टो मॉड्यूल करते हैं ( सूची 2 देखें )। यह मॉड्यूल एन्क्रिप्शन और डिक्रिप्शन की देखभाल करता है। हमने बाइट सरणी डेटा को प्रिंट करने योग्य बेस 64 डेटा और इसके विपरीत में परिवर्तित करना आसान बनाने के लिए मॉड्यूल में एक armorEncrypt()और armorDecrypt()विधि जोड़ी है । हम सिफर ब्लॉक चेनिंग (CBC) एन्क्रिप्शन मोड और PKCS # 5 पैडिंग के साथ एईएस एल्गोरिथ्म का उपयोग करेंगे ।

(लिस्टिंग 2. क्रिप्टोग्राफिक मॉड्यूल Crypto.java )

        package com.yourapp.android.crypto;

        import java.security.InvalidAlgorithmParameterException;
        import java.security.InvalidKeyException;
        import java.security.NoSuchAlgorithmException;
        import javax.crypto.BadPaddingException;
        import javax.crypto.Cipher;
        import javax.crypto.IllegalBlockSizeException;
        import javax.crypto.NoSuchPaddingException;
        import javax.crypto.spec.IvParameterSpec;
        import javax.crypto.spec.SecretKeySpec;
        import android.content.Context;
        import android.util.Base64;

        public class Crypto {

           private static final String engine = "AES";
           private static final String crypto = "AES/CBC/PKCS5Padding";
           private static Context ctx;
           public Crypto(Context cntx) {
             ctx = cntx;
           }

           public byte[] cipher(byte[] data, int mode) throws NoSuchAlgorithmException,NoSuchPaddingException,InvalidKeyException,IllegalBlockSizeException,BadPaddingException,InvalidAlgorithmParameterException {
             KeyManager km = new KeyManager(ctx);
             SecretKeySpec sks = new SecretKeySpec(km.getId(), engine);
             IvParameterSpec iv = new IvParameterSpec(km.getIv());
             Cipher c = Cipher.getInstance(crypto);
             c.init(mode, sks, iv);
             return c.doFinal(data);
           }

           public byte[] encrypt(byte[] data) throws InvalidKeyException,
        NoSuchAlgorithmException, NoSuchPaddingException,
        IllegalBlockSizeException, BadPaddingException,
        InvalidAlgorithmParameterException {
             return cipher(data, Cipher.ENCRYPT_MODE);
           }

           public byte[] decrypt(byte[] data) throws InvalidKeyException,
        NoSuchAlgorithmException, NoSuchPaddingException,
        IllegalBlockSizeException, BadPaddingException,
        InvalidAlgorithmParameterException {
             return cipher(data, Cipher.DECRYPT_MODE);
           }

        public String armorEncrypt(byte[] data) throws InvalidKeyException,NoSuchAlgorithmException,
    NoSuchPaddingException,IllegalBlockSizeException,
    BadPaddingException,InvalidAlgorithmParameterException {
                 return Base64.encodeToString(encrypt(data), Base64.DEFAULT);
               }

         public String armorDecrypt(String data) throws InvalidKeyException,NoSuchAlgorithmException,
    NoSuchPaddingException,IllegalBlockSizeException,
    BadPaddingException,InvalidAlgorithmParameterException {
                 return new String(decrypt(Base64.decode(data, Base64.DEFAULT)));
               }
}

आप अपने किसी भी एप्लिकेशन में इन दो फाइलों को शामिल कर सकते हैं, जिन्हें एन्क्रिप्ट करने के लिए डेटा स्टोरेज की आवश्यकता होती है। सबसे पहले, सुनिश्चित करें कि आपके पास आपकी कुंजी और आरंभीकरण वेक्टर के लिए एक मूल्य है, फिर इसे संग्रहीत करने से पहले अपने डेटा पर एन्क्रिप्ट या डिक्रिप्ट विधियों में से किसी एक को कॉल करें। सूची 3 और सूची 4 में इन वर्गों का उपयोग करते हुए एक बस ऐप-उदाहरण है। हम 3 बटन एनक्रिप्ट, डिक्रिप्ट, डिलीट के साथ एक गतिविधि बनाते हैं; डेटा इनपुट के लिए 1 EditText; डेटा आउटपुट के लिए 1 टेक्स्ट व्यू।

(लिस्टिंग 3. एक उदाहरण। MainActivity.java )

package com.yourapp.android.crypto;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


public class MainActivity extends Activity {
    TextView encryptedDataView;
    EditText editInputData;
    private Context cntx;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.cntx = getApplicationContext();
        Button btnEncrypt = (Button) findViewById(R.id.buttonEncrypt);
        Button btnDecrypt = (Button) findViewById(R.id.buttonDecrypt);
        Button btnDelete = (Button) findViewById(R.id.buttonDelete);
        editInputData = (EditText)findViewById(R.id.editInputData) ;
        encryptedDataView = (TextView) findViewById(R.id.encryptView);

        /**********************************************/
            /** INITIALIZE KEY AND INITIALIZATION VECTOR **/
        String key = "12345678909876543212345678909876";
        String iv = "1234567890987654";
        KeyManager km = new KeyManager(getApplicationContext());
        km.setIv(iv.getBytes());
        km.setId(key.getBytes());
        /**********************************************/

        btnEncrypt.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                String Data = editInputData.getText().toString();
                String Encrypted_Data = "data";
                try {
                    Crypto crypto = new Crypto(cntx);
                    Encrypted_Data = crypto.armorEncrypt(Data.getBytes());
                }   catch (InvalidKeyException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (NoSuchAlgorithmException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (NoSuchPaddingException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (IllegalBlockSizeException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (BadPaddingException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (InvalidAlgorithmParameterException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    }
                encryptedDataView.setText(Encrypted_Data);
            }
        });

        btnDecrypt.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                String Data = encryptedDataView.getText().toString();
                String Decrypted_Data = "data";
                try {
                    Crypto crypto = new Crypto(cntx);
                    Decrypted_Data = crypto.armorDecrypt(Data);
                }   catch (InvalidKeyException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (NoSuchAlgorithmException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (NoSuchPaddingException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (IllegalBlockSizeException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (BadPaddingException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    } catch (InvalidAlgorithmParameterException e) {
                    Log.e("SE3", "Exception in StoreData: " + e.getMessage());
                    }
                encryptedDataView.setText(Decrypted_Data);
            }
        });

        btnDelete.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                encryptedDataView.setText(" Deleted ");
            }
        });

    }

}

(लिस्टिंग 4. एक उदाहरण। activity_main.xml)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#363636"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <EditText
        android:id="@+id/editInputData"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:ems="10"
        android:textColor="#FFFFFF" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@+id/encryptView"
        android:layout_width="fill_parent"
        android:layout_height="100dp"
        android:layout_alignLeft="@+id/editInputData"
        android:layout_alignRight="@+id/editInputData"
        android:layout_below="@+id/buttonEncrypt"
        android:layout_marginTop="26dp"
        android:background="#000008"
        android:text="Encrypted/Decrypted Data View"
        android:textColor="#FFFFFF"
        android:textColorHint="#FFFFFF"
        android:textColorLink="#FFFFFF" />

    <Button
        android:id="@+id/buttonEncrypt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/encryptView"
        android:layout_alignRight="@+id/editInputData"
        android:layout_below="@+id/editInputData"
        android:layout_marginTop="26dp"
        android:text="Encrypt" />

    <Button
        android:id="@+id/buttonDelete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/buttonDecrypt"
        android:layout_alignRight="@+id/buttonDecrypt"
        android:layout_below="@+id/buttonDecrypt"
        android:layout_marginTop="15dp"
        android:text="Delete" />

    <Button
        android:id="@+id/buttonDecrypt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/encryptView"
        android:layout_alignRight="@+id/encryptView"
        android:layout_below="@+id/encryptView"
        android:layout_marginTop="21dp"
        android:text="Decrypt" />

</RelativeLayout>

8
यदि कुंजी को उपकरण में संग्रहीत किया जाता है, तो उस कुंजी का उपयोग करके डेटा को एन्क्रिप्ट करने, एन्क्रिप्ट करने के क्या लाभ हैं?
मिन्हाज

कैसे सेट करें और किसी अन्य फ़ाइल से कुंजी प्राप्त करें .. क्या आप एक कार्यशील उदाहरण दे सकते हैं ?? पठन (फाइल) पर एनपीई प्राप्त करना
गजु कोल्लूर

13

यदि डेटाबेस छोटा होगा, तो आप पूरी फ़ाइल को एक अस्थायी स्थान (एसडी कार्ड पर नहीं) में डिक्रिप्ट करके थोड़ी मात्रा में सुरक्षा प्राप्त कर सकते हैं, जब आपने इसे बंद कर दिया है तो फिर से एन्क्रिप्ट करें। समस्याएं: समय से पहले मौत, मीडिया पर भूत की छवि।

डेटा फ़ील्ड को एन्क्रिप्ट करने के लिए थोड़ा बेहतर समाधान। यह WHERE और ORDER BY क्लॉस के लिए एक समस्या का कारण बनता है। यदि एन्क्रिप्ट किए गए फ़ील्ड को समतुल्य खोज के लिए अनुक्रमित करने की आवश्यकता है, तो आप फ़ील्ड के क्रिप्टोग्राफ़िक हैश को स्टोर कर सकते हैं और उसके लिए खोज कर सकते हैं। लेकिन यह सीमा खोज या ऑर्डर करने में मदद नहीं करता है।

यदि आप कट्टर होना चाहते हैं, तो आप Android NDK में तल्लीन कर सकते हैं और कुछ क्रिप्टोकरंसी को SQLite के लिए C कोड में हैक कर सकते हैं।

इन सभी समस्याओं और आंशिक समाधानों को ध्यान में रखते हुए, क्या आप वाकई आवेदन के लिए SQL डेटाबेस की आवश्यकता है? आप एक फ़ाइल की तरह कुछ के साथ बेहतर हो सकते हैं जिसमें एक एन्क्रिप्टेड क्रमबद्ध वस्तु होती है।


3

आप निश्चित रूप से एंड्रॉइड पर एक एन्क्रिप्टेड SQLite डेटाबेस हो सकते हैं। हालाँकि, आप Google द्वारा प्रदान की गई कक्षाओं के बॉक्स के साथ ऐसा नहीं कर सकते।

कुछ विकल्प:

  • NDK के माध्यम से अपनी खुद की SQLite संकलित करें और उदाहरण के लिए एन्क्रिप्शन कोडेक शामिल करें, wxSQLite3 (पैकेज में एक अच्छा मुफ्त कोडेक शामिल है)
  • SQLCipher में अब Android का समर्थन शामिल है

1

http://sqlite-crypt.com/ एक एन्क्रिप्टेड डेटाबेस बनाने में आपकी मदद कर सकता है, हालांकि मैंने इसे कभी भी एंड्रॉइड पर उपयोग नहीं किया है ऐसा लगता है कि स्रोत कोड के साथ संभव है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.