Last active
December 19, 2015 02:49
-
-
Save monzou/5886251 to your computer and use it in GitHub Desktop.
Security Utilities
This file contains hidden or 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
public final class AESProtector { | |
private static final Configuration CONFIGURATION; | |
static { | |
try { | |
CONFIGURATION = ConfigurationLoader.load(Configuration.class, "aes-security-policy.yml", "default-aes-security-policy.yml"); | |
} catch (IOException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private static final String CHARSET = "UTF-8"; | |
private static final String ALGORITHM = "AES"; | |
/** | |
* 文字列を暗号化します。 | |
* | |
* @param value 文字列 | |
* @param salt ソルト | |
* @return 暗号化された文字列 | |
*/ | |
public static String encrypt(String value, String salt) { | |
checkNotNull(value); | |
checkNotNull(salt); | |
try { | |
SecretKey key = generateKey(); | |
Cipher cipher = Cipher.getInstance(ALGORITHM); | |
cipher.init(Cipher.ENCRYPT_MODE, key); | |
String valueToEncrypt = null; | |
String encryptedValue = value; | |
for (int i = 0; i < CONFIGURATION.iterationCount; i++) { | |
valueToEncrypt = salt + encryptedValue; | |
encryptedValue = new BASE64Encoder().encode(cipher.doFinal(valueToEncrypt.getBytes(CHARSET))); | |
} | |
return encryptedValue; | |
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | |
| UnsupportedEncodingException e) { | |
throw new |RuntimeException(e); | |
} | |
} | |
/** | |
* 文字列を復号化します。 | |
* | |
* @param encryptedValue 暗号化された文字列 | |
* @param salt ソルト | |
* @return 復号化された文字列 | |
*/ | |
public static String decrypt(String encryptedValue, String salt) { | |
checkNotNull(encryptedValue); | |
checkNotNull(salt); | |
SecretKey key = generateKey(); | |
Cipher cipher; | |
try { | |
cipher = Cipher.getInstance(ALGORITHM); | |
cipher.init(Cipher.DECRYPT_MODE, key); | |
String decryptedValue = encryptedValue; | |
for (int i = 0; i < CONFIGURATION.iterationCount; i++) { | |
decryptedValue = new String(cipher.doFinal(new BASE64Decoder().decodeBuffer(decryptedValue)), CHARSET); | |
decryptedValue = decryptedValue.substring(salt.length()); | |
} | |
return decryptedValue; | |
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IOException | IllegalBlockSizeException | |
| BadPaddingException e) { | |
throw new |RuntimeException(e); | |
} | |
} | |
private static SecretKey generateKey() { | |
try { | |
return new SecretKeySpec(CONFIGURATION.secret.getBytes(CHARSET), ALGORITHM); | |
} catch (UnsupportedEncodingException e) { | |
throw new |RuntimeException(e); | |
} | |
} | |
private static class Configuration { | |
public String secret; | |
public int iterationCount; | |
} | |
private AESProtector() { | |
} | |
} |
This file contains hidden or 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
public final class Bytes2 { | |
/** | |
* 16 進に変換します。 | |
* | |
* @param data データ | |
* @return 変換された文字列 | |
*/ | |
public static String toHex(byte[] data) { | |
StringBuilder sb = new StringBuilder(); | |
for (byte b : data) { | |
sb.append(toHex(b)); | |
} | |
return sb.toString(); | |
} | |
/** | |
* 16 進に変換します。 | |
* | |
* @param b データ | |
* @return 変換された文字 | |
*/ | |
public static String toHex(byte b) { | |
String s = Integer.toHexString(0xff & b); | |
if (s.length() == 1) { | |
s = "0" + s; | |
} | |
return s; | |
} | |
private Bytes2() { | |
} | |
} |
This file contains hidden or 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
public final class Hasher { | |
/** | |
* SHA-256 によりハッシュ化します。 | |
* | |
* @param value ハッシュ化する値 | |
* @return ハッシュ化された値 | |
*/ | |
public static String hash(String value) { | |
try { | |
MessageDigest md = MessageDigest.getInstance("SHA-256"); | |
md.update(checkNotNull(value).getBytes()); | |
return Bytes2.toHex(md.digest()); | |
} catch (NoSuchAlgorithmException e) { | |
throw new |RuntimeException(e); | |
} | |
} | |
private Hasher() { | |
} | |
} |
This file contains hidden or 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
public final class Passwords { | |
private static final Configuration CONFIGURATION; | |
static { | |
try { | |
CONFIGURATION = ConfigurationLoader.load(Configuration.class, "password-policy.yml", "default-password-policy.yml"); | |
} catch (IOException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private static final char[] ALPHABET_CHARS = "abcdefghijklmnopqrstuvwxyz".toCharArray(); | |
private static final char[] NUMBER_CHARS = "0123456789".toCharArray(); | |
private static final int RANDOM_PASSWORD_CHAR_LENGTH = 8; | |
/** | |
* パスワードをハッシュ化します。 | |
* <p> | |
* ユーザーコードと固定のソルトをハッシュしてソルトにした後, ストレッチングします。 | |
* | |
* @param userCode ユーザーコード | |
* @param password パスワード | |
* @return ハッシュ化されたパスワード | |
*/ | |
public static String hash(String userCode, String password) { | |
checkNotNull(userCode); | |
checkNotNull(password); | |
String salt = Hasher.hash(CONFIGURATION.salt + userCode); | |
String hashed = null; | |
for (int i = 0; i < CONFIGURATION.stretchCount; i++) { | |
hashed = Hasher.hash(hashed + salt + password); | |
} | |
return hashed; | |
} | |
/** | |
* ランダムパスワードを生成します。 | |
* | |
* @return パスワード | |
*/ | |
public static String generateRandomPassword() { | |
return generateRandomPassword(RANDOM_PASSWORD_CHAR_LENGTH); | |
} | |
/** | |
* ランダムパスワードを生成します。 | |
* | |
* @param passwordCharLength パスワードの文字数 | |
* @return パスワード | |
*/ | |
public static String generateRandomPassword(int passwordCharLength) { | |
char[] password = new char[passwordCharLength]; | |
for (int i = 0; i < passwordCharLength; i++) { | |
double d = Math.random(); | |
if (i < 2) { | |
// 最初の2文字はアルファベット | |
int index = (int) (d * ALPHABET_CHARS.length) % ALPHABET_CHARS.length; | |
password[i] = ALPHABET_CHARS[index]; | |
} else { | |
// 2文字目以降は数字 | |
int index = (int) (d * NUMBER_CHARS.length) % NUMBER_CHARS.length; | |
password[i] = NUMBER_CHARS[index]; | |
} | |
} | |
return new String(password); | |
} | |
private static class Configuration { | |
public String salt; | |
public int stretchCount; | |
} | |
private Passwords() { | |
} | |
} |
This file contains hidden or 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
public final class RandomSaltGenerator { | |
private static final int DEFAULT_LENGTH = 8; | |
/** | |
* ランダムなソルトを生成します。 | |
* | |
* @return ソルト | |
*/ | |
public static String generate() { | |
return generate(DEFAULT_LENGTH); | |
} | |
/** | |
* ランダムなソルトを生成します。 | |
* | |
* @param length ソルトの長さ | |
* @return ソルト | |
*/ | |
public static String generate(int length) { | |
byte[] salt = new byte[length]; | |
SecureRandom sr; | |
try { | |
sr = SecureRandom.getInstance("SHA1PRNG"); | |
sr.nextBytes(salt); | |
return Bytes2.toHex(salt); | |
} catch (NoSuchAlgorithmException e) { | |
throw new |RuntimeException(e); | |
} | |
} | |
private RandomSaltGenerator() { | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment