[Security] bcrypt 정리

🔐 bcrypt란?

bcrypt는 1999년에 Niels ProvosDavid Mazieres가 개발한 암호화 해시 함수로, Blowfish 대칭 키 암호화 알고리즘을 기반으로 만들어졌습니다. 주로 웹 애플리케이션에서 사용자의 비밀번호를 안전하게 저장하기 위해 사용됩니다.

✅ 주요 특징

1. Salt 내장

  • bcrypt는 자동으로 salt를 랜덤 생성하여 포함시킵니다.
  • salt는 같은 비밀번호도 다른 해시 결과를 만들게 하여 무작위성을 증가시키고 레인보우 테이블 공격을 방어합니다.

2. 비용 증가 (Cost factor)

  • cost 또는 work factor는 해시 계산에 걸리는 연산 횟수(또는 시간)를 조절합니다.
  • 예: cost 10이면 2¹⁰ = 1024번의 해시 계산을 수행합니다.
  • 이를 통해 컴퓨터 성능이 높아져도 쉽게 크래킹되지 않도록 시간적 방어 장치를 제공합니다.

3. 느린 연산

  • 빠른 해시 함수(SHA-256 등)는 brute-force 공격에 더 취약한 반면, bcrypt는 의도적으로 느리게 설계되어 공격자를 어렵게 만듭니다.

4. 결과에 버전과 cost 정보 포함

$2b$10$Qcfksu5KwUepA.zVDkkw4Oco0z14Kz2jgfD6sdoGieQfztY1KaIhK
└┬┘└┬┘└─────── Salt ────────┘└─────── Hashed result ───────┘
 │  │
 │  └── Cost factor (2의 10제곱 = 1024번 해싱)
 └────── 버전 (2a, 2b, 2y 등)
  • 2b → bcrypt 알고리즘 버전
  • 10 → cost factor (해시 반복 횟수 조절)
  • 그 뒤 22자 → salt (Qcfksu5KwUepA.zVDkkw4O)
  • 나머지 → 실제 해시된 비밀번호

⚠️ 주의할 점

  • bcrypt는 암호화(encryption)가 아닌 해싱(hash)입니다. 즉, 원래 값을 복호화할 수 없습니다.
  • 사용자가 로그인할 때는 입력된 비밀번호를 같은 방식으로 해시하고, 저장된 해시와 비교(compare)하여 확인합니다.
  • 비밀번호가 노출되었을 경우, 단방향이기 때문에 해시만으로는 원래 값을 알 수 없습니다.

💻 Mac에서 간단히 CLI로 해시를 생성하는 방법

🔹 Homebrew로 bcrypt 설치

brew install bcrypt

🔹 비밀번호 해싱

echo "yourPasswordHere" | bcrypt
  • 예시 출력:
$2a$06$D9f2gKT8iJ1Lg/YhH9QpneCn7vD0Qx7xDdwU5k7AlhOPKfMyVPMta

💻 node.js 예제 코드

🔹 프로젝트 폴더 생성 후 bcrypt 설치

mkdir bcrypt-demo && cd bcrypt-demo
npm init -y
npm install bcrypt

✅ bcrypt-hash.js: 해시 생성 코드

const bcrypt = require('bcrypt');

// 커맨드라인에서 입력받은 비밀번호
const [,, password] = process.argv;

// 유효성 검사
if (!password) {
  console.error("❗ 사용법: node bcrypt-hash.js <비밀번호>");
  process.exit(1);
}

const saltRounds = 10; // 기본 비용 계수 (2^10 = 1024번 해시 반복)

// 해시 생성
bcrypt.hash(password, saltRounds, (err, hash) => {
  if (err) {
    console.error("❌ 에러:", err.message);
    process.exit(1);
  }

  console.log("🔐 bcrypt 해시 결과:");
  console.log(hash);
});

✅ 사용 방법

테스트 예시:

node bcrypt-hash.js mySecretPassword

✅ bcrypt-test.js: 해시 검증 코드

const bcrypt = require('bcrypt');

// 커맨드라인 인자 받아오기
const [,, inputPassword, hashedPassword] = process.argv;

