やること
ConcealとはFacebook社がオープンソースで開発している、Android用の暗号化ライブラリです。今回はこのライブラリを用いて文字列を暗号化してPreferenceに保存します。
暗号
storeKey.java
public static void storeToken(Context context, String token){
SharedPreferences preferences = context.getSharedPreferences(PreferenceValue.PREF_KEY, Context.MODE_PRIVATE);
SharedPreferences.Editor editor;
String accessKey = UUID.randomUUID().toString();
editor = preferences.edit();
Crypto crypto = new Crypto(
new SharedPrefsBackedKeyChain(context),
new SystemNativeCryptoLibrary());
if(!crypto.isAvailable()){
return;
}
try {
byte[] encryptedKey = crypto.encrypt(token.getBytes(), new Entity(accessKey));
editor.putString(PreferenceValue.TOKEN_ACCESS_KEY, accessKey);
editor.putString(PreferenceValue.ENCRYPTED_KEY, Base64.encodeToString(encryptedKey, Base64.DEFAULT));
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}catch (CryptoInitializationException e){
e.printStackTrace();
}catch(KeyChainException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
editor.apply();
}
今回は秘密鍵としてUUIDを用いました。また、byte型はPreferencesに保存できないのでBase64エンコーディングでSting型に変換して保存しました。また秘密鍵もPreferenceに保存しました。
復号
getKey.java
public static String getToken(Context context){
SharedPreferences preferences = context.getSharedPreferences(PreferenceValue.PREF_KEY, Context.MODE_PRIVATE);
String accessKey = preferences.getString(PreferenceValue.TOKEN_ACCESS_KEY, null);
String encryptedToken = preferences.getString(PreferenceValue.ENCRYPTED_KEY, null);
byte[] rawEncryptedToken = null;
String rawDecryptedToken = null;
if(encryptedToken!=null&&accessKey!=null) {
rawEncryptedToken = Base64.decode(encryptedToken, Base64.DEFAULT);
Crypto crypto = new Crypto(
new SharedPrefsBackedKeyChain(context),
new SystemNativeCryptoLibrary());
if (!crypto.isAvailable()) {
return null;
}
try {
byte[] decryptedToken = crypto.decrypt(rawEncryptedToken, new Entity(accessKey));
rawDecryptedToken = new String(decryptedToken);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (CryptoInitializationException e) {
e.printStackTrace();
} catch (KeyChainException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return rawDecryptedToken;
}
参照側のメソッドでも取り出した文字列をBase64でデコードしてbyte型に変換したあとで、同じくPreferenceに保存した秘密鍵を使って復号している。
これで一応、Preferenceの中の文字列は暗号化された状態になります。
しかし、Androidはリバースエンジニアリングが容易に出来てしうので、大事なデータを端末に保存するのはできるだけやめたほうがいいと考えられます。ちなみに以下のリンクでは秘密鍵の保存場所をNDKのコードに格納しているようです。
参考文献
http://techracho.bpsinc.jp/baba/2012_09_23/6178
http://qiita.com/kobakei/items/cb67f8b605b69b11b4eb