비교적 간단한 데이터를 저장하기위해 안드로이드 개발 시 SharedPreferences를 사용한다.
설정에 따라서 SharedPreferences 파일은 프레임워크에서 관리하며 비공개이거나 공개로 설정할 수 있다.


비공개로 설정할 경우 일반적인 방법으로는 저장된 데이터를 확인할수는 없지만, 루팅을 통해 관리자 권한을 획득한 경우 저장된 데이터를 확인할 수있다. 개인정보(카드번호, 인증 비밀번호) 등 중요한 데이터가 저장하여야 하는경우에는 SharedPreferences는 적합하지 않다.

Android SDK 23부터 androidx.security를 통해 EncryptedSharedPreferences를 제공한다.

https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences

 

EncryptedSharedPreferences  |  Android Developers

androidx.constraintlayout.core.motion.parse

developer.android.com

 

기본적인 사용방법은

MasterKey masterKey = new MasterKey.Builder(context)
        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
        .build();

_sharedPreferences = EncryptedSharedPreferences.create(
        context,
        "secret_shared_pref",
        masterKey,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);

 

AES256방식에   암호화 키를 생성하여 생성한 암호화 키로 저장되는 데이터의 AES256_SIV(key) ,AES256_GCM (data)방식으로 키와 데이터를 각각 암호화한다. 

 

(암호화 키 생성 시 keystore를 사용하기 때문에 별도의 키입력을 하지 않으며, 생성된 암호화 키는 컨테이너에 저장되어 저장된 암호화키는 외부에서 추출하기 어렵다.)

https://developer.android.com/training/articles/keystore?hl=ko 

 

SharedPreferences와 동일하게 앱 삭제 시 저장된 데이터도 함꼐 삭제되며, 저장된 데이터는 아래와 같이 암호화되어 저장된다.

 

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a90125a94b1b6aa4f97a630764baecf0e5f4c046a82c8b7947dabc06e71c5170a654d27c1903ffe2da75f84fd1dd011f37c917e9b8ce21d6b4673bbec9127ea066e6adb177f34bc98ff7259331f0d854b78d318226ed62dca1b38ec2dd32598a9357432e0e524a91e9a27393370337acbc5611f8808a6d8bcb724506dcb0e5513e6d6c0cb93d9af1f22cde840c93f3c213adce4bf1cd38aea6464724a1f0bf0bc7153ea84df9b5f4f4344b1a4408b191c8fc03123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118b191c8fc032001</string>
    <string name="AT+SCLGWnuSnzmogArPsMQJbMe92S7STOQ==">AR4mc1e8vYohj66Q91oCIoaMmklTD+DDPStaqibMtsDXatXDJJeskjW7eW9WNTGR</string>
    <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">128801163831f1d036fdc9a33da123fee29b5cda21a49d89684f5fac67e3d54a634de5d8ca990106d0535f0ce74e824f8352e027a37a7512a189a67c183781bf6ce08894b3a622bda2632205c5e5f64389cbff75556bd05d0f8dcd8dc495b9cff09681a7e1e18bae625b7d1513e7301c4ed2aa1e592b97df72474ee9437f75e20e1a019803d7cb3cd9f78f1a4408d7e699f101123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118d7e699f1012001</string>
    <string name="AT+SCLEaHEykuXI9WqXm7wB0ZOTyX/dPWI4=">AR4mc1euqAo6fPFARiDB0ACt92fHt3w1P+64D76rk9Dlyv4ya/hKWgQ5dHy6COIN</string>
</map>

 

 

EncryptedSharedPreferences 을 사용하기 위해서는 Security 라이브러리를 추가 해야함.

(build.gradle의 dependencies추가)

 

implementation "androidx.security:security-crypto-ktx:1.1.0-alpha03"

 

EncryptedSharedPreferences 공통 Class로 사용하기 위한 샘플 소스

 

import android.content.Context;
import android.content.SharedPreferences;

import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKey;

import java.io.IOException;
import java.security.GeneralSecurityException;

public class SharedPreferenceUtil {

    private static SharedPreferenceUtil sharedInstance;
    private Context _context = null;
    private MasterKey masterKey = null;

    private SharedPreferences _sharedPreferences = null;
    private SharedPreferences.Editor _shEditor = null;

    private final static String SECRET_PREFERENCE = "secret_shared_prefs";


    public static synchronized SharedPreferenceUtil getInstance(Context context) throws GeneralSecurityException, IOException {
        if (null == sharedInstance) {
            sharedInstance = new SharedPreferenceUtil(context);
        }
        return sharedInstance;
    }

    public SharedPreferenceUtil(Context context) throws GeneralSecurityException, IOException {
        MasterKey masterKey = new MasterKey.Builder(context)
                .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
                .build();

        _sharedPreferences = EncryptedSharedPreferences.create(
                context,
                SECRET_PREFERENCE,
                masterKey,
                EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
        );
    }

    public void putString(String key, String data) {
        _shEditor.putString(key, data);
        _shEditor.commit();
    }

    public void putInt(String key, int data) {
        _shEditor.putInt(key, data);
        _shEditor.commit();
    }

    public void putFloat(String key, float data) {
        _shEditor.putFloat(key, data);
        _shEditor.commit();
    }

    public void putLong(String key, long data) {
        _shEditor.putLong(key, data);
        _shEditor.commit();
    }

    public void putBoolean(String key, boolean data) {
        _shEditor.putBoolean(key, data);
        _shEditor.commit();
    }

    public void clear() {
        if (null != _shEditor) {
            _shEditor.clear();
            _shEditor.commit();
        }
    }

    public String getString(String key, String defValue) {
        return _sharedPreferences.getString(key, defValue);
    }

    public int getInt(String key, int defValue) {
        return _sharedPreferences.getInt(key, defValue);
    }

    public float getFloat(String key, float defValue) {
        return _sharedPreferences.getFloat(key, defValue);
    }

    public long getLong(String key, long defValue) {
        return _sharedPreferences.getLong(key, defValue);
    }

    public boolean getBoolean(String key, boolean defValue) {
        return _sharedPreferences.getBoolean(key, defValue);
    }
}

 

+ Recent posts