// 유효성 검사
if (!inputPassword || !hashedPassword) {
  console.error("❗ 사용법: node bcrypt-test.js <암호> <해시>");
  process.exit(1);
}

// 비밀번호 검증
bcrypt.compare(inputPassword, hashedPassword, (err, result) => {
  if (err) {
    console.error("❌ 에러 발생:", err.message);
    process.exit(1);
  }

  if (result) {
    console.log("✅ 비밀번호가 일치합니다!");
  } else {
    console.log("❌ 비밀번호가 일치하지 않습니다.");
  }
});

✅ 사용 방법

테스트 예시:

node bcrypt-test.js mySecretPassword '$2b$10$WnV2Kk1aR8...'

[VPN] FortiGate 장비와 MacOS 사이의 IPSec 터널 설정

FortiGate 설정

IPSec Tunnels 생성

Network

  • Remote Gateway: “Dialup User”, Interface: “wan1″(공인 IP가 연결된 WAN 포트)
  • Local Gateway: Disable
  • Mode Config: Disable
  • NAT Traversal: Enable
  • Dead Peer Detection: On Idle
  • Add route: Disable
  • Auto discovery sender / receiver: Disable
  • Device creation: Enabled
  • Tunnel search: Selectors

Authentication

  • Method: Pre-shared Key
  • Pre-shared Key: 정한 PSK를 적는다. 아래 MacOS 설정의 ipsec.secrets 와 당연히 동일(e.g. mySecretKey)해야 한다.
  • IKE Version: 1
  • IKE Mode Main(ID protection)
  • Peer Options: Accept Types는 Specific peer ID로 하고 Peer ID로 아래 ipsec.confleftid와 동일(e.g. dasomoli.org)해야 한다.

Phase 1 Proposal

  • Encryption: AES256
  • Integrity: SHA256
  • DH Group: 14
  • Key Lifetime (seconds): 86400

XAUTH

  • Type: Disabled

Phase 2 Selectors

  • Subnet1
    • Local Address: 192.168.64.0/19 (192.168.64.0/255.255.224.0)
    • RemoteAddress: 192.168.0.0/24 (192.168.0.0/255.255.255.0)
    • Encryption: AES256, Integrity: SHA256, DH Group: 14
    • Enable Replay Detection: Enabled
    • Enable Perfect Forward Secrecy (PFS): Enabled
    • Local Port/Remote Port/Protocol: Enabled
    • Key Lifetime: 3600
  • Subnet2
    • Local Address: 10.30.0.0/16 (10.30.0.0/255.255.0.0)
    • RemoteAddress: 192.168.0.0/24 (192.168.0.0/255.255.255.0)
    • Encryption: AES256, Integrity: SHA256, DH Group: 14
    • Enable Replay Detection: Enabled
    • Enable Perfect Forward Secrecy (PFS): Enabled
    • Local Port/Remote Port/Protocol: Enabled
    • Key Lifetime: 3600

Log 확인

FortiGate CLI에서 확인

diagnose vpn ike gateway list

또는:

diagnose vpn tunnel list

그 외.

  • Static Routes에 터널 연결된 PC로의 routing이 추가되어야 한다.
  • Firewall Policy가 추가된 IPSec 터널을 위한 인터페이스에 incoming/outgoing 모두 허용되어야 한다.
    • NAT는 이 경우 Disable하여야 한다.

MacOS 설정

1. 사전 준비

1.1. strongswan 설치

strongswan 을 설치한다.

brew install strongswan

2. 설정 파일 작성

/opt/homebrew/etc/ipsec.conf 설정 파일을 작성한다.

  • left: 내 Mac
  • right: FortiGate의 공인 IP
  • leftid, rightid: FortiGate와 일치해야 함
  • leftsubnet: 집 네트워크
  • rightsubnet: FortiGate 내부 네트워크
  • ike나 esp의 aes256-sha256-modp2048 는 Encryption: AES256, Integrity: SHA256, DH Group: 14를 의미한다. 느낌표(!)는 강제 적용을 의미한다.
config setup
    charondebug="ike 2, knl 2, cfg 2, net 2, esp 2"

