[SeSACX코딩온] JWT, 암호화

JUHEE·2024년 2월 25일
0

SeSACX코딩온

목록 보기
13/26

JWT

- Json Web Token
- OAuth(Open Autorization): 서드파티 어플리케이션이 사용자의 계정에 접근한 수 있는 권한을 부여하기 위한 프로토콜
- OAuth2.0: JWT Bearer Token인증방식을 지원, 클라이언트가 발급받은 JWT를 Autorization 헤더에 담아 요청을 보내면, 서버는 해당 JWT의 유효성을 검사하여 권한을 부여한다

JWT구성

- Header, Payload, Signature
- 클라이언트에서 요청하면 서버에서 생성과 검증과정을 가짐
- jwt.sign(payload, secretOrPrivateKey,[option]) 생성
- jwt.verify(token, secretOrPrivateKey,[option]) 유효성검증

JWT사용

- npm install jsonwebtoken 모듈 다운로드
- const jwt = require("jsonwebtoken"); 모듈 require
- 생성코드(sign)

const jwt = require("jsonwebtoken");
const SECRET = "DWB0jOga2jrAozUXUsLCQ1e4EeeQH8"; //랜덤문자열 사용

//req, res함수 안 코드
const token = jwt.sign({ id }, SECRET);
res.send({ result: true, token });

//view의 js에서 send데이터 성공시 localStorage작업 진행
localStorage.setItem("login", token);

- 검증코드(verify)

//view의 js에서 header에 토큰 정보 전송
const token = localStorage.getItem("login");

const response = await axios({
  method: "post",
  url: "/token",
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

//app.js코드
if (req.headers.authorization) {
  //인증정보 들어왔을 때
  const token = req.headers.authorization.split(" ")[1];
  //Bearer와 뒤의 토큰을 분리(띄어쓰기 기준), [0] = Bearer, [1] = 토큰만 저장
  try {
    const auth = jwt.verify(token, SECRET);
    //auth는 payload와 iat(issued at, 발급시간)정보 가짐(배열)
    if (userInfo.id === auth.id) {
      //payload값을 비교하여 유효성 검증
      res.send({ result: true, name: userInfo.name });
    }
  } catch(e) {
  //오류발생시 코드작성
  }
}

암호화

- 단방향 암호화: 패스워드 저장 등에 활용, 원본 데이터 복원이 불가능, 주로 해시 함수를 사용하여 구현
- 양방향 암호화: 데이터 기밀성 유지 및 안전한 통신을 위해 사용
1) 대칭키 알고리즘: 암호화,복호화에 동일키 사용
2) 공개키 알고리즘: 공개키, 개인키 쌍을 각각 암호화, 복호화에 사용

Crypto - 단방향

createHash

- js에서 기본적으로 제공되는 모듈 crypto를 사용한다
- createHash(알고리즘).update(암호화할 값).digest(인코딩방식)으로 암호화
- hash값을 DB에 저장하고, 로그인시 암호화를 진행하여 값을 비교하면 로그인 검사를 할 수 있다

const crypto = require("crypto");

const createHashPw = (pw) => {
  return crypto.createHash("sha512").update(pw).digest("base64");
};

console.log("1st hasing", createHashPw("1234"));
console.log("2nd hasing", createHashPw("1234"));
console.log("3rd hasing", createHashPw("1234")); //전부다 똑같은 값 출력

pdkdf2Sync

- salt와 hash값을 DB에 저장해두어야한다
- 같은 입력값이라도 salt값에 따라 해시값이 달라진다
- pdkdf2Sync(암호화할값, 솔트, 반복횟수, 키길이, 알고리즘).toString("base64");을 통해 암호화 한다
- toString을 하지 않으면 buffer값을 가지기 때문에 꼭 문자열로 바꾸는 toString을 진행해야한다
- salt값은 randomBytes()를 통해 무작위로 설정한 후 DB에 저장한다
- 암호화 작업 함수 작성 코드

function saltAndHashPw(pw) {
  const salt = crypto.randomBytes(16).toString("base64");
  const iterations = 100; //반복횟수
  const keylen = 64; //생성할 키의 길이
  const algorithm = "sha512";

  //pdkdf2Sync(암호화할값, 솔트, 반복횟수, 키길이, 알고리즘)
  const hash = crypto
    .pbkdf2Sync(pw, salt, iterations, keylen, algorithm).toString("base64"); //buffer to String

  return { hash, salt }; //{ hash: hash, salt: salt }
}

console.log("1st hashing", saltAndHashPw("1234"));
console.log("2nd hashing", saltAndHashPw("1234"));```
코드를 입력하세요

//랜덤 salt로 인해 다른 값이 나온다

//로그인 작업 시
const hash = crypto
.pbkdf2Sync(inputPw, savedSalt, iterations, keylen, algorithm).toString("base64");
//저장해둔 salt와 동일한 설정으로 해시하여 DB에 저장된 값을 비교한다


### Crypto - 양방향
\- 암호화 객체를 만들고 이를 통해 암호화 한다
\- 암호화객체: crypto.createCipheriv(알고리즘, 키, iv)사용
\- 키와 iv는 buffer데이터로 랜덤값 생성하여 사용
\- 데이터 암호화: 암호화객체.update(암호화할 데이터, 입력인코딩, 출력인코딩);
\- 암호화객체.final(출력인코딩)메소드로 최종결과 생성
\- 암호화 코드
```js
//algorithm, key, iv는 미리 변수로 선언한 상태라고 가정
function encrypt(text) {
  const cipher = crypto.createCipheriv(algorithm, key, iv);
  let encrypted = cipher.update(text, "utf8", "base64");
  encrypted += cipher.final("base64");
  return encrypted;
}

- 복호화: createDecipheriv()사용
- 암호화 역으로 진행
- 복호화 코드

function decrypt(encryptedText) {
  const decipher = crypto.createDecipheriv(algorithm, key, iv);
  let decrypted = decipher.update(encryptedText, "base64", "utf8"); //입력인코딩과 출력인코딩이 반대로 변경된다
  decrypted += decipher.final("utf8");
  return decrypted;
}

Bcrypt

- npm install bcrypt를 통해 모듈 설치가 필요
- require하여 bcrypt선언해준다
- salt의 라운드 수를 설정하고 값을 넣어줘야한다(클수록 안전 but 성능저하)
- 강한 보안이 필요한 경우 주로 사용된다
- 해시값 생성: hashSync(비밀번호, saltRound) -> 암호화된 문자열을 반환 한다
- 해시값 비교: compareSync(원본비밀번호, 해시된 비밀번호) -> true or false값을 반환한다
- 실행코드

const bcrypt = require("bcrypt");
const saltRounds = 10;

function hashPw(pw) {
  return bcrypt.hashSync(pw, saltRounds);
}

function comparePw(inputPw, hashedPw) {
  return bcrypt.compareSync(inputPw, hashedPw);
}
// 두 함수를 사용하여 비밀번호 값을 비교하는데 사용하면 로그인 작업이 가능하다
profile
초보개발자

0개의 댓글