비밀번호 생성 및 검증 도구

강력한 비밀번호와 암호 문구를 생성하고, 일괄 생성, 고유성, 강도 및 정책 검증을 지원하며, 다국어 코드 예제와 실용적인 지식을 제공합니다.

비밀번호 생성기

개수
기호 그룹 선택
팁: 그룹을 선택하거나 직접 문자를 클릭하여 제외할 수 있습니다.
결과

비밀번호 정책 테스터

결과
  • 길이
  • 소문자
  • 대문자
  • 숫자
  • 기호
  • 연속 시퀀스
  • 반복
  • 차단 목록
모든 검사는 귀하의 브라우저에서 로컬로 수행됩니다.

암호구 생성기

단어는 안전한 무작위 생성(Web Crypto)을 사용하여 선택됩니다. 예시 단어 목록은 파일 크기 제한으로 짧습니다.

비밀번호 해시 빠른 참조 가이드

Argon2id
  • Argon2id를 사용하고 적절한 메모리 비용 파라미터를 설정하세요
  • 반복 횟수 ≥ 2회, 메모리 ≥ 64MB (환경에 따라 조정)
  • 사용자별로 독립적인 솔트를 저장; 애플리케이션 레이어에서 페퍼 사용을 고려하세요
PBKDF2
  • SHA-256 또는 SHA-512를 선택하고 반복 횟수 ≥ 210,000회 (필요에 따라 조정)
  • 각 해시에 고유한 솔트를 사용; 파라미터 업그레이드를 지원하세요
  • 다음 로그인 시 더 높은 비용 파라미터로 전환하세요
BCrypt
  • 비용 값 10–14, 서버 성능에 맞게 조정
  • 비밀번호 자르기 문제를 피하고 전체 비밀번호를 해싱하세요
  • 인증 엔드포인트에 요청 제한 및 모니터링을 적용하세요
참조: NIST SP 800-63B, OWASP ASVS. 파라미터는 하드웨어 성능과 SLO와 일치해야 합니다.

비밀번호 강도 평가

강도는 엔트로피를 기반으로 추정됩니다: entropy = log2(문자 집합 크기) × 길이. 더 큰 문자 집합과 더 긴 길이는 추측 저항성을 높입니다.

  • 약함: < 50 비트 —— 일회성 또는 저가치 시나리오에만 적합
  • 보통: 50–80 비트 —— 낮은 위험 환경에서 허용 가능
  • 강함: 80–110 비트 —— 권장 기본 목표
  • 매우 강함: > 110 비트 —— 관리자 또는 핵심 계정에 적합

참고: 실제 공격 모델은 차이가 있을 수 있습니다. 비밀번호 재사용을 피하고 다중 요소 인증(MFA)을 활성화하세요.

사용 방법

  • 길이와 문자 집합(소문자/대문자/숫자/기호)을 선택하세요. 필요 시 '유사 문자 제외' 및 '각 항목 필수 포함'을 활성화하세요.
  • 더 세밀한 제어가 필요할 경우: 특정 문자 또는 문자 그룹을 제외하거나 기호 그룹을 선택하세요.
  • 생성 버튼을 클릭하세요. 여러 결과가 필요하면 일괄 생성을 활성화하고 한 번에 모두 복사할 수 있습니다.
  • 기존 비밀번호를 검증하려면 '정책 테스터'를, 기억하기 쉬운 암호 문구를 원하면 '암호 문구 생성기'를 사용하세요.

기능 특징

  • 보안 무작위 소스(Web Crypto)
  • 설정 가능한 문자 집합 및 기호 그룹
  • 유사 문자 필터링 및 사용자 정의 제외
  • 일괄 생성, 고유성 보장 및 중복 제거 통계
  • 강도 및 엔트로피 지표
  • 정책 테스터 및 암호 문구 생성기
  • 다국어 코드 예제 (JS、Python、PHP、Go、Java、C#、Rust)
  • 한 번에 복사 (단일/모두)

비밀번호 생성 예시

강력함 (Strong)
길이 24, 대소문자/숫자/기호 포함
기억하기 쉬움 (Memorable)
길이 16, 대소문자/숫자 포함, 유사 문자 제외

비밀번호 지식 기반

1) 비밀번호 강도와 엔트로피
  • 엔트로피 ≈ log2(문자 집합 크기) × 길이; 길이가 더 큰 영향을 미칩니다
  • 목표 권장값: 일반 계정 ≥ 80비트; 고권한/금융 계정 ≥ 110비트
  • 더 큰 문자 집합 + 더 긴 길이 → 추측 저항성 향상
