Node js 비대칭 암호화 - Node js bidaeching amhohwa

Node.js를 설치하게 되면 내장 모듈중 crypto라는 모듈이 있습니다.
이 모듈을 사용하여 암호화 하는 방법에 대해서 알아보겠습니다.

비밀번호를 단순히 평문으로 데이터베이스에 저장하는 것은 범죄와 다름 없습니다.

데이터베이스가 해킹 당하는 순간 고객들의 비밀번호가 그대로 해커의 손에 넘어가게 되는 것이죠.
(데이터베이스가 해킹 당하지 않는 것이 최선..)
그렇기 때문에 비밀번호 암호화로 안전장치를 만들어 놓는 것입니다.

암호화의 방법은 단방향 암호화와 양방향 암호화 두가지가 있습니다.
먼저 단방향 암호화에 대해서 알아보겠습니다.

1. 단방향 암호화
비밀번호는 보통 단방향 암호화를 사용합니다. 단방향 암호화는 복호화 할 수 없는 암호화 방식입니다. 복호화는 암호화된 문자열을 암호화 되기전의 평문으로 되돌려 놓는 것을 의미합니다. 그러므로 단방향 암호화를 사용하게 되면 원래 문자열이 무엇인지 알 수 없습니다.

Q: 왜 비밀번호 저장을 단방향 암호화로 할까요?
A: 고객의 비밀번호를 굳이 복호화할 이유가 없기 때문입니다.

Q: 복호화가 되어있지 않으면 비교는 어떻게하나요?
A: 기존에 데이터베이스에 저장된 암호화된 비밀번호와 로그인할 때 입력받은 비밀번호를 단방향 암호화를 통해 비교하면 됩니다.

즉 기존의 비밀번호는 어디에도 저장되지 않고 암호화된 문자열로만 비교하는 방법입니다.

단방향 암호화는 해시 알고리즘을 사용합니다. 해시는 임의의 크기를 가진 문자열을 고정된 길이의 다른 문자열로 변경하는 것을 말합니다. 예를 들어서 zqxwce라는 문자열과 asdf라는 문자열을 해시 알고리즘을 사용한다면 고정된 길이(6개로 가정) pmonib와 lkjhgf로 바꾸는 방식입니다. 입력된 문자열의 길이가 다르지만, 해시알고리즘으로 변경된 문자열의 길이는 6개로 고정되어 있습니다.

해시함수를 어떻게 쓰는지 알아보겠습니다.

먼저 crypto의 method와 property에 대해서 알아보겠습니다.

- createHash(algorithm[,options]): 사용할 해시 알고리즘을 입력합니다.

md5

,

sha1

, sha256, sha512등이 가능합니다.
- update(data[,inputEncoding]): 변환할 문자열을 입력합니다.
- digest([encoding]): 인코딩할 알고리즘을 넣어줍니다. base64, hex, latin1이 주로 사용됩니다. 변환된 문자열을 반환합니다.

crypto란?

javascript에서 해시 함수를 통한 암호화를 할 수 있도록 해주는 Node.js 패키지

해시함수란? / 블록체인 내부의 해시함수

[프로그래밍] 블록체인이란?

블록체인이란? 정보가 담긴 블록을 체인형태로 묶은 것으로, 여러명의 사람들이 하나의 데이터를 나눠서 저장하는 기술 블록체인의 필요성 하나의 컴퓨터가 해킹당해 정보가 조작되었더라도,

defineall.tistory.com

Node js 비대칭 암호화 - Node js bidaeching amhohwa

crypto의 필요성

node.js 앱에서, 중요한 정보를 암호화 해, 안전하게 보호 할 수 있다

crypto 설치

Node.js 기본 패키지 이므로 따로 설치할 필요가 없다.

암호화 방법

단방향 암호화 : 

  복호화 할 수 없는 암호화 ( 복호화 : 암호화 되기 이전의 내용으로 되돌리는 것 )
  
  해시 함수 ( crypto로 사용할 수 있는 부분 )

양방향 암호화

  대칭형 암호화
  
  비대칭형 암호화

암호화 사용법

1. 비밀번호 암호화

2. 암호화된 문자열 DB에 저장

3. 다음에 비밀번호 입력 받아 다시 암호화해서, DB에 저장된 암호화 문자열과 비교

4. 일치하면 승인, 그렇지 않으면 거부

cryto 사용법

// crypto 사용하기 위한 모듈 불러오기

import crypto from 'crypto';

// 'sha512' 해시 함수 사용해서 base64, hex 형식으로 출력하기

crypto.createHash('sha512').update('비밀번호').digest('base64');
crypto.createHash('sha512').update('비밀번호').digest('hex');

해커의 레인보우 테이블 방지하기 위한 salt 생성

import crypto from 'crypto';

// salt값을 구할때와 해시값을 구할때, 작업이 끝날때까지 기다려 주어야 하므로 [동기 방식] 사용

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



// randomBytes(64) : 64비트 길이의 salt을 돌려준다.

// salt는 버퍼 형식이기 때문에 salt.toString('base64')로 base64 문자열로 바꿔주어야 한다.

// pbkdf2(비밀번호, salt, 반복횟수, 비밀번호길이, 해시 알고리즘) :설정값에 따른 최종 해시값을 돌려준다.

    반복횟수 : 해시함수를 몇 번 반복하느냐 ( 10만번으로 설정했음 )
    
    비밀번호 길이 : 적당한 길이로 설정 ( 해킹이 어렵도록 )
    
    해시 알고리즘 : 사용하고 싶은 해시 함수 ( sha512 선택했음 )
    
    salt를 key와 같이 저장해야만, 정확한 비밀번호 비교가 가능하다.
    
    randomBytes 메소드는 매번 다른 salt값을 돌려주므로, 암호화 결과가 매번 달라진다.

* 동기 방식과 버퍼  /  defineall.tistory.com/648

* 레인 보우 테이블 / https://defineall.tistory.com/1011

대칭형 암호화

키가 있으면, 암호화된 해시값을 복호화할 수 있다.

웹에서는 사용하기 어렵다

특정 키로 암호화한 문자열을 서버에서 클라이언트로 보냈을 때,

그 문자열을 복호화하려면 그 키도 같이 보내주어야 하는데,

클라이언트에서는 무슨 일이 일어날 지 모르기때문에 키를 클라이언트로 보내서는 안된다.

비대칭형 암호화를 사용함으로 해결할 수 있다.

대칭형 암호화 방식 사용

import crypto from 'crypto';

const cipher = crypto.createCipher('aes-256-cbc', '열쇠');
let result = cipher.update('암호화할문장', 'utf8', 'base64');
result += cipher.final('base64');



// createCipher(암호화알고리즘, 키) : 암호화 객체 만들기

// 그 후 update 및 final 메소드를 호출해주면 암호화가 됩니다.

// update(암호화할문장, 사용할 인코더, 사용할 출력형식) : base64형식의 buffer 생성

// final을 해줘야만, final block이 생성되고, final block이 있어야 복호화를 할 수 있다.



const decipher = crypto.createDecipher('aes-256-cbc', '열쇠');
let result2 = decipher.update(result, 'base64', 'utf8');
result2 += decipher.final('utf8');



// createDecipher(암호화알고리즘, 키) : 복호화 객체 만들기

// 그 후 update 및 final 메소드를 호출해주면 복호화가 됩니다!

// update(복호화할문장, 사용한 출력형식, 사용한 인코더)

// final을 하지않아도 결과의 일부가 출력, final block 생성시 나머지 부분 출력