SlideShare une entreprise Scribd logo
1  sur  69
Télécharger pour lire hors ligne
C-LIS CO., LTD.
自己紹介
Android Studio本
3
2014年11月21日発売
技術評論社刊
Android Studio 0.8.6
http://amzn.to/1HYRp32
4
5
https://github.com/keiji/the-androidstudio-book
コミックマーケット87

Android Studioセットアップガイド
6
https://anharu.keiji.io
はじめての
Androidアプリ開発レッスン
7
改訂版が出ます(2016年1月上旬予定)
改訂版の原稿を送ったのが11月16日
9
11月20日
サンプルコードのプロジェクトを

Android 1.5用に調整したのが11月23日
11月24日
11
Android Studio 2.0 Preview
続く
Realmの暗号化と

Android System
2015/11/25 Realm Meetup #9
今日の内容
データの保護
15
 ユーザーや悪意のある開発者からデータを保護したい。
 安全にデータを保管するための方法として

「javax.cryptoによるデータベースファイルの保護」

「SQLCipherを使った保護」

「Realmの暗号化機能」

 の、三つについて、それぞれ利用して比較する。
鍵の保護
16
 暗号化したデータの復号鍵をどこに保存するかは大きな
課題である。
 Android 6.0で大幅に強化された「Android Keystore
System」を使って、データを安全に保護する方策を検討
する。
 
