// ========================================================================
// Copyright (C) zeroth Project Team. All rights reserved.
// GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007
// http://www.gnu.org/licenses/agpl-3.0.txt
// ========================================================================
package zeroth.framework.standard.shared;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
* セキュリティユーティリティ
* <dl>
* <dt>事前条件</dt>
* <dd>AES256bit鍵を利用するには、JCE管轄ポリシーファイル(無制限強度)をダウンロードして、
* %JAVA_HOME%/jre/lib/securityへUS_export_policy.jarとlocal_policy.jar上書きすること。</dd>
* </dl>
* @author nilcy
*/
public class SecurityUtils {
/** 暗号方式名 */
private static final String ALGO_NAME = "AES";
/** 乱数生成名 */
private static final String RAND_NAME = "SHA1PRNG";
/** 鍵長(標準128,JCE無制限ポリシー適用256) TODO 256bit鍵 */
private static final int KEY_LENGTH = 128;
/** 非公開コンストラクタ */
private SecurityUtils() {
}
/**
* 共通鍵の作成
* <ul>
* <li>AES256bit鍵を作成します。</li>
* <li>SHA1PRNGで乱数生成したのち、URL安全なBASE64文字列に変換します。</li>
* </ul>
* @return 共通鍵(URL安全なBASE64文字列)
*/
public static String createKey() {
try {
final KeyGenerator generator = KeyGenerator.getInstance(ALGO_NAME);
generator.init(KEY_LENGTH, SecureRandom.getInstance(RAND_NAME));
return Base64.encodeBase64URLSafeString(generator.generateKey().getEncoded());
} catch (final NoSuchAlgorithmException e) {
throw new IllegalArgumentException(e);
}
}
/**
* 暗号
* @param plainBytes 平文バイト列
* @param base64Key 共通鍵
* @return 暗号バイト列
*/
public static byte[] encrypt(final byte[] plainBytes, final String base64Key) {
return exec(plainBytes, base64Key, Cipher.ENCRYPT_MODE);
}
/**
* 復号
* @param encryptedBytes 暗号バイト列
* @param base64Key 共通鍵
* @return 平文バイト列
*/
public static byte[] decrypt(final byte[] encryptedBytes, final String base64Key) {
return exec(encryptedBytes, base64Key, Cipher.DECRYPT_MODE);
}
/**
* 暗号/復号実行
* @param encryptedBytes 入力バイト列(平文/暗号)
* @param base64Key 共通鍵
* @param cipherMode 暗号/復号モード
* @return 出力バイト列(暗号/平文)
*/
private static byte[] exec(final byte[] encryptedBytes, final String base64Key,
final int cipherMode) {
try {
final Cipher cipher = Cipher.getInstance(ALGO_NAME);
cipher.init(cipherMode, new SecretKeySpec(Base64.decodeBase64(base64Key), ALGO_NAME));
return cipher.doFinal(encryptedBytes);
} catch (final InvalidKeyException e) {
e.printStackTrace();
throw new StandardRuntimeException(e);
} catch (final NoSuchAlgorithmException e) {
throw new StandardRuntimeException(e);
} catch (final NoSuchPaddingException e) {
throw new StandardRuntimeException(e);
} catch (final IllegalBlockSizeException e) {
throw new StandardRuntimeException(e);
} catch (final BadPaddingException e) {
throw new StandardRuntimeException(e);
}
}
}