ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [security] hashing password with bcrypt
    Back-end 2021. 12. 10. 01:23

    비밀번호의 보안?

    백 엔드에서 유저의 비밀번호를 데이터베이스에 그대로 저장하는 경우가 있을까요? 🐱 그 것은 정말 엉망진창의 보안일 것입니다. 누군가가 데이터베이스에 접근 하더라도 유저의 비밀번호는 확인할 수 없어야하지만, 우리는 비밀번호를 Compare하여 로그인을 진행하여야 하기 때문에 비밀번호의 데이터베이스 저장은 필수불가결합니다. 그렇다면 어떻게 우리는 비밀번호를 숨길 수 있을까요?

     

    "그 것은 비밀번호를 Hashing 하는 것 입니다."

     

    우선 비밀번호 해쉬화 알고리즘은 예전부터 발달되어 오던 기술입니다. 해싱에 관한 많은 알고리즘이 있지요. 그 중 우리는 Blowfish를 이용한 Bcrypt를 이용하여 비밀번호를 해싱할 것입니다. 많은 다양한 기술이 있습니다만 ex) SHA SHA를 사용하는 암호화는 빠른 연산의 GPU 공격에 취약하기 때문에 (SHA 암호화는 GPU 연산에 유리한 32비트 논리 및 산술 연산에만 사용됩니다.

    따라서 우리는 공격자의 속도를 늦춰야할 필요가 있기 때문에 bycrypt를 기용하기로 합니다.

     

    한번 해싱된 비밀번호는 절대 복호화가 불가능하며, 이 것은 단방향 함수이기 때문에 원래의 비밀번호를 해싱된 비밀번호와 비교하는 것 밖에 하지 못할 것입니다.

    bycrypt algorihm

    감사하게도 우리는 이미 구현된 패키지에 의해 bcrypt를 간단하게 구현할 수 있습니다. 

    npm install bcrypt

     

    데이터베이스에 넣기 전 우리는 유저에게 비밀번호를 input으로 받아올 것 입니다. 데이터베이스에 INSERT하기 전 우리는 bcrypt의 hash메소드를 통해 비밀번호를 해싱합니다.

    async hashPassword(): Promise<void> {
        try {
          this.password = await bcrypt.hash(this.password, 10);
        } catch (error) {
          console.log(error);
          throw new InternalServerErrorException();
        }
      }

    bcrypt의 default around (즉, 비밀번호를 얼마나 강하게 솔팅할 것인지를 정한다고 생각하면 편합니다.) 는 10입니다. 다음과 같이 비밀번호를 해싱하면 우리는 유저가 제공한 비밀번호를 Hashing할 수 있습니다.

     

    이렇게 Hashing된 비밀번호와 다시 유저의 로그인 요청 시 받아온 비밀번호를 비교하기 위해 다음과 같은 함수를 작성할 수 있습니다.

    async checkPassword(notSaltPassword: string): Promise<boolean> {
        try {
          const compareOk = await bcrypt.compare(notSaltPassword, this.password);
          return compareOk;
        } catch (error) {
          console.log(error);
          throw new InternalServerErrorException();
        }
      }

    마찬가지로, bcrypt의 compare메소드를 통하여 유저의 로그인 요청 시 받아온 비밀번호와 데이터베이스의 salting된 비밀번호를 비교하여 우리는 true or false를 return 할 수 있을 것이고 비밀번호를 비교할 수 있을 것입니다.

     

    이렇게 굉장히 중요한 비밀번호 암호화 기법 중 하나인 bcrypt에 대해 알아보았습니다. 도움이 되셨다면 좋을 것 같습니다🧤

    댓글

sangjun's blog