Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
63
Help us understand the problem. What is going on with this article?

More than 3 years have passed since last update.

@NagaokaKenichi

Spring Boot + Spring Securityでパスワードをハッシュ化(ソルト付、ストレッチングあり)

Spring SecurityのPasswordEncoderを利用すると、ソルト付 + ストレッチングされたハッシュ値を容易に生成することが可能です。本記事はそのサンプルになります。

環境

JDK:1.8
Spring Boot:1.5.3.RELEASE
Spring Security:4.2.2.RELEASE

Spring Security PasswordEncoder Class Diagram

見づらいかもしれませんが、Spring Security4.2.2.RELEASEのPasswordEncoderのクラス図は以下のようになってます。

Spring Security PasswordEncoder Class Diagram1.png

PasswordEncoderインターフェースの実装クラスが6つあります。

PasswordEncoderの実装クラス 概要
AbstractPasswordEncoder -
NoOpPasswordEncoder ハッシュ化を行わないエンコーダ(テスト用)
Pbkdf2PasswordEncoder 設定可能な反復回数とランダムな8バイトランダムソルト値を使用してPBKDF2を使用するPasswordEncoderの実装
StandardPasswordEncoder SHA-256アルゴリズム + 1024回のストレッチでハッシュ化を行うエンコーダ
BCryptPasswordEncoder bcryptアルゴリズムでハッシュ化を行うエンコーダ
SCryptPasswordEncoder scryptアルゴリズムでハッシュ化を行うエンコーダ

本記事ではBCryptPasswordEncoderを使ってハッシュ化してみます。

BCryptPasswordEncoderを使ってハッシュ化

Spring Securityの依存関係を追加します。

pom.xml
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
</dependency>

今回はCommandLineRunnerをimplementsしてCLIとしています。

SpringBootEncodeApplication.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;

    public static void main(String[] args) {
        SpringApplication.run(SpringBootEncodeApplication.class, args);
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void run(String... args) {

        String password = "#fe?3d31";
        String digest = passwordEncoder.encode(password);
        System.out.println("ハッシュ値 = " + digest);

        if (passwordEncoder.matches(password, digest)) {
            System.out.println("一致したよ");
            return;
        }
        System.out.println("一致しなかったよ");
    }
}

平文パスワード(password)をPasswordEncoderのencodeメソッドを使ってハッシュ化します。ハッシュ化した結果がdigestです。
次に、PasswordEncoderのmatchesメソッドを使って平文パスワード(password)とencodeメソッドで得られたハッシュ値(digest)を照合します。

実行結果.
ハッシュ値 = $2a$10$im98CLRwtWohvPE6wZkYk.Os.RXZVF0iROJXL8vUn7TGrfWoixTdq
一致したよ

ハッシュ値の見方

上記で生成したハッシュ値は以下のようになりました。

$2a$10$im98CLRwtWohvPE6wZkYk.Os.RXZVF0iROJXL8vUn7TGrfWoixTdq

見方は以下の通りです。

文字場所 文字列 概要
1文字目~3文字目 $2a bcryptのバージョン番号。
4文字目~6文字目 $10 ストレッチング回数(ハッシュ化演算の繰り返し回数)になります。回数は2のn乗回です。そのため、この例だと2^10=1024回となります。
7文字目~29文字目 $im98CLRwtWohvPE6wZkYk. ソルト値。
30文字目~最後 Os.RXZVF0iROJXL8vUn7TGrfWoixTdq パスワード本体。

※ソルト値、ストレッチング等については、本記事の内容とは外れてしまうのでここでは省略します。

以上のように、Spring SecurityのPasswordEncoderを使えばソルト + ストレッチングされたハッシュ値が生成でき、また、平文パスワードとの照合も容易にできます。
※bcryptの話になってしまいました。

63
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
63
Help us understand the problem. What is going on with this article?