Node 내장 모듈 (3) - crypto와 util

김무연·2023년 12월 12일

Backend

목록 보기
18/49

단방향 암호화(crypto)

암호화는 가능하지만 복호화는 불가능

  • 암호화 : 평문 => 암호화 ( asdf => @$sefe23121cv:!@#fdfs )
  • 복호화 : 암호화 => 평문 ( @$sefe23121cv:!@#fdfs => asdf )

단방향 암호화의 대표 주자는 해시 기법

  • 문자열을 고정된 길이의 다른 문자열로 바꾸는 방식
  • abcdefgh 문자열 => qvew
  • 복호화 불가능
  • 비밀번호에서 많이 쓰임
  • 암호화를 할시 알고리즘에 의해 동일한 특정한 문자가 생기는데, 그 특정한 문자와 서버가 가지고 있는 문자와 비교해서 맞는 것만 통과

hash 사용하기 (sha512)

createHash(알고리즘)

알고리즘에 사용할 해시 알고리즘을 넣어줍니다.

  • 알고리즘 종류에는 md5, sha1, sha256, sha512 등이 가능하지만, md5와 sha1은 이미 취약점이 발견되었습니다
  • 현재는 sha512 정도로 충분하지만, 나중에 이 마저도 취학해지면 더 강화된 알고리즘으로 바뀌어야 합니다.

update(문자열) : 변환할 문자열을 넣어줍니다

digest(인코딩) : 인코딩할 알고리즘을 넣어줍니다.

  • base64, hex, latin1이 주로 사용되는데, 그 중 base64가 결과 문자열이 가장 짧아 애용됩니다. 결과물로 변환된 문자열을 반환합니다.
const crypto = require('crypto');

console.log('base64:', crypto.createHash('sha512').update('비밀번호').digest('base64'));
console.log('hex:', crypto.createHash('sha512').update('비밀번호').digest('hex'));
console.log('base64:', crypto.createHash('sha512').update('다른 비밀번호').digest('base64'));

pbkdf2

컴퓨터의 발달로 기존 암호화 알고리즘이 위협받고 있음

  • sha512가 취햑해지면 sha3으로 넘어가야 함
  • 현재는 pbkdf2나, bcrypt, scrypt 알고리즘으로 비밀번호를 암호화
  • Node는 pbkdf2와 scrypt 지원

  • cyprto.randomBytes로 64바이트 문자열 생성 -> salt 역할
  • 암호학에서 솔트(salt)는 데이터, 비밀번호, 통과암호를 해시 처리하는 단방향 함수의 추가 입력으로 사용되는 랜덤 데이터
  • pbkdf2 인수로 ( 비밀번호, salt, 반복 횟수, 출력 바이트, 알고리즘)
  • 반복 횟수를 조정해 암호화하는 데 1초 정도 걸리게 맞추는 것이 줜장됨
const crypto = require('crypto');

crypto.randomBytes(64, (err, buf) => {
  const salt = buf.toString('base64');
  console.log('salt:', salt);
  crypto.pbkdf2('비밀번호', salt, 100000, 64, 'sha512', (err, key) => {
    console.log('password:', key.toString('base64'));
  });
});

양방향 암호화 ( 대칭형/비대칭형 )

대칭형 암호화(암호문 복호화 가능)

  • key가 사용됨
  • 암호화할 때와 복호화 할 때 같은 key를 사용해야 함
  • key를 이용하기 때문에 보안에 취약함
  • 해커들은 암호화를 복호화 하려는 것이 아닌 key를 탈취하려고 함
  • 프론트 서버에서는 key를 관리할 수 없음. 왜냐하면 프론트 서버의 코드는 전부 공개되어 있기 때문..
const crypto = require('crypto');

const algorithm = 'aes-256-cbc';
const key = 'abcdefghijklmnopqrstuvwxyz123456';
const iv = '1234567890123456';

const cipher = crypto.createCipheriv(algorithm, key, iv);
let result = cipher.update('암호화할 문장', 'utf8', 'base64');
result += cipher.final('base64');
console.log('암호화:', result);

const decipher = crypto.createDecipheriv(algorithm, key, iv);
let result2 = decipher.update(result, 'base64', 'utf8');
result2 += decipher.final('utf8');
console.log('복호화:', result2);

  • 기존 node에 내장 된 암호화들은 복잡하기도 하고 암호학 기반 지식이 없으면 사용하기가 어려우니, crypto-js 라이브러리를 많이 사용 함 (남이 만들어 둔 암호화)
    https://www.npmjs.com/package/crypto-js

  • key 관리가 애매하기 때문에 AWS KMS (Key management System) 등을 이용하기도 함

util (편의기능)

각종 편의 기능을 모아둔 모듈

  • deprecated와 promisify가 자주 쓰임

deprecated

util.deprecated(경고 메시지가 출력될 함수, 경고 메시지 내용)

  • 함수를 쓰면 경고창이 나오게 만드는 함수
  • 예를 들어 프로그램을 만든 후 코드가 잘못되었다는 것을 인지할 시 수정하거나, 기존코드를 지워야 되는데, 이를 그냥 지워버리게 되면 그 코드를 쓰고 있거나, 연관된 파일에서 모두 오류가 발생하게 됩니다
  • 그렇기 때문에 왠만하면 코드가 잘못된 걸 나중에 알게될 시 그대로 진행을 하고, deprecated함수를 통해 함수 실행시 경고창이 뜨도록 해줍니다

promisify

  • 최근에는 callback 함수에서 promise기반으로 넘어가는 추세
  • 옛날 함수들은 callback 기반으로 작성이 많이 되어 있음
  • 하지만 위와 같은 이유로 삭제를 못하기도 하고, node에서 아직 promise를 지원안하는 기능도 몇 개 있기도 해서 사용
  • promisify로 callback 함수를 감쌀 시 promise처럼 async / await, promise, then, catch 이용가능하게 됩니다.
  • 단 callback이 (error, data) => {} 형식이어야 함
const util = require('util');
const crypto = require('crypto');

const dontUseMe = util.deprecate((x, y) => {
  console.log(x + y);
}, 'dontUseMe 함수는 deprecated되었으니 더 이상 사용하지 마세요!');
dontUseMe(1, 2);

const randomBytesPromise = util.promisify(crypto.randomBytes);
randomBytesPromise(64)
  .then((buf) => {
    console.log(buf.toString('base64'));
  })
  .catch((error) => {
    console.error(error);
  });

profile
Notion에 정리된 공부한 글을 옮겨오는 중입니다... (진행중)

0개의 댓글