2) 길이 대 복잡도
  • 기호를 무분별하게 추가하는 것보다 길이를 늘리는 것이 더 효과적입니다
  • 예측 가능한 패턴을 피하세요 (예: 항상 ‘첫 글자 대문자 + 끝에 숫자!’)
  • 충분한 길이를 확보한 후, 문자 다양성을 적절히 높이는 것이 좋습니다
3) 흔한 오류 및 역패턴
  • 키보드 시퀀스(qwerty), 반복 구간, 생일/연도 등은 규칙 기반 공격에 쉽게 노출됩니다
  • ‘기본 비밀번호 + 웹사이트 접미사’ 방식은 변형 재사용으로, 위험이 집중되고 예측하기 쉽습니다
  • 여러 사이트에서 동일한 비밀번호를 사용하지 마세요
4) 비밀번호 관리 권장사항
  • 비밀번호 관리자를 사용하고, 각 사이트마다 고유한 비밀번호를 설정하며, 중요한 계정에는 MFA를 활성화하세요
  • 공개 채널을 통해 비밀번호를 평문으로 전송하지 마세요. 필요한 경우 발음하기 쉬운 암구를 사용하세요
  • 누설되거나 재사용된 경우 즉시 변경하고, 고유하게 관리하세요
5) 암구(Passphrase) 가이드
  • 4~6개 단어로 구성된 조합은 보통 강력하면서도 기억하기 쉽습니다
  • 구분 기호 혼용, 첫 글자 대문자, 숫자 삽입 등을 통해 강도와 가독성을 동시에 향상시키세요
  • 흔한 문구, 가사, 명언을 그대로 연결하지 마세요

비밀번호 보안 실천 가이드

최선의 실천 방법
  • 충분한 길이를 사용하세요: 일반 계정은 16자 이상, 핵심 계정은 24자 이상을 권장합니다.
  • 기억이 필요한 경우 암호 문구를 우선적으로 사용하고, 무작위 고강도 암호는 암호 관리자를 통해 저장하세요.
  • 가능하면 다중 요소 인증(MFA)을 활성화하세요.
  • 다른 웹사이트에서 비밀번호를 재사용하지 말고, 모든 계정에 고유한 비밀번호를 사용하세요.
엔트로피와 강도

엔트로피는 길이와 문자 집합 크기에 기반한 예측 불가능성을 나타내며, 엔트로피 비트 수가 높을수록 일반적으로 더 강력합니다.

  • 최대 효과를 얻으려면 길이를 늘리는 것을 우선시하세요.
  • 가능한 경우 다양한 문자 집합을 사용하세요.
  • 과도하게 문자를 제외하면 문자 집합이 줄어들어 강도가 낮아집니다.
정책 및 주기적 변경
  • 복잡한 구성 규칙보다는 길이와 일반적/유출된 암호를 차단하는 블랙리스트를 선호하세요.
  • 빈번한 강제 주기적 변경은 피하고, 유출이나 위험이 발생할 때만 변경하세요.
  • 유출된 암호 목록을 사용하여 일반적/유출된 암호를 차단하세요.
암호 문구
  • 4~6개의 무작위 단어를 구분자로 연결하여 사용하세요. 예: lake-CARROT-planet_7
  • 유명한 문장이나 가사 같은 일반적인 문구를 피하세요. '지혜로움'보다 무작위성이 더 중요합니다.
  • 핵심 계정에는 암호 관리자를 사용하여 진정으로 고엔트로피의 무작위 암호를 저장하세요.
생성 설정 팁
  • "선택한 각 세트를 필수로 포함" 옵션은 각 유형이 최소 한 번 이상 포함되도록 보장합니다.
  • "유사한 문자 피하기"는 가독성을 향상시키지만 문자 집합 크기를 약간 줄입니다.
  • 기호는 대상 시스템에서 허용되는 하위 집합으로 제한할 수 있습니다.
서버 측 저장
  • 절대 평문으로 저장하지 마세요. 강력한 해시(Argon2id/PBKDF2/BCrypt)를 사용하고 솔트를 적용하세요.
  • 적절한 매개변수(메모리/시간/비용)를 설정하고 필요시 피퍼를 사용하세요.
  • 속도를 제한하고 실패 시도를 모니터링하세요. 공격이 감지되면 CAPTCHA 또는 장치 검증을 추가하세요.
다중 요소 및 복구
  • TOTP/하드웨어 키를 우선 사용하고, SMS는 가능한 한 피하세요.
  • 복구 프로세스를 보호하세요: 다중 요소 또는 이메일 인증을 사용하고 쿨다운 기간을 설정하세요.
  • 백업 복구 코드를 제공하고 사용자가 안전하게 보관하도록 권장하세요.
브루트 포스 공격 방어
  • 점진적인 지연/잠금 및 IP/장치 리스크 점수를 사용하세요.
  • API 및 로그인 폼에 WAF/요청 제한을 구성하세요.
  • 사용자 계정 정보 유출 시도를 감지하고 고유한 비밀번호 사용을 장려하세요.
