はじめに
スマートフォンのアプリで暗号キーなどの重要情報を安全に保存するニーズは高いですね。
それは、アプリで普通に保存してしまうと、他のアプリや攻撃者に重要情報を取得される危険性があるからです。
この危険性を防ぐために、iOS では KeyChain、Android では KeyStore という、重要情報を安全に保存する仕組みがあります。
この KeyChain と KeyStore に、 React Native から重要情報を保存する方法をご紹介します。
使用するライブラリ
iOS では KeyChain、Android では KeyStore に暗号キーなどの重要情報を保存するために、 rn-secure-storageというライブラリを使用します。rn-secure-storage
は任意のキーを任意の数だけ保存できるため使い勝手がよいものになっています。
ちなみに、react-native-keychainというライブラリは、ユーザーIDとパスワードの固定の組み合わせを一組しか保存できません。react-native-keychain
の使用方法については、以下の記事を参考にしてください。
なお、rn-secure-storage
は、iOS ではバージョンに関係なく KeyChain に保存するので問題はありません。
ですが、Android では API のバージョンが 23 (Android 6.0)以下だと KeyStore ではなくsecure-preferencesというライブラリを使用するので注意が必要です。API のバージョンが 24(Android 7.0)以降では KeyStore を使用するので安全です。
また、ログに OS 情報を出力するために、react-native-device-infoというライブラリも使用します。
プロジェクトの作成
React Native のプロジェクトを作成します。今回は TypeScript を使用するので、以下のようにコマンドを実行します。
$ npx react-native init KeySecure --template react-native-template-typescript
インストール
下記コマンドを実行して、必要なライブラリをインストールします。
$ yarn add rn-secure-storage $ yarn add react-native-device-info $ cd ios && pod install && cd ..
App.tsx の編集
App.tsxを以下のように編集します。
内容は見てのとおりですが、key と value の組み合わせを保存、取得、存在チェック、削除しています。なお、保存時に存在している key で保存すると上書きされます。
import React, {useEffect} from 'react'; import {SafeAreaView, Text} from 'react-native'; import DeviceInfo from 'react-native-device-info'; import RNSecureStorage, {ACCESSIBLE} from 'rn-secure-storage'; const App = () => { useEffect(() => { const storeKeys = async () => { // Retrieve the systemname const systemName = DeviceInfo.getSystemName(); console.log(systemName); // Set key/value console.log('Set key/value.'); try { // {accessible: ACCESSIBLE.WHEN_UNLOCKED} -> This for IOS const res1 = await RNSecureStorage.set('key1', 'This is value 1.', { accessible: ACCESSIBLE.WHEN_UNLOCKED, }); console.log('key1:' + res1); const res2 = await RNSecureStorage.set('key2', 'This is value 2.', { accessible: ACCESSIBLE.WHEN_UNLOCKED, }); console.log('key2:' + res2); } catch (error) { console.log(error); } // Get key/value console.log('Get key/value.'); try { const value1 = await RNSecureStorage.get('key1'); console.log('key1=' + value1); const value2 = await RNSecureStorage.get('key2'); console.log('key2=' + value2); } catch (error) { console.log(error); } // Exists check console.log('Exists check.'); try { // res -> is can be True or False const res1 = await RNSecureStorage.exists('key1'); console.log(res1 ? 'key1:exists' : 'key1:not exists'); const res2 = await RNSecureStorage.exists('key2'); console.log(res2 ? 'key2:exists' : 'key2:not exists'); // Nothing const res3 = await RNSecureStorage.exists('key3'); console.log(res3 ? 'key3:exists' : 'key3:not exists'); } catch (error) { console.log(error); } // Remove key/value console.log('Remove key/value.'); try { const res1 = await RNSecureStorage.remove('key1'); console.log('key1:' + res1); const res2 = await RNSecureStorage.remove('key2'); console.log('key2:' + res2); } catch (error) { console.log(error); } }; storeKeys(); }, []); return ( <> <SafeAreaView> <Text>Hello</Text> </SafeAreaView> </> ); }; export default App;
実行
iOS で動作させるために、下記コマンドを実行します。
$ react-native run-ios
ログが正しく出力されることが分かります。
なお、iOS でログが出力されない場合は、下記記事を参考にしてください。
Android で動作させるために、下記コマンドを実行します。
$ react-native run-android
こちらも、ログが正しく出力されることが分かります。
おわりに
React Native で暗号キーなどの重要情報に安全な場所に保存する方法を見てきました。
日本語情報は相変わらずないですが、ライブラリを使用すれば比較的簡単に KeyChain や KeyStore に保存できることが分かったかと思います。