データの保護を検討する
https://github.com/keiji/realm_meetup_9/releases/tag/realm_meetup_9
{

"characters": [

{

"name": "Uduki Shimamura",

"age": "17",

"megane": false

},

{

"name": "Rin Shibuya",

"age": "15",

"megane": false

},

{

"name": "Haruna Kamijo",

"age": "18",

"megane": true

},
サンプルアプリ
18
https://github.com/keiji/realm_meetup_9/releases/tag/realm_meetup_9
アプリの動作
https://github.com/keiji/realm_meetup_9/releases/tag/realm_meetup_9
{

"characters": [

{

"name": "Uduki Shimamura",

"age": "17",

"megane": false

},

{

"name": "Rin Shibuya",

"age": "15",

"megane": false

},

{

"name": "Mio Honda",

"age": "15",

"megane": false

},

{

"name": "Hina Araki",

"age": "20",

"megane": false

},

characters.json
Database
ユーザー
検索 &
一覧表示
JSONパース
保存
19
検索条件
{

"characters": [

{

"name": "Uduki Shimamura",

"age": "17",

"megane": false

},

{

"name": "Rin Shibuya",

"age": "15",

"megane": false

},

{

"name": "Haruna Kamijo",

"age": "18",

"megane": true

},
これがtrue
https://github.com/keiji/realm_meetup_9/releases/tag/realm_meetup_9
20
実行画面
21
javax.crypto
22
•Androidに組み込まれている暗号化フレームワーク
•AES 256-bitに対応している
暗号化したデータベースファイルを、
利用時に限定して復号する
@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);



setContentView(R.layout.user_list);

mListView = (ListView) findViewById(R.id.listview);



getSupportLoaderManager().restartLoader(LOADER_ID_DECRYPT, null, mCipherLoaderCallback);

}



@Override

protected void onDestroy() {

super.onDestroy();



mDb.close();



new EncryptTask(getDatabasePath(DbHelper.DB_FILE_NAME)).execute();

}
sqlite.SQLiteActivity
23
private static final String TRANSFORMATION = "AES/CBC/PKCS7Padding";

private static final byte[] KEY = "thisismypa55w0rdthisismypa55w0rd".getBytes();

sqlite.SQLiteActivity
24
SecretKeySpec key = new SecretKeySpec(KEY, "AES");



Cipher cipher = Cipher.getInstance(TRANSFORMATION);

cipher.init(Cipher.ENCRYPT_MODE, key);



byte[] buffer = new byte[cipher.getBlockSize()];

int len;



while ((len = is.read(buffer)) != -1) {

byte[] encrypted = cipher.update(buffer, 0, len);

os.write(encrypted);

}

os.write(cipher.doFinal());



rawDbFile.deleteOnExit();
32byte必要
テーブル構造
25
private static final String CREATE_TABLE_USERS = "CREATE TABLE characters ( " +

"_id INTEGER PRIMARY KEY," +

"name TEXT," +

"age INTEGER," +

"megane INTEGER" +

" )";

public static Character read(Cursor cursor) {

Character user = new Character();

user.name = cursor.getString(cursor.getColumnIndex("name"));

user.age = cursor.getInt(cursor.getColumnIndex("age"));

user.megane = cursor.getInt(cursor.getColumnIndex("megane")) == 1;

return user;

}



public static Cursor findAllMeganeCursor(SQLiteDatabase db) {

return db.query("characters", new String[]{"_id", "name", "age", "megane"},

"megane = ?", new String[]{Integer.toString(1)}, null, null, null);

}

sqlite.DbHelper.java
sqlite.entity.Character.java
問題点
26
復号してデータベースにアクセスしている間、

暗号化されていないデータがファイルシステム上に存在する
SQLCipher
27
•Zetetic社が開発、提供する暗号化機能付きSQLite
•AES 256-bitで暗号化
•透過的にアクセス可能
暗号化したままデータを読み書きする
公式ではバイナリを配布せず
28
SQLCipherは、基本的に有償版を推しているイメージ。
オープンソース版のCommunity Editionは個々でビルドする
dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

testCompile 'junit:junit:4.12'

compile 'com.android.support:appcompat-v7:23.1.1'

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



}

BintrayでAndroid版を入手
app/build.gradle
29
private static final String DB_PASSWORD = "pa55w0rd";

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);



SQLiteDatabase.loadLibs(this);



setContentView(R.layout.user_list);

mListView = (ListView) findViewById(R.id.listview);



if (!getDatabasePath(DbHelper.DB_FILE_NAME).exists()) {

mDb = new DbHelper(this).getWritableDatabase(DB_PASSWORD);

getSupportLoaderManager().restartLoader(LOADER_ID, null, mLoaderCallback);

sqlcipher.SQLCipherActivity
30
テーブル構造
31
private static final String CREATE_TABLE_USERS = "CREATE TABLE characters ( " +

"_id INTEGER PRIMARY KEY," +

"name TEXT," +

"age INTEGER," +

"megane INTEGER" +

" )";

public static Character read(Cursor cursor) {

Character user = new Character();

user.name = cursor.getString(cursor.getColumnIndex("name"));

user.age = cursor.getInt(cursor.getColumnIndex("age"));

user.megane = cursor.getInt(cursor.getColumnIndex("megane")) == 1;

return user;

}



public static Cursor findAllMeganeCursor(SQLiteDatabase db) {

return db.query("characters", new String[]{"_id", "name", "age", "megane"},

"megane = ?", new String[]{Integer.toString(1)}, null, null, null);

}

sqlcipher.DbHelper.java
sqlcipher.entity.Character.java
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[
DexPathList[
[zip file "/data/app/io.keiji.realmsample2-2/base.apk"],
nativeLibraryDirectories=[/data/app/io.keiji.realmsample2-2/lib/arm64,
/data/app/io.keiji.realmsample2-2/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]]
couldn't find "libstlport_shared.so"
at java.lang.Runtime.loadLibrary(Runtime.java:367)
at java.lang.System.loadLibrary(System.java:1076)
at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:173)
at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:169)
at io.keiji.realmsample2.sqlcipher.SQLCipherActivity.onCreate(SQLCipherActivity.java:83)
at android.app.Activity.performCreate(Activity.java:6237)
Android 6.0(Marshmallow)
32
問題点
33
SQLCipherのSQLiteDatabaseクラスは、

net.sqlcipher.databaseパッケージに所属している。
SQLiteDatabaseとの継承関係もないため、

一般的なORMとの相性は良くないと思われる
Realm
34
•Realm社が開発、提供するNoSQLデータベース
•AES 256-bitで暗号化
•透過的にアクセス可能
読み書き中もデータは暗号化されたまま
データが抜き出されても現実的な時間では解読が困難
public class RealmAdapter {



private static final byte[] KEY
= "thisismypa55w0rdthisismypa55w0rdthisismypa55w0rdthisismypa55w0rd".getBytes();



public RealmConfiguration getRealmConfiguration(Context context) {

return new RealmConfiguration.Builder(context)

.encryptionKey(KEY)

.build();

}

}
 64byte必要
@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);



setContentView(R.layout.user_list);



mRealmAdapter = new RealmAdapter();



mRealm = Realm.getInstance(mRealmAdapter.getRealmConfiguration(this));



realm.RealmActivity
35
RealmResults<Character> realmResult = mRealm

.where(Character.class)

.equalTo("megane", true)

.findAll();

mListView = (ListView) findViewById(R.id.listview);

mAdapter = new Adapter(this, realmResult, true);

mListView.setAdapter(mAdapter);

情報を検索して表示
public class Adapter extends RealmBaseAdapter<Character> {



@Override

public View getView(int position, View convertView, ViewGroup parent) {

Character character = getItem(position);



ViewHolder holder = null;

if (convertView == null) {

convertView = View.inflate(RealmActivity.this, R.layout.user_list_row, null);

holder = new ViewHolder((TextView) convertView.findViewById(R.id.label));

convertView.setTag(holder);

}

36
遭遇した課題
createObjectFromJson
38
{

"characters": [

{

"name": "Uduki Shimamura",

"age": "17",

"megane": false

},

{

"name": "Rin Shibuya",

"age": "15",

"megane": false

},

{

"name": "Haruna Kamijo",

"age": "18",

"megane": true

},
public class Character extends RealmObject {



private long id;



private String name;



private Integer age;



private boolean megane = true;

public class Characters extends RealmObject {



private RealmList<Character> characters;

createObjectFromJson
39
public class JsonLoaderRealmJson extends AsyncTaskLoader<LoaderResult> {

@Override

public LoaderResult loadInBackground() {



LoaderResult result;



Realm realm = Realm.getInstance(realmAdapter.getRealmConfiguration(getContext()));



try {



realm.beginTransaction();

realm.createObjectFromJson(Characters.class, getContext().getAssets().open(JSON_FILE_NAME));

realm.commitTransaction();



result = new LoaderResult(null);



} catch (IOException e) {

想定していないデータの存在
40
{

"name": "Kirari Moroboshi",

"age": "17",

"megane": false

},

{

"name": "Nana Abe",

"age": "永遠の17歳",

"megane": false

},

{

"name": "Akiha Ikebukuro",

"age": "14",

"megane": true

}

]

public class Character extends RealmObject {



private long id;



private String name;



private Integer age;



private boolean megane = true;

public class Characters extends RealmObject {



private RealmList<Character> characters;

課題の解決 - JPP
41
JsonPullParser

https://github.com/vvakame/JsonPullParser

を導入して、Jsonのパース処理をRealmから切り離した。
参考: RealmとJSONライブラリ by zaki50
https://speakerdeck.com/zaki50/realmtojsonraiburari
課題の解決
42
@JsonModel

public class Characters4Jpp {



@JsonKey

private List<Character> characters;



public List<Character> getCharacters() {

return characters;

}



public void setCharacters(List<Character> characters) {

this.characters = characters;

}

}

converterを指定
43
@JsonModel

public class Character extends RealmObject {



@JsonKey

private long id;



@JsonKey

private String name;



@JsonKey(converter = AgeTokenConverter.class)

private Integer age;



@JsonKey

private boolean megane = true;

converter
44
public class AgeTokenConverter extends TokenConverter<Integer> {



static AgeTokenConverter converter = null;



public static AgeTokenConverter getInstance() {

if (converter == null) converter = new AgeTokenConverter();



return converter;

}



@Override

public Integer parse(JsonPullParser parser, OnJsonObjectAddListener listener)
throws IOException, JsonFormatException {

Integer value = null;

if (parser.getEventType() == JsonPullParser.State.VALUE_STRING) {

String str = parser.getValueString();

try {

value = !TextUtils.isEmpty(str) ? Integer.parseInt(str) : null;

} catch (NumberFormatException e) {

}

}



return value;

鍵の保護を検討する
鍵をどこに置く?
46
private static final String DB_PASSWORD = "pa55w0rd";
private static final byte[] KEY
= "thisismypa55w0rdthisismypa55w0rdthisismypa55w0rdthisismypa55w0rd".getBytes();
private static final byte[] KEY = "thisismypa55w0rdthisismypa55w0rd".getBytes();

Android Keystore System
47
 Android端末のセキュリティ・ハードウェア(Secure Element,
Trusted Execution Environment)内に鍵情報を格納する。
 Android 4.3から導入されていたがAndroid 6.0(Marshmallow)で
AES共通鍵に対応するなど機能が強化された。
http://developer.android.com/intl/ja/training/articles/keystore.html
Android Keystore System
48
 javax.cryptoと密接に連携している。
 任意の情報を保存できるわけではない(=Realmの暗号化キーを直
接保存できない)。
http://developer.android.com/intl/ja/training/articles/keystore.html
Android Keystore System
49
Realm暗号キー
64bytes
Android
Keystore
System
鍵情報
AES
暗号キー
64bytes
暗号化済
ユーザー認証
Storage
http://developer.android.com/intl/ja/training/articles/keystore.html
realm_with_ask.RealmActivity
50
static final String PROVIDER_NAME = "AndroidKeyStore";

static final String KEY_ALIAS = "auth_key";
private static void generateKey() {

try {

KeyGenerator keyGenerator = KeyGenerator.getInstance(

KeyProperties.KEY_ALGORITHM_AES,

PROVIDER_NAME);



keyGenerator.init(new KeyGenParameterSpec.Builder(

KEY_ALIAS,

KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)

.setBlockModes(KeyProperties.BLOCK_MODE_CBC)

.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)

.setUserAuthenticationRequired(true)

.setUserAuthenticationValidityDurationSeconds(

AUTH_VALID_DURATION_IN_SECOND)

.build());

keyGenerator.generateKey();



} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException

realm_with_ask.RealmActivity
51
void authorize() {

KeyguardManager km = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);

Intent intent = km.createConfirmDeviceCredentialIntent("Android Keystore System",

"Android Keystore Systemに保存した を使ってRealmのデータベースにアクセスします");



startActivityForResult(intent, REQUEST_CREDENTIAL);

}

realm_with_ask.RealmActivity
52
realm_with_ask.RealmActivity
53
void readyRealm() {

try {

Cipher cipher = Cipher.getInstance(TRANSFORMATION);



byte[] encryptedKey = null;



File file = new File(getFilesDir(), KEY_FILE_NAME);
// 暗号化された 情報の読み込み → encryptedKey



RealmAdapter.setKey(decryptRealmKey(encryptedKey, cipher));

realm_with_ask.RealmActivity
54
byte[] encryptRealmKey(byte[] passkey, Cipher cipher) {



try {

SecretKey key = (SecretKey) mKeyStore.getKey(KEY_ALIAS, null);

cipher.init(Cipher.ENCRYPT_MODE, key);



byte[] encrypted = cipher.doFinal(passkey);

byte[] initializationVector = cipher.getIV();



byte[] result = new byte[initializationVector.length + encrypted.length];

System.arraycopy(initializationVector, 0, result, 0, initializationVector.length);

System.arraycopy(encrypted, 0, result, initializationVector.length, encrypted.length);



return result;
Initialization Vector
16 bytes
encryption key
64 bytes
realm_with_ask.RealmActivity
55
byte[] decryptRealmKey(byte[] encrypted, Cipher cipher) {

byte[] initializationVector = new byte[16];

byte[] passKey = new byte[encrypted.length - initializationVector.length];



System.arraycopy(encrypted, 0, initializationVector, 0, initializationVector.length);

System.arraycopy(encrypted, initializationVector.length, passKey, 0, passKey.length);



try {

SecretKey key = (SecretKey) mKeyStore.getKey(KEY_ALIAS, null);



IvParameterSpec ivSpec = new IvParameterSpec(initializationVector);

cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);



return cipher.doFinal(passKey);

Fingerprint API
56
 Android 6.0(Marshmallow)で追加。
 Android Keystore Systemをパターンロック・パスワードに
加えて指紋スキャナーで認証する。
http://developer.android.com/intl/ja/about/versions/marshmallow/android-6.0.html#fingerprint-authentication
RealmFingerprintActivity
57
private final AuthenticationCallback mAuthenticationCallback
= new FingerprintManager.AuthenticationCallback() {

@Override

public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {

super.onAuthenticationSucceeded(result);

readyRealm();

}

};

RealmFingerprintActivity
58
@Override
void authorize() {

FingerprintManager fingerprintManager
= (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);



try {

SecretKey key = (SecretKey) mKeyStore.getKey(KEY_ALIAS, null);



Cipher cipher = Cipher.getInstance(TRANSFORMATION);

cipher.init(Cipher.ENCRYPT_MODE, key);



FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);



Toast.makeText(this, "指紋スキャナーに指を当てて下さい...", Toast.LENGTH_LONG)

.show();



//noinspection ResourceType

fingerprintManager.authenticate(cryptoObject, null, 0, mAuthenticationCallback, null);
RealmFingerprintActivity
59
今日の内容 - まとめ
今日の内容 - まとめ
61
 安全にデータを保管するための方法として
「javax.cryptoによるデータベースファイルの保護」
「SQLCipherを使った保護」

「Realmの暗号化機能」
 の3パターンを、それぞれ比較した。
今日の内容 - まとめ
62
 「javax.cryptoによるデータベースファイルの保護」で
は、SQLDatabaseのファイルを必要なときだけ復号し
た。
 しかし、読み書きの最中はファイルシステム上に復号し
たデータファイルが存在するため、安全とは言えなかった。
今日の内容 - まとめ
63
 「SQLCipherを使った保護」では、SQLDatabaseのファ
イルを暗号化した上で全体を復号することなく、透過的に
読み書きができた。
 しかし、Android 6.0で正常な動作が確認できなかった。
また、そのままではActiveAndroidなどORMを適用しに
くいという課題もあった。
今日の内容 - まとめ
64
 Realmを使うと、データベースを暗号で保護した状態
で、透過的に扱うことができた。
 JSONからモデルに変換する機能は、異常値が含まれる
場合などは対応しきれないケースは、JsonPullParserの
converterを使って解決した。
 
今日の内容 - まとめ
65
 「Android Keystore System」を使うことで、機密
データの復号鍵をセキュリティ・ハードウェアに保護され
た領域に保存して、安全に格納することができる。
 ただし、Realmはjavax.crypto.Cipherを直接扱えない
ため、暗号化に用いるキーをAndroid Keystore System
を用いて暗号化。キーをファイルシステムに保存した。
C-LIS CO., LTD.
各製品名・ブランド名、会社名などは、一般に各社の商標または登録商標です。本資料中では、©、®、™を割愛しています。
本資料は、有限会社シーリスの著作物です。掲載されているイラストは、特に記載がない場合は根雪れいの著作物です。
本資料の全部、または一部について、著作者から文書による許諾を得ずに複製することは禁じられています。
Material Icons are reproduced or modified from work created and shared by Google and used according to
terms described in the Creative Commons 4.0 Attribution license.
http://techbooster.github.io/c89/
Copyright TechBooster
C89 - TechBooster 3日目東シ58a
Copyright TechBooster
C89 - TechBooster 3日目東シ58a
Copyright TechBooster

Contenu connexe

Tendances

Windows Server 2019 で Container を使ってみる
Windows Server 2019 で Container を使ってみるWindows Server 2019 で Container を使ってみる
Windows Server 2019 で Container を使ってみるKazuki Takai
 
高負荷に耐えうるWebApplication Serverの作り方
高負荷に耐えうるWebApplication Serverの作り方高負荷に耐えうるWebApplication Serverの作り方
高負荷に耐えうるWebApplication Serverの作り方GMO-Z.com Vietnam Lab Center
 
Automating your mac farm for iOS build and automation
Automating your mac farm for iOS build and automationAutomating your mac farm for iOS build and automation
Automating your mac farm for iOS build and automationMikhail Advani
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugMasatoshi Tada
 
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発慎一 古賀
 
PostgreSQL 15の新機能を徹底解説
PostgreSQL 15の新機能を徹底解説PostgreSQL 15の新機能を徹底解説
PostgreSQL 15の新機能を徹底解説Masahiko Sawada
 
MySQLバックアップの基本
MySQLバックアップの基本MySQLバックアップの基本
MySQLバックアップの基本yoyamasaki
 
AIP改め、MIP_20230128_it.pdf
AIP改め、MIP_20230128_it.pdfAIP改め、MIP_20230128_it.pdf
AIP改め、MIP_20230128_it.pdftomokoitoda1
 
Burp Suite 2.0触ってみた
Burp Suite 2.0触ってみたBurp Suite 2.0触ってみた
Burp Suite 2.0触ってみたYu Iwama
 
DBパフォーマンスチューニングの基礎:インデックス入門
DBパフォーマンスチューニングの基礎:インデックス入門DBパフォーマンスチューニングの基礎:インデックス入門
DBパフォーマンスチューニングの基礎:インデックス入門Akira Shimosako
 
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)Sen Ueno
 
Git超入門_座学編.pdf
Git超入門_座学編.pdfGit超入門_座学編.pdf
Git超入門_座学編.pdf憲昭 村田
 
RETEアルゴリズムを使いこなせ
RETEアルゴリズムを使いこなせRETEアルゴリズムを使いこなせ
RETEアルゴリズムを使いこなせMasahiko Umeno
 
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)NTT DATA Technology & Innovation
 
継続使用と新規追加したRedmine Plugin
継続使用と新規追加したRedmine Plugin継続使用と新規追加したRedmine Plugin
継続使用と新規追加したRedmine PluginMei Nakamura
 
明日から使えるRxjava頻出パターン (Droid kaigi 2016)
明日から使えるRxjava頻出パターン (Droid kaigi 2016)明日から使えるRxjava頻出パターン (Droid kaigi 2016)
明日から使えるRxjava頻出パターン (Droid kaigi 2016)Kazuki Yoshida
 
徳丸本ができるまで
徳丸本ができるまで徳丸本ができるまで
徳丸本ができるまでHiroshi Tokumaru
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説do_aki
 

Tendances (20)

Windows Server 2019 で Container を使ってみる
Windows Server 2019 で Container を使ってみるWindows Server 2019 で Container を使ってみる
Windows Server 2019 で Container を使ってみる
 
高負荷に耐えうるWebApplication Serverの作り方
高負荷に耐えうるWebApplication Serverの作り方高負荷に耐えうるWebApplication Serverの作り方
高負荷に耐えうるWebApplication Serverの作り方
 
Entity Framework
Entity FrameworkEntity Framework
Entity Framework
 
Automating your mac farm for iOS build and automation
Automating your mac farm for iOS build and automationAutomating your mac farm for iOS build and automation
Automating your mac farm for iOS build and automation
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
 
PostgreSQL 15の新機能を徹底解説
PostgreSQL 15の新機能を徹底解説PostgreSQL 15の新機能を徹底解説
PostgreSQL 15の新機能を徹底解説
 
MySQLバックアップの基本
MySQLバックアップの基本MySQLバックアップの基本
MySQLバックアップの基本
 
Binary Reading in C#
Binary Reading in C#Binary Reading in C#
Binary Reading in C#
 
AIP改め、MIP_20230128_it.pdf
AIP改め、MIP_20230128_it.pdfAIP改め、MIP_20230128_it.pdf
AIP改め、MIP_20230128_it.pdf
 
Burp Suite 2.0触ってみた
Burp Suite 2.0触ってみたBurp Suite 2.0触ってみた
Burp Suite 2.0触ってみた
 
DBパフォーマンスチューニングの基礎:インデックス入門
DBパフォーマンスチューニングの基礎:インデックス入門DBパフォーマンスチューニングの基礎:インデックス入門
DBパフォーマンスチューニングの基礎:インデックス入門
 
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
 
Git超入門_座学編.pdf
Git超入門_座学編.pdfGit超入門_座学編.pdf
Git超入門_座学編.pdf
 
RETEアルゴリズムを使いこなせ
RETEアルゴリズムを使いこなせRETEアルゴリズムを使いこなせ
RETEアルゴリズムを使いこなせ
 
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
 
継続使用と新規追加したRedmine Plugin
継続使用と新規追加したRedmine Plugin継続使用と新規追加したRedmine Plugin
継続使用と新規追加したRedmine Plugin
 
明日から使えるRxjava頻出パターン (Droid kaigi 2016)
明日から使えるRxjava頻出パターン (Droid kaigi 2016)明日から使えるRxjava頻出パターン (Droid kaigi 2016)
明日から使えるRxjava頻出パターン (Droid kaigi 2016)
 
徳丸本ができるまで
徳丸本ができるまで徳丸本ができるまで
徳丸本ができるまで
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説
 

Similaire à Realmの暗号化とAndroid System

Android Studioの魅力
Android Studioの魅力Android Studioの魅力
Android Studioの魅力Keiji Ariyama
 
Java/Androidセキュアコーディング
Java/AndroidセキュアコーディングJava/Androidセキュアコーディング
Java/AndroidセキュアコーディングMasaki Kubo
 
Appsody でnodejsのアプリを立ち上げよう!
Appsody でnodejsのアプリを立ち上げよう!Appsody でnodejsのアプリを立ち上げよう!
Appsody でnodejsのアプリを立ち上げよう!Daisuke Hiraoka
 
SEAndroid -AndroidのアーキテクチャとSE化について-
SEAndroid -AndroidのアーキテクチャとSE化について-SEAndroid -AndroidのアーキテクチャとSE化について-
SEAndroid -AndroidのアーキテクチャとSE化について-Hiromu Yakura
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platformToru Yamaguchi
 
ScalaでAndroidアプリ開発
ScalaでAndroidアプリ開発ScalaでAndroidアプリ開発
ScalaでAndroidアプリ開発papamitra
 
Google I/O 2013 報告会 Android Studio と Gradle
Google I/O 2013 報告会 Android Studio と GradleGoogle I/O 2013 報告会 Android Studio と Gradle
Google I/O 2013 報告会 Android Studio と GradleKeishin Yokomaku
 
初めてのPadrino
初めてのPadrino初めてのPadrino
初めてのPadrinoTakeshi Yabe
 
Play2 scalaを2年やって学んだこと
Play2 scalaを2年やって学んだことPlay2 scalaを2年やって学んだこと
Play2 scalaを2年やって学んだことdcubeio
 
Djangoフレームワークの紹介
Djangoフレームワークの紹介Djangoフレームワークの紹介
Djangoフレームワークの紹介Shinya Okano
 
.NET最先端技術によるハイパフォーマンスウェブアプリケーション
.NET最先端技術によるハイパフォーマンスウェブアプリケーション.NET最先端技術によるハイパフォーマンスウェブアプリケーション
.NET最先端技術によるハイパフォーマンスウェブアプリケーションYoshifumi Kawai
 
初めての Data api cms どうでしょう - 大阪夏の陣
初めての Data api   cms どうでしょう - 大阪夏の陣初めての Data api   cms どうでしょう - 大阪夏の陣
初めての Data api cms どうでしょう - 大阪夏の陣Yuji Takayama
 
Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.Yuki Higuchi
 
Next2Dで始めるゲーム開発 - Game Development Starting with Next2D
Next2Dで始めるゲーム開発  - Game Development Starting with Next2DNext2Dで始めるゲーム開発  - Game Development Starting with Next2D
Next2Dで始めるゲーム開発 - Game Development Starting with Next2DToshiyuki Ienaga
 
復習も兼ねて!C#6.0-7.0
復習も兼ねて!C#6.0-7.0復習も兼ねて!C#6.0-7.0
復習も兼ねて!C#6.0-7.0Yuta Matsumura
 
laravel x モバイルアプリ
laravel x モバイルアプリlaravel x モバイルアプリ
laravel x モバイルアプリMasaki Oshikawa
 
冬だからAndroid再入門
冬だからAndroid再入門冬だからAndroid再入門
冬だからAndroid再入門Katsumi Honda
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回Naoyuki Yamada
 

Similaire à Realmの暗号化とAndroid System (20)

Android Studioの魅力
Android Studioの魅力Android Studioの魅力
Android Studioの魅力
 
Java/Androidセキュアコーディング
Java/AndroidセキュアコーディングJava/Androidセキュアコーディング
Java/Androidセキュアコーディング
 
Appsody でnodejsのアプリを立ち上げよう!
Appsody でnodejsのアプリを立ち上げよう!Appsody でnodejsのアプリを立ち上げよう!
Appsody でnodejsのアプリを立ち上げよう!
 
SEAndroid -AndroidのアーキテクチャとSE化について-
SEAndroid -AndroidのアーキテクチャとSE化について-SEAndroid -AndroidのアーキテクチャとSE化について-
SEAndroid -AndroidのアーキテクチャとSE化について-
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
ScalaでAndroidアプリ開発
ScalaでAndroidアプリ開発ScalaでAndroidアプリ開発
ScalaでAndroidアプリ開発
 
Google I/O 2013 報告会 Android Studio と Gradle
Google I/O 2013 報告会 Android Studio と GradleGoogle I/O 2013 報告会 Android Studio と Gradle
Google I/O 2013 報告会 Android Studio と Gradle
 
初めてのPadrino
初めてのPadrino初めてのPadrino
初めてのPadrino
 
Play2 scalaを2年やって学んだこと
Play2 scalaを2年やって学んだことPlay2 scalaを2年やって学んだこと
Play2 scalaを2年やって学んだこと
 
Djangoフレームワークの紹介
Djangoフレームワークの紹介Djangoフレームワークの紹介
Djangoフレームワークの紹介
 
.NET最先端技術によるハイパフォーマンスウェブアプリケーション
.NET最先端技術によるハイパフォーマンスウェブアプリケーション.NET最先端技術によるハイパフォーマンスウェブアプリケーション
.NET最先端技術によるハイパフォーマンスウェブアプリケーション
 
ScalaMatsuri 2016
ScalaMatsuri 2016ScalaMatsuri 2016
ScalaMatsuri 2016
 
AndroidでDIxAOP
AndroidでDIxAOPAndroidでDIxAOP
AndroidでDIxAOP
 
初めての Data api cms どうでしょう - 大阪夏の陣
初めての Data api   cms どうでしょう - 大阪夏の陣初めての Data api   cms どうでしょう - 大阪夏の陣
初めての Data api cms どうでしょう - 大阪夏の陣
 
Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.
 
Next2Dで始めるゲーム開発 - Game Development Starting with Next2D
Next2Dで始めるゲーム開発  - Game Development Starting with Next2DNext2Dで始めるゲーム開発  - Game Development Starting with Next2D
Next2Dで始めるゲーム開発 - Game Development Starting with Next2D
 
復習も兼ねて!C#6.0-7.0
復習も兼ねて!C#6.0-7.0復習も兼ねて!C#6.0-7.0
復習も兼ねて!C#6.0-7.0
 
laravel x モバイルアプリ
laravel x モバイルアプリlaravel x モバイルアプリ
laravel x モバイルアプリ
 
冬だからAndroid再入門
冬だからAndroid再入門冬だからAndroid再入門
冬だからAndroid再入門
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
 

Plus de Keiji Ariyama

Vuzix Developer Conference
Vuzix Developer ConferenceVuzix Developer Conference
Vuzix Developer ConferenceKeiji Ariyama
 
Android Studio開発講座
Android Studio開発講座Android Studio開発講座
Android Studio開発講座Keiji Ariyama
 
2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa
2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa
2015年のAndroidアプリ開発入門 - ABCD 2015 KanazawaKeiji Ariyama
 
Vuzix developer conference - M100アプリ開発
Vuzix developer conference - M100アプリ開発Vuzix developer conference - M100アプリ開発
Vuzix developer conference - M100アプリ開発Keiji Ariyama
 
Google Glassアプリ開発と自由度の変遷
Google Glassアプリ開発と自由度の変遷Google Glassアプリ開発と自由度の変遷
Google Glassアプリ開発と自由度の変遷Keiji Ariyama
 
Google Cloud Endpointsによる API構築
Google Cloud Endpointsによる API構築Google Cloud Endpointsによる API構築
Google Cloud Endpointsによる API構築Keiji Ariyama
 
Google Mirror API勉強会 20130607
Google Mirror API勉強会 20130607Google Mirror API勉強会 20130607
Google Mirror API勉強会 20130607Keiji Ariyama
 
これからの"日付変更線"の話をしよう
これからの"日付変更線"の話をしようこれからの"日付変更線"の話をしよう
これからの"日付変更線"の話をしようKeiji Ariyama
 
20130119 adkハンズオン発表資料
20130119 adkハンズオン発表資料20130119 adkハンズオン発表資料
20130119 adkハンズオン発表資料Keiji Ariyama
 

Plus de Keiji Ariyama (9)

Vuzix Developer Conference
Vuzix Developer ConferenceVuzix Developer Conference
Vuzix Developer Conference
 
Android Studio開発講座
Android Studio開発講座Android Studio開発講座
Android Studio開発講座
 
2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa
2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa
2015年のAndroidアプリ開発入門 - ABCD 2015 Kanazawa
 
Vuzix developer conference - M100アプリ開発
Vuzix developer conference - M100アプリ開発Vuzix developer conference - M100アプリ開発
Vuzix developer conference - M100アプリ開発
 
Google Glassアプリ開発と自由度の変遷
Google Glassアプリ開発と自由度の変遷Google Glassアプリ開発と自由度の変遷
Google Glassアプリ開発と自由度の変遷
 
Google Cloud Endpointsによる API構築
Google Cloud Endpointsによる API構築Google Cloud Endpointsによる API構築
Google Cloud Endpointsによる API構築
 
Google Mirror API勉強会 20130607
Google Mirror API勉強会 20130607Google Mirror API勉強会 20130607
Google Mirror API勉強会 20130607
 
これからの"日付変更線"の話をしよう
これからの"日付変更線"の話をしようこれからの"日付変更線"の話をしよう
これからの"日付変更線"の話をしよう
 
20130119 adkハンズオン発表資料
20130119 adkハンズオン発表資料20130119 adkハンズオン発表資料
20130119 adkハンズオン発表資料
 

Realmの暗号化とAndroid System