[Research] bcrypt vs bcryptjs

5014 단어 ResearchstudyResearch

들어가며

요즘 Springboot Security의 로직을 공부하면서 node js의 Spring이라고 불리는 nest js에 대해 같이 공부하고 있다.

그러면서 유저 인증 관련 로직을 구현하면서 bcryptjs라는 라이브러리를 알게되었다.

bcryptjs는 bcrypt 라이브러리를 js에서 사용할 수 있도록 구현되서 nest js에선 무조건 bcryptjs를 사용해야 하는 줄 알았으나 최근에 nest js에서도 bcrypt 라이브러리를 사용할 수 있다는 것을 발견했다.

그렇다면 bcrypt 라이브러리가 있는데 왜 bcryptjs가 생겨났는 지, 두 라이브러리를 비교해보기로 했다.


npm 내부 사용 빈도

bcrypt

bcryptjs

두 라이브러리의 사용 빈도를 비교해보면 bcryptjs가 bcrypt에 비해 약 1.43배 많이 사용되었다.


성능 비교

두 라이브러리를 통해 10개의 임의 비밀번호를 암호화하고 기존 비밀번호와 비교하는 로직의 처리 시간을 비교해보고자 한다.

구현하는 로직은 다음과 같다.

  • Async 기반의 암호화 로직
  • Async 기반의 암호 비교 로직
  • Sync 기반의 암호화 로직
  • Sync 기반의 암호 비교 로직

bcrypt Code

// bcrypt library

import bcrypt from 'bcrypt';

const password = [  'MyPassword123!@#',
                'YourPassword123!@#',
                'MyPassword456!@#',
                'YourPassword**123!@#',
                'MyPass123!@#!@#',
                'Password123!@@@@#',
                'mypassword!!@#',
                'MyPassword!@#',
                'MyPassword123123',
                'MyPas(!)@#*!@)'  ]


async function doTest (password, i) {

    const saltRounds = 8;
    
    var hashAsync;
    var hashSync;

    console.log(`State : ${i}, Password : ${password} `)
	
    // - Async 기반의 암호화 로직
    console.time('bcrypt_Async Generate Hash');
    hashAsync = await bcrypt.hash(password, saltRounds);
    console.timeEnd('bcrypt_Async Generate Hash');

	// - Async 기반의 암호 비교 로직
    console.time('bcrypt_Async Compare Hash');
    await bcrypt.compare(password, hashAsync)
    console.timeEnd('bcrypt_Async Compare Hash');

	// - Sync 기반의 암호화 로직
    console.time('bcrypt_Sync Generate Hash');
    hashSync = bcrypt.hashSync(password, saltRounds);
    console.timeEnd('bcrypt_Sync Generate Hash')

	// - Sync 기반의 암호 비교 로직
    console.time('bcrypt_Sync Compare Hash');
    bcrypt.compareSync(password, hashSync);
    console.timeEnd('bcrypt_Sync Compare Hash');

    console.log();
}


for (var i = 0; i < 10; i++) {
    await doTest(password[i], i);
}

bcryptjs Code

// bcryptjs library

import bcryptjs from 'bcryptjs';

const password = [  'MyPassword123!@#',
                'YourPassword123!@#',
                'MyPassword456!@#',
                'YourPassword**123!@#',
                'MyPass123!@#!@#',
                'Password123!@@@@#',
                'mypassword!!@#',
                'MyPassword!@#',
                'MyPassword123123',
                'MyPas(!)@#*!@)'  ]


async function doTest (password, i) {

    const saltRounds = 8;
    
    var hashAsync;
    var hashSync;

    console.log(`State : ${i}, Password : ${password} `)

    // - Async 기반의 암호화 로직
    console.time('bcryptjs_Async Generate Hash');
    hashAsync = await bcryptjs.hash(password, saltRounds);
    console.timeEnd('bcryptjs_Async Generate Hash');

	// - Async 기반의 암호 비교 로직
    console.time('bcryptjs_Async Compare Hash');
    await bcryptjs.compare(password, hashAsync)
    console.timeEnd('bcryptjs_Async Compare Hash');

	// - Sync 기반의 암호화 로직
    console.time('bcryptjs_Sync Generate Hash');
    hashSync = bcryptjs.hashSync(password, saltRounds);
    console.timeEnd('bcryptjs_Sync Generate Hash')

	// - Sync 기반의 암호 비교 로직
    console.time('bcryptjs_Sync Compare Hash');
    bcryptjs.compareSync(password, hashSync);
    console.timeEnd('bcryptjs_Sync Compare Hash');

    console.log();
}



for (var i = 0; i < 10; i++) {
    await doTest(password[i], i);
}

실행 결과

bcrypt

bcryptjs

평균 수행 시간 비교

평균적으로 4개의 로직 모두에서 bcryptjs 라이브러리가 bcrypt 라이브러리에 비해 약 1.5배의 시간이 더 소요되는 것을 알 수 있다.


bcrypt 라이브러리의 제작자, kelektiv의 코멘트

bcrypt github 위키에 보면 제작자 kelektiv가 남긴 코멘트를 볼 수 있다.

위 코멘트를 해석하면 다음과 같다.

'bcryptjs 라이브러리는 순수 자바스크립트로 구현된 라이브러리로 c++로 구현된 bcrypt 라이브러리를 코드의 변화없이 대체할 수 있다.

다만 c++로 구현되어 스레드 풀 방식을 사용하는 기존의 bcrypt 라이브러리에 비해 단일 스레드로 구성된 js로 구현된 bcryptjs 라이브러리가 약 30%의 성능 차이를 보인다.

그러나 브라우저에서는 bcrypt 라이브러리가 동작하지 않기 때문에 웹브라우저 환경에서는 bcryptjs 라이브러리가 유일한 선택지다.'


결론

bcrypt 라이브러리가 bcryptjs 라이브러리에 비해 약 30% 정도 성능적으로 우수하지만 웹브라우저 환경에서 사용할 수 있다는 장점으로 인해 bcryptjs 라이브러리가 더욱 많이 사용된다.

좋은 웹페이지 즐겨찾기