#最初に...
初投稿です。
普段アプリ開発をする際に、IDなどをアプリ内に保存した際、いつも平文でした。
アプリ内に保存はしていますが、念のため暗号化しようと思い
AES暗号鍵を使用して値を暗号化して保存してみましたので、それについての記事となります。
まず、AES採用の理由とAndroidにおける鍵の保存領域について。
##AES(Advanced Encryption Standard)
AESにした理由は、CRYPTRECにて共通鍵暗号にて推奨されているためです。
(参考:http://www.cryptrec.go.jp/list/cryptrec-ls-0001-2016.pdf)
また、RSAにしない理由としては鍵の使用者が一人しかいないので
非対称鍵にする必要がないと思いました。
##AndroidKeyStoreSystem?
AndroidOSが提供している鍵をセキュアに保存できる領域です。
(APKで使うKeyStoreじゃないです。)
ちなみに指紋認証付き端末ですと、鍵を使用する際に指紋認証をすることを
条件にすることもでき更にセキュアになります。
(Androidの指紋認証付き端末のシェア率を考慮すると、微妙なので
採用は見送りました)
##実際のソース
AES鍵作成
public void createAESKey() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES,"AndroidKeyStore");
keyGenerator.init(new KeyGenParameterSpec.Builder(ALIAS,KeyProperties.PURPOSE_ENCRYPT|KeyProperties.PURPOSE_DECRYPT)//この鍵は、暗号化・復号を目的として作成しますということを明示してます
.setCertificateSubject(new X500Principal("CN="+ALIAS))
.setCertificateSerialNumber(BigInteger.ONE)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)//CBC=「Cipher Block Chaining mode」
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setRandomizedEncryptionRequired(false)//初期化ベクトルを固定値とする設定をしています。
.build());
keyGenerator.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
}
暗号化
public String encrypt(String text) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
if (!keyStore.containsAlias(ALIAS)) {
createAESKey();
}
SecretKey secretKey = (SecretKey)keyStore.getKey(ALIAS,null);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(IVKEY.getBytes());
cipher.init(Cipher.ENCRYPT_MODE,secretKey,ivParameterSpec);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream,cipher);
cipherOutputStream.write(text.getBytes("UTF-8"));
cipherOutputStream.close();
return Base64.encodeToString(outputStream.toByteArray(),Base64.NO_WRAP);
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
復号
public String decrypt(String encryptText) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey)keyStore.getKey(ALIAS,null);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(IVKEY.getBytes());
cipher.init(Cipher.DECRYPT_MODE,secretKey,ivParameterSpec);
CipherInputStream cipherInputStream = new CipherInputStream(new ByteArrayInputStream(Base64.decode(encryptText,Base64.NO_WRAP)),cipher);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int buffer;
while ((buffer = cipherInputStream.read())!= -1) {
byteArrayOutputStream.write(buffer);
}
byteArrayOutputStream.close();
return byteArrayOutputStream.toString("UTF-8");
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
呼び出し
KeyService keyService = new KeyService();
keyService.createAESKey();
String text = "5000兆円欲しい";
String encryptText = keyService.encrypt(text);
String text2 = keyService.decrypt(encryptText);
Log.d("","text="+text);
Log.d("","encryptText="+encryptText);
Log.d("","text2="+text2);
結果
text=5000兆円欲しい
encryptText=ooIvV63AJIyyRhZUpUJ2Le4B2DyWUw1ZmSG33Z2IhQM=
text2=5000兆円欲しい
##最後に
ご覧いただき、ありがとうございます。
次回はSwift4で同じことをする予定です・・・。