일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- React.js
- Reducer
- Kubernetes
- AWS
- action
- docker
- #api 문서화
- ecs
- 모캠
- 쿠버네티스 컨트롤러
- #Swagger-ui
- Site Reliability engineering
- 카카오게임즈
- SRE
- 기술PM
- 모두의캠퍼스
- 쿠버네티스
- Redux
- #Swagger-codegen
- javascript
- #Swagger-editor
- 프로세스
- 프로세스 통신
- server
- #스웨거
- IP
- 북딜
- fluentd
- #Swagger
- React
- Today
- Total
탕구리's 블로그
Node.js Crypto 모듈 본문
시작하기 전에
해당 블로그에 작성되는 글은 주인장의 지극히 주관적인 생각이 다수이며, 대부분의 지식은 구글링을 통해 얻고 있기 때문에 옳지않은 정보가 있습니다.
잘못된 부분이나 수정해야 하는 부분이 있다면 과감히 덧글을 남겨주세요! 모르는게 많은 새싹입니다
Crypto 모듈을 이용한 기초적인 단방향 암호화
암호화란?
간단하게 생각하면 내가 가진 정보를 다른사람이 알아보지 못하게 "난독화" 혹은 "나만의 비밀번호를 설정" 하는 과정이라고 생각하시면 편할것 같아요.
위키백과를 들여다 보면 아래와 같은 설명이 있습니다.
암호화(暗號化) 또는 엔크립션은 특별한 지식을 소유한 사람들을 제외하고는 누구든지 읽어볼 수 없도록 알고리즘을 이용하여 정보(평문을 가리킴)를 전달하는 과정이다. 이러한 과정을 통해 암호화된 정보(암호문)를 낳는다. 이에 역행하는 과정을 해독 또는 디크립션이라고 하며 이로써 암호화된 정보를 다시 읽을 수 있다.
암호화 방식
암호화 방식은 크게 세가지로 분류할 수 있다는 글을 보았습니다. 단방향 암호화와 양방향 암호화 이며, 양방향 암호화는 대칭형 암호화와 비대칭형 암호화가 존재합니다. 대칭형 암호화와 비대칭형 암호화는 암호화할 때 사용하는 키와 복호화할 때 사용하는 키의 동일성(?)에 대한 기준으로 구분하게 됩니다.
그러면 단방향 암호화는 무엇일까? 단방향 암호화는 말 그대로 암호화만 가능하고 복호화(암호화한 내용을 다시 되돌리는것)가 불가능하게 함을 목표로 합니다.
단방향 암호화는 복호화가 불가능하기 때문에 복호화할 필요가 없는 정보를 암호화 하는데 사용합니다. 일반적으로 저희가 이용하는 웹 사이트에서 비밀번호는 한번 암호화 하면 복호화 할 필요가 없기 때문에 단방향 암호화를 이용하여 비밀번호를 암호화 시키고 사용자가 로그인을 할때는 입력받은 비밀번호를 다시 암호화하여 기존에 암호화 되었던 값과 비교를 통해 로그인 처리를 하게 됩니다.
저희는 오늘 단방향 암호화에 대한 실습을 할 예정입니다.(단방향 밖에 안해봤기 때문에)
단방향 암호화 해보기
우선, Node.js를 이용해 단방향 암호화를 하는 방법은 아.주. 무.지. 간.단. 합니다.
const string = 'this is my password' //1. 단순 해싱으로 비밀번호 해싱 let hashAlgorithm = crypto.createHash('sha512'); //선택된 알고리즘으로 해싱 let hashing = hashAlgorithm.update(string); //표시할 인코딩 설정. let hashedString = hashing.digest('base64');
자! 이게 끝입니다
이제 실행되는 순서를 살펴 봅시다.
첫번째, string 변수 안에 사용할 비밀번호를 입력 받습니다.
두번째, 사용할 해시함수를 선택합니다 위의 코드에서는 "sha512" 방식을 선택 하였습니다.
세번째, 선택한 해시함수와 나의 비밀번호를 해싱하는 과정을 실행합니다.
마지막으로 "base64"로의 인코딩 된 digest 코드를 만들어 냅니다.
하지만 이러한 단순방식은 같은 알고리즘과 같은 인코딩 방식을 선택하여 암호화하면 같은 결과을 뱉어냅니다.
"레인보우 테이블"을 통해 해커는 암호화된 결과를 보고 원래의 비밀번호를 도출할 수 있습니다.
소금을 뿌려 해커를 방해하자.
이렇게 소금(salt)와 password를 섞어 해시함수에 넣어주면 기똥찬 digest가 나오게 됩니다.
모든 패스워드에 같은 소금정보를 사용하게 되면 해커가 한번 소금정보를 알아 냈을때 다른 비밀번호도 쉽게 뚫리겠죠?
이 문제를 해결하기 위해서 랜덤바이트를 생성하여 임의 소금정보를 생성하여 줍니다.
crypto.randomBytes(32, function(err, buffer){ //32bit 길이의 random byte 생성 if(err){ console.log(err); } else{ }})
이렇게 cryto모듈의 랜덤바이트 함수를 이용하면 32비트의 기똥찬 소금을 만들어 낼 수 있습니다.
랜덤바이트 함수의 콜백으로 err, buffer(이것을 나중에 base64로 인코딩할 겁니다!) 정보를 받게 됩니다.
그럼 이렇게 저희는 문자열과 솔트를 얻게 되었습니다.
해커를 좀 더 괴롭히는 키 스트레칭(Key Stretching)
crypto.pbkdf2(string, buffer.toString('base64'), 130495, 64, 'sha512', function(err, hashed) { if(err){ console.log(err); } else{ console.log(hashed.toString('base64')); } });
pdkdf함수에는 총 다섯가지의 인자가 들어갑니다.
1. 저희가 처음에 해싱하려 했던 문자열(패스워드)가 들어갑니다.
2. 위에서 랜덤바이트 함수를 통해 생성했던 버퍼있죠? 아까 말씀 드렸던것 처럼 base64로의 인코딩을 통해 넣어줍니다.
3. 이터레이션 반복횟수를 지정해 줍니다. 반복횟수가 많아 질수록 복호화하기 어려워지지만 그만큼 시간도 많이 소모됩니다. (네이버 D2페이지 에서는 1초에 5번 정도 비교할 수 있는 반복횟수를 넣어주는게 좋다고 적혀있어요!)
4. digest의 길이를 설정해줍니다.
5. 어떤 암호화 알고리즘을 사용할 것 인가! 저는 sha512 알고리즘을 이용하였습니다.
로그를 찍어보면 이렇게!
정체모를 문자열을 만들어 줍니다.
이상으로 단방향 암호화와 Crypto 모듈에 대한 포스팅을 마치도록 하겠습니다.
시간이 나면 얼른 양방향 암호화에 대한 포스팅도 작성할 예정입니다.
'javascript > Node.js' 카테고리의 다른 글
Node.js Stream API에 대해 알아보자! (0) | 2018.12.19 |
---|---|
ORM(Object Relation Mapping)을 이용해보자!!! 1편 Sequelize.js (0) | 2018.06.22 |
ORM(Object Relation Mapping)을 이용해보자! 2편 CRUD! (0) | 2018.06.17 |