본문 바로가기

Web

암호화와 보안: 데이터 보호의 첫걸음

암호화와 보안

1. 왜 암호화가 중요한가?

오늘날의 디지털 세상에서 데이터는 언제나 해킹 위험에 노출되어 있습니다. 특히, 사용자의 비밀번호와 같은 민감한 데이터가 데이터베이스에 평문으로 저장된다면, 해킹 시 치명적인 정보 유출이 발생할 수 있습니다. 이를 방지하기 위해 **암호화(Encryption)**와 **해시(Hashing)**가 사용됩니다.

 

2. 해시(Hashing)란 무엇인가?

**해싱(Hashing)**은 데이터의 무결성을 확인하거나 비밀번호를 안전하게 저장하는 데 사용됩니다.

 

해싱의 특징

  1. 단방향: 해시 함수는 원본 데이터를 복원할 수 없습니다.
  2. 고정된 출력값: 입력 데이터 크기에 관계없이 고정된 크기의 해시 값을 생성합니다.
  3. 충돌 가능성: 서로 다른 데이터가 동일한 해시 값을 생성할 수도 있습니다(충돌).
  4. 민감도: 입력 데이터가 조금이라도 바뀌면 해시 값이 완전히 달라집니다.

해시 함수의 사용 예시

  • 비밀번호 저장: 데이터베이스에 비밀번호를 저장할 때, 원본 대신 해시 값을 저장합니다. 이렇게 하면 데이터베이스가 해킹되더라도 해시 값을 복원해 원본 비밀번호를 알 수 없습니다.
  • 데이터 무결성 검증: 파일이 손상되거나 변경되지 않았는지 확인할 때 사용됩니다.

해시 알고리즘의 종류

  • MD5: 빠르지만 보안 취약점으로 인해 잘 사용되지 않음
  • SHA-1: 더 나은 보안성을 제공하지만, 충돌 문제가 있어 사용이 줄어듦
  • SHA-256: 현재 가장 널리 사용되며 높은 보안성을 제공

3. 비밀번호 저장과 해싱의 실제 사례

비밀번호 저장 시, 단순 해싱은 보안상 위험할 수 있습니다. 이를 보완하기 위해 **솔트(Salt)**와 반복 해싱을 사용합니다.

  • 솔트(Salt): 고유한 임의 값을 비밀번호에 추가해 동일한 비밀번호라도 서로 다른 해시 값을 생성하도록 합니다.
  • 반복 해싱: 해시 함수를 반복 적용해 해시 충돌 가능성을 줄이고, 무차별 대입 공격(Brute Force Attack)을 방어합니다.

Node.js 예제

const bcrypt = require("bcrypt");

// 비밀번호 해싱
const saltRounds = 10;
const plainPassword = "mypassword";

bcrypt.hash(plainPassword, saltRounds, (err, hash) => {
  console.log("Hashed Password:", hash);
});

// 비밀번호 검증
bcrypt.compare("mypassword", hash, (err, result) => {
  console.log("Password Match:", result); // true or false
});

 

JWT(Json Web Token): 인증의 새로운 표준

1. JWT란?

**JWT(Json Web Token)**는 사용자 인증과 정보 전달을 위해 사용되는 JSON 기반의 토큰입니다. 서버가 클라이언트에 인증 정보를 안전하게 전달하고, 클라이언트는 이 정보를 바탕으로 서버와 상호작용할 수 있습니다.

 

2. JWT의 구조

JWT는 점을 기준으로 3개의 부분으로 나뉜다. ex) dfjdk321fe.w1wdct.fb4bd

 

Header: 토큰의 타입(JWT)과 해싱 알고리즘 정보를 포함

{
  "alg": "HS256",
  "typ": "JWT"
}

 

Payload: 사용자 정보와 같은 데이터가 포함됩니다.

{
  "userId": 123,
  "username": "john_doe",
  "exp": 1672531200
}

 

Signature: Header와 Payload를 비밀 키로 서명한 값.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywidXNlcm5hbWUiOiJqb2huX2RvZSIsImV4cCI6MTY3MjUzMTIwMH0.jVL1nXZlQzU1hRh5ktF6kRZm1l6GvP6m5L3-w0Sh4Fg

 

 

3. JWT의 사용 흐름

  1. 로그인 요청: 사용자가 ID/비밀번호를 입력해 서버에 로그인 요청.
  2. 토큰 발급: 서버는 사용자 인증 후 JWT를 발급해 클라이언트에 전달.
  3. 토큰 저장: 클라이언트는 JWT를 브라우저의 쿠키나 로컬 스토리지에 저장.
  4. 인증 요청: 클라이언트가 서버로 요청을 보낼 때 JWT를 포함.
  5. 토큰 검증: 서버는 JWT의 서명과 유효기간을 검증해 요청을 처리