로컬 저장 및 처리
  • 신뢰할 수 있는 암호 관리자를 사용하여 저장하고 자동 채우기를 수행하세요.
  • 비밀번호를 채팅이나 이메일로 평문으로 공유하지 마세요. 팀은 비밀 관리 도구를 사용하세요.
  • 오프라인으로 기록해야 하는 경우 물리적 보안을 확보하세요.
공지사항: 이 도구는 브라우저 내부에서 Web Crypto를 사용하여 로컬로 비밀번호를 생성하며, 데이터를 서버로 전송하지 않습니다.

프로그래밍 언어로 비밀번호 생성하는 방법

JavaScript(Web Crypto)
function randomPassword(length = 16, sets = {lower:true, upper:true, digits:true, symbols:true}) {
  const pools = {
    lower: 'abcdefghijklmnopqrstuvwxyz',
    upper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
    digits: '0123456789',
    symbols: '!@#$%^&*+-=_~`|/?()[]{}<>,.;:\'\"'
  };
  let pool = '';
  for (const k of Object.keys(sets)) if (sets[k]) pool += pools[k];
  if (!pool) throw new Error('No charset');
  const bytes = new Uint32Array(length);
  crypto.getRandomValues(bytes);
  let out = '';
  for (let i = 0; i < length; i++) out += pool[bytes[i] % pool.length];
  return out;
}
Python(secrets)
import secrets

def random_password(length=16, lower=True, upper=True, digits=True, symbols=True):
    pools = {
        'lower': 'abcdefghijklmnopqrstuvwxyz',
        'upper': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
        'digits': '0123456789',
        'symbols': '!@#$%^&*+-=_~`|/?()[]{}<>,.;:\'\"'
    }
    pool = ''.join(v for k, v in pools.items() if locals()[k])
    if not pool:
        raise ValueError('No charset')
    return ''.join(secrets.choice(pool) for _ in range(length))
PHP(random_int)
function random_password($length = 16, $sets = ['lower'=>true,'upper'=>true,'digits'=>true,'symbols'=>true]) {
    $pools = [
        'lower' => 'abcdefghijklmnopqrstuvwxyz',
        'upper' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
        'digits' => '0123456789',
        'symbols' => '!@#$%^&*+-=_~`|/?()[]{}<>,.;:\'\"'
    ];
    $pool = '';
    foreach ($sets as $k => $on) if ($on) $pool .= $pools[$k];
    if ($pool === '') throw new Exception('No charset');
    $out = '';
    for ($i = 0; $i < $length; $i++) {
        $out .= $pool[random_int(0, strlen($pool)-1)];
    }
    return $out;
}
Go(crypto/rand)
package main

import (
  "crypto/rand"
  "math/big"
)

func RandomPassword(length int, pool string) (string, error) {
  out := make([]byte, length)
  for i := 0; i < length; i++ {
    nBig, err := rand.Int(rand.Reader, big.NewInt(int64(len(pool))))
    if err != nil { return "", err }
    out[i] = pool[nBig.Int64()]
  }
  return string(out), nil
}
Java(SecureRandom)
import java.security.SecureRandom;

public class Pw {
  static final String POOL = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*+-=_~`|/?()[]{}<>,.;:'\"";
  static final SecureRandom SR = new SecureRandom();
  static String randomPassword(int length) {
    StringBuilder sb = new StringBuilder(length);
    for (int i = 0; i < length; i++) {
      int idx = SR.nextInt(POOL.length());
      sb.append(POOL.charAt(idx));
    }
    return sb.toString();
  }
}
C#(.NET RandomNumberGenerator)
using System;
using System.Security.Cryptography;

public static class Pw {
  public static string RandomPassword(int length, string pool) {
    using var rng = RandomNumberGenerator.Create();
    var bytes = new byte[length];
    rng.GetBytes(bytes);
    var chars = new char[length];
    for (int i = 0; i < length; i++) {
      chars[i] = pool[bytes[i] % pool.Length];
    }
    return new string(chars);
  }
}
Rust(rand + getrandom)
use rand::rngs::OsRng;
use rand::RngCore;

fn random_password(length: usize, pool: &str) -> String {
    let mut bytes = vec![0u8; length];
    OsRng.fill_bytes(&mut bytes);
    let chars: Vec = pool.chars().collect();
    bytes
        .iter()
        .map(|b| chars[(*b as usize) % chars.len()])
        .collect()
}

fn main() {
    let pool = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*+-=_~`|/?()[]{}<>,.;:'\"";
    let pw = random_password(16, pool);
    println!("{}", pw);
}