Skip to content

Instantly share code, notes, and snippets.

@yatatsu
Created August 22, 2017 01:08
Show Gist options
  • Save yatatsu/32181e14ea440275cd84698fae44eb85 to your computer and use it in GitHub Desktop.
Save yatatsu/32181e14ea440275cd84698fae44eb85 to your computer and use it in GitHub Desktop.
aes on android java
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