Published on

平文のパスワードとソルトから安全なパスワードを作成する

Authors
  • avatar
    Name
    Kikusan
    Twitter
    package password;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.security.spec.InvalidKeySpecException;
    
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.PBEKeySpec;
    
    public class EncryptionPlayGround {
    
        public static void main(String[] args) {
            String securePass1 = getSecurePassword("password", "userid01");
            String securePass2 = getSecurePassword("password", "userid01");
            String securePass3 = getSecurePassword("password", "userid02");
            String securePass4 = getSecurePassword("p@ssword", "userid02");
            System.out.println(securePass1);
            System.out.println(securePass2);
            System.out.println(securePass3);
            System.out.println(securePass4);
        }
    
        /** パスワードを安全にするためのアルゴリズム */
        private static final String ALGORITHM = "PBKDF2WithHmacSHA256";
        /** ストレッチング回数 */
        private static final int STRETCHING_COUNT = 10000;
        /** 生成される鍵の長さ */
        private static final int KEY_LENGTH = 256;
    
        /**
         * 平文のパスワードとソルトから安全なパスワードを生成し、返却する
         *
         * @param String:password 平文のパスワード
         * @param String:salt ソルト(userid)
         * @return String:securePassword
         */
        public static String getSecurePassword(String password, String salt) {
    
            char[] passCharAry = password.toCharArray();
            // ソルト値のハッシュ化
            byte[] hashedSalt = getHashedSalt(salt);
            // パスワード,ソルト値, ストレッチ回数, 鍵の長さを指定したキー仕様を設定
            PBEKeySpec keySpec = new PBEKeySpec(passCharAry, hashedSalt, STRETCHING_COUNT, KEY_LENGTH);
    
            SecretKeyFactory skf;
            try {
                //暗号化・復号オブジェクト
                skf = SecretKeyFactory.getInstance(ALGORITHM);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }
    
            SecretKey secretKey;
            try {
                // 安全なパスワード生成
                secretKey = skf.generateSecret(keySpec);
            } catch (InvalidKeySpecException e) {
                throw new RuntimeException(e);
            }
            byte[] passByteAry = secretKey.getEncoded();
    
            // 生成されたバイト配列を16進数の文字列に変換
            StringBuilder sb = new StringBuilder(64);
            for (byte b : passByteAry) {
                sb.append(String.format("%02x", b & 0xff));
            }
            return sb.toString();
        }
    
        /**
         * ソルトをハッシュ化して返却する
         * ※ハッシュアルゴリズムはSHA-256を使用
         *
         * @param String:salt ソルト
         * @return byte[]:hashedSalt
         */
        private static byte[] getHashedSalt(String salt) {
            MessageDigest md;
            try {
                md = MessageDigest.getInstance("SHA-256");
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }
            md.update(salt.getBytes());
            return md.digest();
        }
    }