앞선 과정에서 단방향 암호화 방식을 살펴보았습니다. 이 과정을 간단히 요약하면, [비밀번호] → [해시 함수] → [다이제스트]의 과정을 거치게 된다고 볼 수 있죠. 단방향이므로 해시 함수에서 다시 비밀번호로 돌아갈 수 없다는 특징이 있다고 했습니다.
const crypto = require('crypto');
console.log('base64 : ', crypto.createHash('sha512').update('password').digest('base64'));
console.log('hex : ', crypto.createHash('sha512').update('password').digest('hex'));
console.log('base64 : ', crypto.createHash('sha512').update('other-password').digest('base64'));
/* 출력
base64 : sQnzu7wkTrgkQZF+0G1hi5AI3Qmzvv0bXgc5THBqi7mAsdd4Xll27ASbRt9fEyavWi6m0QP9B8lThf+rDKy8hg==
hex : b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86
base64 : VObtH7mbEpc0y+QlXH62L5LUTTSWeja4AyrqOKvHuBL9K0pAIPDxRzfab5mZ0+0TmnX9xt7qnnQy7Ay59Mw1Ig==
*/
물론 이런 변환 과정에서 '충돌'이 발생하는 가능성도 있습니다. 예를 들어 'abcdefgh'가 '"qvew"로 변환되었는데, 'nopqrst'라는 문자열도 "qvew"로 변환될 수도 있습니다. 그렇다면 비밀번호가 abcdefgh임에도 불구하고, nopqrst를 입력하게 되면 로그인이 되는 일이 발생합니다. 해킹을 할 때는 이러한 경우의 수를 찾아내는 경우가 많습니다.
앞선 아티클에서 설명했든 현재 사용되는 sha512 방식도 언젠가 취약점이 발견되면 더욱 강력한 알고리즘인 sha3를 사용하는 방식으로 보안을 진행해야 합니다.
최근에는 pbkdf2, bcrypt, scrypt 같은 알고리즘을 사용합니다. 여기서는 노드에서 지원하는 pbkdf2를 예제로 사용해보겠습니다. pbkdf2의 방식을 간단하게 설명하자면, [기존 문자열에 salt라고 불리는 문자열을 붙인 다음 해시 알고리즘을 반복 적용하는 것]입니다. 아래 예제를 보겠습니다.
const crypto = require('crypto');
crypto.randomBytes( 64, (err, buf) => {
const salt = buf.toString('base64');
console.log('salt:', salt);
crypto.pbkdf2('passwordString', salt, 10000, 64, 'sha512', (err, key) => {
console.log('password:', key.toString('base64'));
});
} );
/*출력 -- 실행 시 마다 변경
salt: s+QGH3e9defp/IslOtOoM4+pxeBzBYgcky0PcaPbH0f4JCEqtwpTu9BgAMoP9TRRUjty0Tsiyfm9yIkGiPLi/w==
password: fHqhCco00NVtxGKd6Ji5kRlwMvVIIH1UYec/CLMWBvP4qkDa0x4fy7ZkLDCBzbXgkskq3ZFkd5nK/V020FK56g==
*/
위 과정을 살펴보면, 우선 처음에 randomBytes( )로 64바이트 길이의 스트링을 생성하고 인코딩을 거친다면 이것이 salt가 됩니다. 다음, pbkdf2( ) 메서드에 [비밀번호, salt, 반복횟수, 출력 바이트, 알고리즘]을 인수로 전달합니다. 여기서는 "sha512로 변환된 결과를 sha512로 변환하는 과정을 10만 번 반복한다"라는 의미가 됩니다. 너무 많은 듯 해도 실제로는 1초면 됩니다.
참고로 crypto.randomBytes( )와 crypto.pbkdf2( )는 내부적으로 스레드 풀을 사용해 멀티 스레딩으로 동작합니다. 추후 살펴보겠습니다. 또한, 이는 randomBytes가 실행될 때마다 결과가 달라지므로 salt를 잘 보관하고 있어야 비밀번호를 찾을 수 있습니다. 물론 pbkdf2는 간단한 만큼 취약한 부분이 있기에, 나중에 예제에서는 bcrypt를 사용합니다.
'Programming > Node.js' 카테고리의 다른 글
4. Node 기능 살펴보기 (4) - 노드 내장 모듈 8 [util] (1) | 2024.04.26 |
---|---|
4. Node 기능 살펴보기 (4) - 노드 내장 모듈 7 [crypto] : 양방향 암호화 (0) | 2024.04.25 |
4. Node 기능 살펴보기 (4) - 노드 내장 모듈 7 [crypto] : 단방향 암호화 1 (0) | 2024.04.22 |
4. Node 기능 살펴보기 (4) - 노드 내장 모듈 6 [dns] (1) | 2024.04.19 |
4. Node 기능 살펴보기 (4) - 노드 내장 모듈 5 [url 2/2] (0) | 2024.04.18 |