[JAVA] Handle passwords hashed with BCryptPasswordEncoder in Spring Security in Perl

There are times when you want to use a string such as password hashed with BCryptPasswordEncoder in Spring Security from Perl for authentication, right?

No, I don't know.

Premise

There was such an event.

Hash value stored in DB

$2a$10$Cc6/UiniMuKkyVsVM.FUt.rmgDm0UOQxuhuGSSuL/LzZUGrNeGvxq

Such a value was saved. It seems to be the work of Spring Security. What kind of value is this unfamiliar hash value?

When I was addicted to the situation, I googled variously, but no information came out.

Raw password

JscxAX:5[4Q]NYoK

A certain login user "This is my password, is it correct?" I asked me in Perl.

Well, verification of that strange character string and this password that Spring Security has hashed and stored earlier? I don't know about Perl, right?

No, let's do our best

It's surprisingly easy

code

use strict;
use warnings;
use utf8;
use feature qw(say);
use Crypt::Eksblowfish::Bcrypt qw(bcrypt);

my $raw_password = 'JscxAX:5[4Q]NYoK';

my $hashed_password = '$2a$10$Cc6/UiniMuKkyVsVM.FUt.rmgDm0UOQxuhuGSSuL/LzZUGrNeGvxq';

my $salt  = substr($hashed_password, 0, 29); # "$2a$10$" +22 characters
my $check = bcrypt($raw_password, $salt);

if ($check eq $hashed_password) {
    say "ATTERUYO!";
}
else {
    say "ATTENAIYO!";
}

result

ATTERUYO!

Was good. There was.

… Eh, does this come out with ATTERUYO! Every time?

If the user enters the wrong password

my $raw_password = 'JscxAX:4[5Q]NYoK';

Only one line changed to a slightly wrong feeling.

result

ATTENAIYO!

Was good. I can judge the mistake properly.

Save it from Perl with the same etiquette.

Spring Security "From Perl, change the password and create a function to save it." You say.

Yeah, you use that value for validation, right? Do I have to make it a format that you can handle ...?

… Of course, you have to do that.

The hated Perl should be able to do it. So do your best

Don't say that you can do it in Java, you can't do it in Perl, or you can't put it upwind of a camel.

code

use strict;
use warnings;
use utf8;
use feature qw(say);
use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64);
use Crypt::Random qw(makerandom_octet);

sub gen_salt {
    return en_base64(makerandom_octet(Length => 16));
}

my $raw_password = 'Z86J9_Kr_sDcw#o4'; #new password

my $salt = '$2a$10$' . gen_salt();
my $hashed_password = bcrypt($raw_password, $salt);

say $hashed_password;

result

$2a$10$/IwrxT05tg1ZlmUrV.7eAOsowJsbkVHs6ku54FC0VHBew23HOm61W

I could do something like that

Verify with Spring Security

Z86J9_Kr_sDcw#o4 Password is given by the above Perl code $2a$10$/IwrxT05tg1ZlmUrV.7eAOsowJsbkVHs6ku54FC0VHBew23HOm61W It has been converted into a character string like that and saved in the DB. Is it really possible to verify this hash correctly with Java (Spring Security) ...?

code

Indeed, I verified it with a fairly appropriate code that has a strong feeling of being written by a person who does not usually write Java.

package com.example.demo;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

public class DemoApplication {
    public static void main(String[] args) {
        String rawPassword = "Z86Jq_Kr_sDcw#o4";
        String hashedPassword = "$2a$10$/IwrxT05tg1ZlmUrV.7eAOsowJsbkVHs6ku54FC0VHBew23HOm61W";

        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        if (passwordEncoder.matches(rawPassword, hashedPassword)) {
            System.out.println("ATTERUYO!");
        }
        else {
            System.out.println("ATTENAIYO!");
        }
    }
}

result

ATTERUYO!

I'm glad I was able to do it properly.

… Eh, does this come out with ATTERUYO! Every time?

If the user enters the wrong password

        String rawPassword = "Z86Jq_Kr_sDcw#o4";

Only one line changed to a slightly wrong feeling.

result

ATTENAIYO!

Was good. I can judge the mistake properly.

What about other hashing?

There are SCryptPasswordEncoder and Pbkdf2PasswordEncoder, but at this point it's not an issue in my environment, so someday someone should put it together.

Recommended Posts

Handle passwords hashed with BCryptPasswordEncoder in Spring Security in Perl
Hash passwords with Spring Boot + Spring Security (with salt, with stretching)
Call your own method with PreAuthorize in Spring Security
Login function with Spring Security
Login with HttpServletRequest # login in Spring Security of Servlet 3.x environment
Implemented authentication function with Spring Security ②
Implemented authentication function with Spring Security ①
Authentication / authorization with Spring Security & Thymeleaf
Handle system environment variables in Spring application.properties
Use Spring Security JSP tags with FreeMarker
How Spring Security works with Hello World
Achieve BASIC authentication with Spring Boot + Spring Security
Test controller with Mock MVC in Spring Boot
Asynchronous processing with regular execution in Spring Boot
Implement Sign in with Twitter in spring-boot, security, social
Tests with @Parameters in Spring 4.3 should have no parameters
Try LDAP authentication with Spring Security (Spring Boot) + OpenLDAP
Add your own authentication items with Spring Security
[JAVA] [Spring] [MyBatis] Use IN () with SQL Builder
[Introduction to Spring Boot] Authentication function with Spring Security
Handle JSON in cross domain with Play Framework
Create Spring Cloud Config Server with security with Spring Boot 2.0