JWT(JSON Web Token)
웹 애플리케이션에서 정보를 안전하게 전송하기 위한 방법
인증된 사용자 식별, 데이터 서명하여 변조 방지
Header
- 토큰의 타입과 해시 알고리즘 정보
Payload
- 실제 정보를 가진 데이터, claim이라 불리는 Key-Value로 이루어져 있음
Signature
- 토큰의 무결성 검증위한 서명 부분, Header와 Payload의 조합에 비밀 키 사용해 생성
Client/사용자
가 로그인을 시도 → Server
에서 로그인 정보 확인 후, JWT 생성하여 Client
에게 JWT와 같이 응답 → 이후 Client
에서 데이터를 요청할 때, 발급받은 JWT를 헤더에 담아 요청 → Server
에서 받은 요청에서 JWT 검증을 수행한 후, 데이터 응답
npm install jsonwebtoken
→ jsonwebtoken 모듈 설치
import jwt from 'jsonwebtoken';
const SECRETKEY = 'abcdefghijklmnopqrstuvwxyz1234567890';
//토큰 생성
jwt.sign({ id : userid }, SECRETKEY);
//sign(payload, secretOrPrivateKey, [options, callback])
//토큰 검증
//1. 헤더에서 토큰값 추출
const auth = req.headers.authorization;
const token = auth.split(' ')[1];
//2. JWT 검증
jwt.verify(token, SECRETKEY, (err, encoded)=> {
...
});
// verify(token, secretOrPrivateKey, [options, callback]);
암호화
Key
- 매핑 전 원래 데이터 값, Value
- 매핑 후 데이터값SHA-256
, SHA-512
사용AES
AES-128
, AES-192
, AES-256
RSA
, ECC
Node에서의 암호화 모듈 (1) - CryptoJS
import crypto from 'crypto';
const createHashedPassword = (password) => {
// 알고리즘 암호화할 값 인코딩 방식
return crypto.createHash(algorithm).update(password).digest(encoding);
}
const salt = crypto.randomBytes(16).toString('base64'); //솔트값
const iterations = 10000; //반복 횟수
const keylen = 64; //생성할 키 길이
const digest = 'sha512'; //알고리즘
//비밀번호 기반 키 도출함수
const createPbkdf = (password) => {
return crypto.pbkdf2Sync(password, salt, iterations, keylen, digest).toString('base64');
};
//검증
const verifyPassword = (password, salt, dbPassword) => {
const compare = crypto.pbkdf2Sync(password, salt, iterations, keylen, digest).toString('base64');
if(compare === dpPassword) return true;
return false;
};
createHash(algorithm)
- 해시알고리즘 사용해 해시 객체 생성
pdkdf2Sync(pw, salt, iterations, keylen, digest)
- 비밀번호 기반 키 도출 함수 동기적 실행
const algorithm = 'aes-256-cbc';
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16); //초기화 벡터
const cipherEncrypt = (word) => {
const cipher = crypto.createCipheriv(algorithm, key, iv); //암호화 객체 생성
let encryptedData = cipher.update(word, 'utf-8', 'base64'); //암호화할 데이터 처리
console.log('cipher.update : ' , encryptedData);
encryptedData += cipher.final('base64'); //최종결과 생성
console.log('cipher.final : ' , encryptedData);
return encryptedData;
};
const decipher = (encryptedData) => {
const decipher = crypto.createDecipheriv(algorithm, key, iv); //복호화 객체 생성
let decryptedData = decipher.update(encryptedData, 'base64', 'utf-8');
decryptedData += decipher.final('utf-8');
return decryptedData;
}
createCipheriv(algorithm, key, iv)
, createDecipheriv(algorithm, key, iv)
- cryptoJS에서 대칭키 암호화, 복호화 위한 객체 생성
Node에서의 암호화 모듈 (2) - Bcrypt
import bcrypt from 'bcrypt';
const salt = 10; //암호화 사용할 솔트값 정의
//암호화
const bcryptPassword = (password) => {
return bcrypt.hashSync(password, salt);
};
//암호화값과 비교
const comparePassword = (password, dbPassword) => {
return bcrypt.compareSync(password, dbPassword);
};