4. JWT와 암호화의 관계

  • JWT 자체는 암호화된 데이터가 아닙니다.
  • 대신, 토큰의 무결성을 확인하기 위해 **서명(Signature)**을 사용합니다.
  • 민감한 정보를 포함해야 할 경우, 별도의 **암호화(Encryption)**를 적용해야 합니다.

5. JWT 예제

Node.js로 JWT 생성 및 검증

const jwt = require("jsonwebtoken");

const secretKey = "mysecretkey";

// JWT 생성
const token = jwt.sign({ userId: 123, username: "john_doe" }, secretKey, {
  expiresIn: "1h"
});
console.log("Generated Token:", token);

// JWT 검증
try {
  const decoded = jwt.verify(token, secretKey);
  console.log("Decoded Token:", decoded);
} catch (err) {
  console.error("Token Verification Failed:", err.message);
}

 

 

해싱은 비밀번호와 데이터 무결성을 보호하는 데 사용되며, 데이터베이스 보안을 강화합니다. JWT는 인증 시스템에서 세션 관리 없이 사용자 정보를 안전하게 전달할 수 있는 강력한 도구입니다. 이 두 가지는 독립적으로 사용되지만, 함께 사용하면 더욱 안전하고 유연한 인증 시스템을 구축할 수 있습니다. 

 

JWT는 암호화된 데이터가 아니라 서명된 데이터로 Payload에 저장된 데이터는 누구나 읽을 수 있으므로 비밀번호나 민감한 정보는 JWT에 절대 저장하지 않습니다.

 

Salt

1. Salt란?

  • Salt는 비밀번호를 해싱(Hashing)할 때 보안을 강화하기 위해 사용되는 고유한 랜덤 값입니다.
  • 동일한 비밀번호라도 Salt 값이 다르면 서로 다른 해시 결과를 생성합니다.

2. Salt의 특징

  1. 비밀번호 해싱에 사용:
    • 비밀번호를 해싱하기 전에 Salt를 추가하여 Rainbow Table Attack(무작위 대입 공격)을 방지합니다.
  2. DB에 저장:
    • Salt 값은 비밀번호 해시와 함께 데이터베이스에 저장됩니다.
    • 서버가 비밀번호를 검증할 때 사용됩니다.
  3. 단방향 암호화:
    • Salt를 사용한 해싱은 단방향 암호화이므로 복호화가 불가능합니다.

3. Salt 사용 흐름

  1. 사용자가 회원가입 시 비밀번호를 입력.
  2. 서버는 랜덤하게 생성된 Salt를 비밀번호에 추가하여 해싱.
  3. 해싱된 비밀번호와 Salt 값을 데이터베이스에 저장.
  4. 사용자가 로그인 시 비밀번호를 입력하면, 저장된 Salt 값을 사용해 다시 해싱 후 비교.

Salt 예제

const bcrypt = require('bcrypt');

// 비밀번호 해싱
const saltRounds = 10;
const password = "mypassword";

const hashedPassword = bcrypt.hashSync(password, saltRounds);
console.log("Hashed Password:", hashedPassword);

// 비밀번호 검증
const isMatch = bcrypt.compareSync("mypassword", hashedPassword);
console.log("Password Match:", isMatch); // true

 

JWT와 Salt의 차이

특징 JWT Salt
주된 목적 인증 정보 저장 및 전송 비밀번호 보안 강화
구성 요소 Header, Payload, Signature 고유한 랜덤 문자열
사용 목적 클라이언트-서버 간 인증 정보를 전달 비밀번호 해싱에 추가
저장 위치 클라이언트(쿠키 또는 로컬 스토리지) 서버(DB에서 해시와 함께 저장)
보안 방식 토큰 서명을 통해 무결성 확인 해시 결과를 고유화
복호화 가능 여부 복호화 불가능(하지만 Payload는 누구나 읽을 수 있음) 복호화 불가능
사용 사례 인증 및 권한 관리 비밀번호 저장

 

  • Salt: 비밀번호를 안전하게 저장하기 위해 사용하며, 비밀번호를 해싱할 때 추가되는 값.
  • JWT: 인증과 권한 관리를 위해 사용되며, 클라이언트와 서버 간 상태를 유지하지 않는 인증 방식.
  • Salt는 서버에서 저장되고 검증 과정에서만 사용되며, JWT는 클라이언트에 저장되어 서버와의 요청에 사용됩니다.

'Web' 카테고리의 다른 글

JavaScript 자료 구조와 메모리 관리  (3) 2024.11.15
CSS - Flex Box로 레이아웃 디자인하기  (0) 2024.11.04
웹 표준과 웹 접근성이란?  (8) 2024.10.29