crypto를 활용한 암호화

6120 단어 node.jsnode.js

암호화의 방식

암호화에는 크게 세 가지 방법이 있다.

  1. 단방향 암호화
  2. 양방향 비대칭형 암호화
  3. 양방향 대칭형 암호화

node.js에 내장되어 있는 crypto 모듈은 단방향 암호화를 이용하고 있다.


암호화와 복호화

  • 암호화: 평문을 암호로 만드는 작업
  • 복호화: 암호를 평문으로 해독하는 작업

해시 기법

단방향 암호화의 대표 주자는 해시 기법이다. 해시기법은 문자열을 고정된 길이의 다른 문자열로 바꾸는 방식이다.
여기서 중요한 것은 암호화 된 암호를 다시 평문으로 바꿀 수 없다(복호화 불가능). 특정 단어를 해시화하면 같은 결과를 가져온다. 그래서 DB에는 해시화된 암호를 저장하여 DB를 해킹당해도 비밀번호를 보호할 수 있다.

const crypto = require('crypto');
crypto.createHash('sha512').update('비밀번호').digest('base64'); // 'dvfV6nyLRRt3NxKSlTHOkkEGgqW2HRtfu19Ou/psUXvwlebbXCboxIPmDYOFRIpqav2eUTBFuHaZri5x+usy1g=='
crypto.createHash('sha512').update('비밀번호').digest('base64'); // 위와 같은 결과

위에 예시를 자세히 보면

  • createHash에는 사용할 해시 알고리즘을 넣어준다. md5, sha1, sha256, sha512 등의 알고리즘이 존재하지만, md5와 sha1은 취약점이 발견되어 sha512를 추천한다.
  • update에는 변환할 문자열을 넣어준다.
  • digest에는 인코딩할 알고리즘을 넣어준다. base64, hex, latin 1 등이 사용되지만, base64가 결과 문자열이 가장 짧아 자주 사용된다.

하지만, 이러한 방식도 같은 알고리즘과 인코딩 방식을 사용하면 같은 비밀번호에 대해 같은 결과를 반환한다.
그래서 만약 해커가 모든 암호에 대해 어떤 결과가 나올지 데이터베이스화 해두었다면, 결과만 보고도 원래 암호를 유추해낼 수 있다. 이러한 데이터베이스를 레인보우 테이블이라고 한다.


Salt

이러한 레인보우 테이블을 사용하지 못하도록 하기위해 Salt를 사용해야한다. salt라는 특정 값을 통해서 해시화 결과를 변형할 수 있다. 비밀번호에 salt 문자열을 붙여서 그것을 수 만번 반복 해시화 하는 방식이다. salt는 랜덤 문자열을 생성해서 비밀번호와 같이 DB에 저장한다.

crypto.randomBytes(64, (err, buf) => {
  crypto.pbkdf2('비밀번호', buf.toString('base64'), 100000, 64, 'sha512', (err, key) => {
    console.log(key.toString('base64')); // 'dWhPkH6c4X1Y71A/DrAHhML3DyKQdEkUOIaSmYCI7xZkD5bLZhPF0dOSs2YZA/Y4B8XNfWd3DHIqR5234RtHzw=='
  });
});

위의 예시를 자세히 보면,

  • crypto.randomBytes가 64바이트의 문자열을 생성하여 Salt역할을 수행한다.
  • pbkdf2는 Salt를 사용하기위한 알고리즘 이름이다. 각 인수로 비밀번호, salt, 반복횟수, 출력 바이트, 알고리즘을 받는다.
  • 반복 횟수를 조정해 암호화하는 데 1초 정도 걸리게 맞추는 것이 권장된다.
  • 반드시 salt를 key와 같이 저장해야 한다! randomBytes 메소드는 매번 다른 salt값을 뱉어내기 때문에 암호화 매번 결과가 달라지게 된다. 같은 salt값으로 비밀번호를 찾아야 비교가 가능하기 때문에 salt를 보관해야 한다. 또한 반복 횟수, 비밀번호 길이, 해시 알고리즘, 인코딩 방식까지 다 같아야 같은 결과가 나오게 된다.


출처:

좋은 웹페이지 즐겨찾기