패스워드 암호화 - Bcrypt

dalBeen·2023년 10월 23일
0

스프링

목록 보기
12/14

Bcrypt를 알아보기에 앞서 암호화, 복호화, 단방향, 양방향에 대해서 알아보자

암호화, 복호화, 단방향, 양방향

암호화

  • 사용자가 입력한 데이터를 알아볼 수 없는 데이터로 변경하는 과정

복호화

  • 암호화된 데이터를 정상적인 데이터로 변경하는 과정

단방향

  • 암호화를 수행하고 나온 데이터를 다시 원래의 데이터로 돌릴 수 없는 암호화 방식
  • 단방향 암호화에서 나오는 데이터는 원래 데이터의 1bit만 바뀌어도 전혀 다른 암호문으로 변함

양방향

  • 평문으로 되어있는 데이터를 암호화하게 되면, 알 수 없는 임의의 데이터로 변경되게 되고, 복호화를 수행하면 암호화되어 있는 데이터가 다시 원래의 데이터로 돌아오게 됨.
  • 암호화키, 복호화키라는 특정한 데이터를 요구

단방향에 대해 조금더 자세히

단반향 알고리즘으로 해시 알고리즘이 잘 알려져 있음
해시 알고리즘은 암호화 가능하지만, 복호화가 불가능하다는 점을 이용하여 데이터 무결성을 검증하기 위함
-> 데이터 무결성 : 데이터가 허락된 사용자로 인해 수정이 제대로 이루어졌는지, 허가되지 않은 사용자가 무단으로 데이터를 조작했는지 여부를 보는 것

  • 해시 함수/알고리즘
    • 어떤 데이터든지 일정한 길이의 문자열(또는 코드)로 변환
    • 변환된 문자열 = 해시값
      • 예를 들어 "안녕하세요"라는 문장은 "123456"으로 변환될 수 있음(실제 그렇지 않고 그냥 간단 예제)
      • 이때 동일한 데이터는 항상 동일한 해시값을 변환되지만 해시값을 원래의 데이터로 되돌릴 수 없음
      • 만약 조금이라도 문서의 내용이 바뀌면 해시값도 변함
    • 데이터의 무결성 확인하려면
      • 원본의 데이터 해시값을 저장
      • 나중에 그 데이터의 무결성을 확인하고 싶을때, 다시 그데이터의 해시값을 생성
      • 두 해시값이 동일하면 데이터가 바뀌지 않았다는 것
    • 해시 알고리즘 예 : SHA, Bcrypt

양방향에 대해 조금더 자세히

암호문을 복호화할 수 있도록 구현된 암호 알고리즘
키의 성질에 따라 구분되는데, 대칭키 암호 알고리즘 과 비대치킹 암호 알고리즘이 있다

  • 대칭키 암호 알고리즘
    • 쉽게 설명하자면 집의 문을 열고 닫는게 같은 열쇠를 사용하는 것
    • 데이터를 암호화, 복호화하는데 동일한 키를 사용
    • 장점 : 처리 속도가 빠름
    • 단점 : 키를 안전하게 전달하는 문제(키가 누출되면, 누군가 그 키로 암호화된 데이터를 복호화 가능)
    • 예 : DES,AES 등
  • 비대칭키 암호 알고리즘
    • 집의 문을 열때, 닫을때의 서로다른 키를 사용
    • 두개의 키가 존재. 하나는 공개키(모두에게 공개되는 키), 다른 하나는 개인키(본인만)
    • 공개키로 암호화하면 개인키로만 복호화할 수 있고, 개인키로 암호화하면 공개키로만 복호화할 수 있음
    • 장점 : 키 전달문제가 대칭키 방식보다 안전
    • 단점 : 처리 속도가 대칭키보다 느림
    • 예 : RSA, ECC등

Bcrypt이용해서 패스워드 암호화하기

여기서 잠깐 SHA, Bcrypt중 Bcrypt를 이용하는 이유는..?

SHA 경우
- GPU를 이용한 연산속도가 매우 빠르기 때문에 password 암호화에 권장되지 않음
- GPU 연산속도가 빠를수록 공격자의 하드웨어를 통한 오프라인 brute force에 더 취약하다.
-> 빠른 해시를 사용하여 암호화를 진행시 공격자는 오프라인 공격으로 초당 수십억개의 해시를 계산할 수 있다.

Bcrypt경우
- 반복횟수를 늘려 연산속도를 늦출 수 있으므로 연산 능력이 증가하더라도 brute-forece 공격에 대비할 수 있음

패스워드 암호화 요구 조건

  • 복호화 불가능
  • 해시함수 사용
  • 특정 패스워드 해시값이 노출되어도, 같은 패스워드인 다른 계정도 탈취당하면 안됨
  • salt 필요
  • Brute-force공격에 대비가 가능해야함(연산속도가 너무 빠르면 안된다)
salt ??
- 주로 비밀번호 해싱에서 랜덤한 데이터를 의미
- 원본 비밀번호에 추가되어, 해시함수의 입력으로 같이 제공
- 같은 비밀번호를 가진 사용자라도 다른 해시값을 생성하게 만들어 주는 것이 목적

솔트 사용 방법
- 사용자가 비밀번호 생성/변경시 랜던함 솔트 생성해서 원본 비밀번호에 추가

hash와 salt의 사용으로 똑같은 문자열 패스워드라도 다른 hash값 나옴

코드 만들어보기

  1. spring boot와 spring security가 필요로 함
dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-security'
}
  1. 암호화하기
@Override
    public boolean register(MemberInput parameter) {
    
        Optional<Member> optionalMember = memberRepository.findById(parameter.getUserId());
        if (optionalMember.isPresent()) {
            //현재 userId에 해당하는 데이터 존재
            return false;
        }

        String encPassword = BCrypt.hashpw(parameter.getPassword(), BCrypt.gensalt());
        String uuid = UUID.randomUUID().toString();
        
        Member member = Member.builder()
                .userId(parameter.getUserId())
                .userName(parameter.getUserName())
                .phone(parameter.getPhone())
                .password(encPassword)
                .regDt(LocalDateTime.now())
                .emailAuthYn(false)
                .emailAuthKey(uuid)
                .userStatus(Member.MEMBER_STATUS_REQ)
                .build();
        memberRepository.save(member);
        
        
        return true;
    }
  1. 비밀번호 로그인 맞는지 확인하는 방법
public class PasswordUtils {
    
    //비밀번호 맞는지 확인
    public static boolean equals(String plaintext, String hashed) {
        
        if (plaintext == null || plaintext.length() < 1) {
            return false;
        }
        
        if (hashed == null || hashed.length() < 1) {
            return false;
        }
        				    //사용자가 입력한 비미번호, DB에 저장되어있는 해시값
        return BCrypt.checkpw(plaintext, hashed);
    }
 
 	///비밀번호 암호화
    public static String encPassword(String plaintext) {
        if (plaintext == null || plaintext.length() < 1) {
            return "";
        }
        return BCrypt.hashpw(plaintext, BCrypt.gensalt());
    }

}

참고블로그

참고블로그

profile
깊게 공부해보자

0개의 댓글