본문 바로가기
Programming/Study

PasswordEncoder의 작동 원리와 테스트하기 어려운 이유

by JKROH 2023. 12. 4.
반응형

 회원 가입 과정에서 비밀번호의 암호화가 잘 되었는지를 테스트하고자 했는데, 지속적으로 실패했다. 내 생각은 다음과 같았다. '과정 전부 거치고 나온 Response DTO의 비밀번호랑 따로 PasswordEncoder로 인코딩한 비밀번호가 같은지를 검증하면 되지 않을까?' 뭐 꽤 괜찮은 생각이라고 생각했다. PasswordEncoder는 BCrype

 

 그런데, 막상 진행해보니까 잘 되지를 않더라. 그래서 한 번, 같은 패스워드를 두 번 돌려서 결과를 확인해봤다.

    @Test
    void test(){
        PasswordEncoder passwordEncoder1 = PasswordEncoderFactories.createDelegatingPasswordEncoder();

        String password = "1234";
        String a =  passwordEncoder1.encode(password);
        String b =  passwordEncoder1.encode(password);

        System.out.println("a : " + a);
        System.out.println("b : " + b);
    }
    
/////////////////////////

a : {bcrypt}$2a$10$Jsle3EQOA0/rK6edqXdn3.Y4JmRpv7SV1B1IxIb1YT.iEk2mtF59m
b : {bcrypt}$2a$10$NCl4JqwI693dj6kpjCFNleFRfK.FbIG6P5hhc9DjKz3w70jr0y8Cu

 

 같은 값을 같은 PasswordEncoder에 넣었는데, 나오는 암호화 된 값은 달랐다. 관련해서 찾아보던 중 밸덩의 글bcrypt의 동작 과정을 읽고 해답을 알 수 있었다.

 

 밸덩의 글에 따르면 암호화 해시는 여러 가지 기준을 만족해야 한다. 그 중 Collision resistance, Preimage resistance, Second preimage resistance 를 만족시키면 같은 값을 넣어도 다른 결과물이 나온다. 간단하게 살펴보면

  • 해시 알고리즘 H, 서로 다른 메시지 a, b가 있다고 해보자.
  • Collision resistance를 만족시키면 H(a) != H(b)이다.
  • Preimage resistance를 만족시키면 암호화 된 값 c가 있을 때 H(x) = c를 만족시키는 x를 찾기 어려워야 한다.
  • Second preimage resistance를 만족시키면 같은 암호화 된 값을 만들어내는 두 인자를 찾을 수 없어야 한다.

 나는 Second preimage resistance에 집중했다. 'y라는 값이 두 번 나올 수는 있는데, 이게 어떻게 두 번 나왔는지는 몰라야한다.' 그러니까 H(x) = y가 나오고 H(z).= y가 나올 수도 있는데, x와 z를 찾는 것은 불가능해야한다는 말이다. 만약에 x == z면, 두 인자를 찾는 건 세상에서 제일 쉽다. 그냥 같으니까. 즉, "H(x) == H(z) 일 때, x != z여야 한다." 는 명제를 만들어 낼 수 있다. 참인 명제는 대우도 참이다. 즉, "x == z 일 때, H(x) != H(z)여야 한다" 도 참이 되는 것이다.

 

 이제 bcrypt의 동작 과정을 보면 확실하게 알 수 있다. bcrypt는 암호화 과정에서 무작위 salt를 원문에 추가한다. 즉, x를 두 번 넣는다고 해도 다른 salt가 첨가되기 때문에 H(x) == H(x)가 될 수가 없는 것이다.

 

 그럼 뭘 테스트해봐야하나를 찾아보니 PasswordEncoder의 내장 함수인 matches로 암호화한 값과 기존 값을 비교하는 테스트를 진행하는 분들도 있는데, 이게 굳이 필요한가 싶다. 암호화도 라이브러리 내장 함수고 matches도 내장 함순데 흠...

 

 아무튼 PasswordEncdoer테스트가 어려운 이유를 공부하면서 bcrypt 암호화 원리와 암호화 해시의 기본 규칙도 학습할 수 있는 시간이었다. 암호화 테스트는 좀 더 고민해보자.

반응형

댓글