conn fortigate
    keyexchange=ikev1
    aggressive=no
    authby=psk
    forceencaps=yes
    installpolicy=yes
    type=tunnel
    left=%defaultroute
    leftid=@dasomoli.org
    right=11.13.3.1
    rightid=11.13.3.1
    leftsubnet=192.168.0.0/24
    rightsubnet=192.168.64.0/19,10.30.0.0/16
    leftupdown=/opt/homebrew/etc/ipsec-updown.sh
    ike=aes256-sha256-modp2048!
    esp=aes256-sha256-modp2048!
    ikelifetime=86400s
    lifetime=3600s
    dpdaction=restart
    auto=start

설정 파일에서 사용하는 /opt/homebrew/etc/ipsec-updown.sh 를 작성한다. 이는 strongSwan은 macOS에서 커널 라우팅 테이블에 자동으로 라우트를 추가하지 않기 때문이다. 이는 macOS 커널이 PF_ROUTE를 통해 정책 기반 라우팅을 제공하지 않기 때문이다. 따라서 updown 스크립트를 활용해 수동 라우팅을 추가한다.

#!/bin/sh
case "$PLUTO_VERB" in
    up-client)
        /sbin/route add -net 10.30.0.0/16 -interface $PLUTO_INTERFACE
        /sbin/route add -net 192.168.64.0/19 -interface $PLUTO_INTERFACE
        ;;
    down-client)
        /sbin/route delete -net 10.30.0.0/16
        /sbin/route delete -net 192.168.64.0/19
        ;;
esac

PSK를 /opt/homebrew/etc/ipsec.secrets 파일 안에 다음과 같이 넣는다.

@dasomoli.org @fortigate : PSK "mySecretKey"

3. 실행 방법

macOS에서는 시스템 서비스로 실행되지 않기 때문에, 수동으로 아래와 같이 실행한다.

sudo ipsec start

또는

sudo ipsec down fortigate
sudo ipsec up fortigate

로그 확인:

log show --predicate 'process == "charon"' --info --last 5m

연결 확인:

ipsec statusall

종료:

sudo ipsec stop

라우팅 확인:

route -n get 10.30.0.1

혹은:

netstat -rn | grep 10.

[Mac] Dock에 앱 관련 아이콘 추가

Launchpad 추가

기본으로 Dock에 Launchpad 아이콘은 추가되어 있다. 없앴을 때 복구하고 싶다면 다음과 같이 한다.

  1. “Finder” 실행
  2. 왼쪽 바의 “응용 프로그램”에서 우클릭 후 “Dock에 추가”

“응용 프로그램” 추가

아래처럼 “응용 프로그램” 전체를 볼 수 있는 아이콘을 추가한다.

  1. “Finder” 실행
  2. 왼쪽 바의 “위치”에서 “XXX의 MacBook Pro” / “Macintosh HD”
  3. “응용 프로그램”을 끌어다 Dock에 갖다 놓기

[Mac] Windows manager Rectangle쓰기

기존에 Windows manager로 Veer를 쓰다가 Rectangle이 더 나은 것 같아 갈아탔다. 설치는 Rectangle 사이트(https://rectangleapp.com/)에서 다운로드 받아 설치하면 된다.

내 Rectangle 설정 (32:9 모니터 기준)
내 Rectangle 설정 (32:9 모니터 기준)

나같은 경우는 아래 절반, 위 절반을 사용하지 않기 때문에 둘 모두 없앴다. 대신 높이 최대화를 Ctrl + Option + 위, 가운데 절반을 Ctrl + Option + 아래로 설정했다.

32:9 울트라 와이드 모니터의 경우 Ctrl + Option + D, F, G가 유용할 것 같다. Ctrl + Option + D만 눌러도 1/3씩 토글되면서 움직인다.

왼쪽 위, 오른쪽 위, 왼쪽 아래, 오른쪽 아래도 사용하지 않을 것 같아서 1/4 쪽으로 U, I, J, K도 바꿨다. 역시 Ctrl + Option + U만 눌러도 1/4씩 토글되면서 움직인다.

창 복원은 항상 Ctrl + Option + BackSpace 이다.