概要
Spring bootを例にユーザー認証時のパスワードの暗号化(ハッシュ化)についての扱いを紹介します。
依存関係
pom.xmlに下記の依存関係を追加します。
pom.xml
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId></dependency>
<dependency>
ハッシュ化アルゴリズム
PasswordEncoderインターフェースの実装クラスが6つあります。
PasswordEncoderの実装クラス | 概要 |
---|---|
AbstractPasswordEncoder | - |
NoOpPasswordEncoder | ハッシュ化を行わないエンコーダ(テストなどで使用) |
Pbkdf2PasswordEncoder | 設定可能な反復回数とランダムな8バイトランダムソルト値を使用してPBKDF2を使用するPasswordEncoderの実装 |
StandardPasswordEncoder | SHA-256アルゴリズム + 1024回のストレッチでハッシュ化を行うエンコーダ |
BCryptPasswordEncoder | bcryptアルゴリズムでハッシュ化を行うエンコーダ |
SCryptPasswordEncoder | scryptアルゴリズムでハッシュ化を行うエンコーダ |
###bcryptとは
認証で使用するパスワードを安全にハッシュ化するアルゴリズムです。
bcryptは60文字のハッシュ値を生成します。
また、このハッシュ値の中には下記4つの情報が含まれています。
- bcryptのバージョン
- ストレッチング回数(ハッシュ化の回数で、2のn乗のnのことで4~31を指定できる)
- ソルト値
- ハッシュ値
下記ハッシュ値を例に表にすると以下の表のようになります。
$2a$10$E5J7SFVBbzynwgKPazA69uNN9lpn6zHq5om6a51FuoTqxo9KsxQHG
要素 | 実際の文字列 | 範囲 |
---|---|---|
バージョン情報 | $2 | 最初の$の後 |
ストレッチング回数 | $10 | 2番目の$の後 |
ソルト値 | $E5J7SFVBbzynwgKPazA69 | 3番目の$の後 |
実際のハッシュ値 | uNN9lpn6zHq5om6a51FuoTqxo9KsxQHG | 30文字目から最後 |
プログラムの実装例
eApplication.java
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@SpringBootApplication
public class SpringBootEncodeApplication implements CommandLineRunner {
@Autowired
PasswordEncoder passwordEncoder;
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public static void main(String[] args) {
SpringApplication.run(SpringBootEncodeApplication.class, args);
}
@Override
public void run(String... args) {
String password = "123";
// PasswordEncoderのencodeメソッドを用いての平文のパスワードのハッシュ化
String hashedPassword = passwordEncoder.encode(password);
System.out.println("hashedPassword : " + hashedPassword);
// PasswordEncoderのmatchesメソッドを用いて平文パスワードとハッシュ化したパスワードの照合
if (passwordEncoder.matches(password, hashedPassword)) {
System.out.println("it is match");
}
System.out.println("it is not match");
}
}