Created
August 22, 2017 01:08
-
-
Save yatatsu/32181e14ea440275cd84698fae44eb85 to your computer and use it in GitHub Desktop.
aes on android java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.github.yatatsu.android.util; | |
import android.util.Base64; | |
import java.io.UnsupportedEncodingException; | |
import java.security.InvalidAlgorithmParameterException; | |
import java.security.InvalidKeyException; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.SecureRandom; | |
import java.security.spec.InvalidKeySpecException; | |
import java.security.spec.KeySpec; | |
import java.util.Locale; | |
import javax.crypto.BadPaddingException; | |
import javax.crypto.Cipher; | |
import javax.crypto.IllegalBlockSizeException; | |
import javax.crypto.NoSuchPaddingException; | |
import javax.crypto.SecretKey; | |
import javax.crypto.SecretKeyFactory; | |
import javax.crypto.spec.IvParameterSpec; | |
import javax.crypto.spec.PBEKeySpec; | |
import javax.crypto.spec.SecretKeySpec; | |
/** | |
* | |
* cf. https://nelenkov.blogspot.jp/2012/04/using-password-based-encryption-on.html | |
*/ | |
public final class Ciphers { | |
private static final int ITERATION_COUNT = 1000; | |
private static final int KEY_LENGTH = 256; // 256bits for AES256 | |
private static final int SALT_LENGTH = KEY_LENGTH / 8; // 32bytes. 導出するキーと同じサイズが良い. | |
private static final String DELIMITER = "]"; | |
/** | |
* 入力からAES暗号化文字列を作ります。 | |
* | |
* @param plainText text | |
* @param secret passphrase | |
* @return [0] = salt, [1] = "iv]ciphertext" | |
* @throws NoSuchAlgorithmException | |
* @throws InvalidKeySpecException | |
* @throws NoSuchPaddingException | |
* @throws InvalidAlgorithmParameterException | |
* @throws InvalidKeyException | |
* @throws UnsupportedEncodingException | |
* @throws BadPaddingException | |
* @throws IllegalBlockSizeException | |
*/ | |
public static String[] encrypt(String plainText, String secret) | |
throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, | |
InvalidAlgorithmParameterException, InvalidKeyException, UnsupportedEncodingException, | |
BadPaddingException, IllegalBlockSizeException { | |
SecureRandom random = new SecureRandom(); | |
byte[] salt = new byte[SALT_LENGTH]; | |
random.nextBytes(salt); | |
// キー | |
SecretKey key = deriveKeyFromPassword(salt, secret); | |
// キーを元に暗号化する | |
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
byte[] iv = new byte[cipher.getBlockSize()]; | |
random.nextBytes(iv); | |
IvParameterSpec ivParams = new IvParameterSpec(iv); | |
cipher.init(Cipher.ENCRYPT_MODE, key, ivParams); | |
byte[] cipherText = cipher.doFinal(plainText.getBytes("UTF-8")); | |
// `{iv}]{cipher}` | |
return new String[]{toBase64(salt), | |
String.format(Locale.US, "%s%s%s", toBase64(iv), DELIMITER, toBase64(cipherText))}; | |
} | |
public static String decrypt(String cipherText, String salt, String secret) | |
throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, | |
NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException, | |
BadPaddingException, IllegalBlockSizeException { | |
String[] fields = cipherText.split(DELIMITER); | |
if (fields.length != 2) { | |
throw new IllegalArgumentException("Invalid encrypted text format"); | |
} | |
byte[] iv = fromBase64(fields[0]); | |
byte[] cipherBytes = fromBase64(fields[1]); | |
// キー | |
SecretKey key = deriveKeyFromPassword(fromBase64(salt), secret); | |
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
IvParameterSpec ivParams = new IvParameterSpec(iv); | |
cipher.init(Cipher.DECRYPT_MODE, key, ivParams); | |
byte[] plaintext = cipher.doFinal(cipherBytes); | |
return new String(plaintext, "UTF-8"); | |
} | |
private static SecretKey deriveKeyFromPassword(byte[] salt, String password) | |
throws NoSuchAlgorithmException, InvalidKeySpecException { | |
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, | |
ITERATION_COUNT, KEY_LENGTH); | |
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); | |
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); | |
return new SecretKeySpec(keyBytes, "AES"); | |
} | |
private static String toBase64(byte[] bytes) { | |
return Base64.encodeToString(bytes, Base64.NO_WRAP|Base64.NO_PADDING); | |
} | |
private static byte[] fromBase64(String base64) { | |
return Base64.decode(base64, Base64.NO_WRAP|Base64.NO_PADDING); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment