보안초급📖 9분 읽기📅 2025-07-31

안전한 비밀번호 관리 완벽 가이드

개인부터 기업까지, 해킹으로부터 안전한 비밀번호 생성 및 관리 전략

#보안#비밀번호#해킹방지#2FA

안전한 비밀번호 관리 완벽 가이드

개인정보 유출과 해킹 사고가 일상화된 시대, 강력한 비밀번호는 디지털 보안의 첫 번째 방어선입니다. 올바른 비밀번호 생성과 관리 전략으로 개인과 기업의 디지털 자산을 보호할 수 있습니다.

1. 비밀번호 보안의 중요성 {#password-basics}

현재 위협 환경

사이버 공격 통계 (2024년 기준)

const cybersecurityStats = {
  // 전 세계 데이터 유출 현황
  globalBreaches: {
    annualIncidents: 3200,
    exposedRecords: '45억 건',
    averageCostPerBreach: '$4.45M',
    identityTheftCases: '143만 건'
  },
  
  // 비밀번호 관련 보안 사고
  passwordAttacks: {
    credentialStuffing: '61% 증가', // 기존 유출된 계정으로 다른 서비스 공격
    bruteForceAttacks: '28% 증가',
    passwordSpraying: '34% 증가', // 여러 계정에 흔한 비밀번호 시도
    phishingSuccess: '12% 성공률'
  },
  
  // 일반적인 비밀번호 취약점
  commonVulnerabilities: {
    reusedPasswords: '65%의 사용자', // 같은 비밀번호 재사용
    weakPasswords: '23%의 계정',   // 취약한 비밀번호 사용
    noMFA: '78%의 개인 계정',      // 2단계 인증 미사용
    storedInBrowser: '51%의 사용자' // 브라우저에 비밀번호 저장
  }
};

해킹 방법과 대응

const attackMethods = {
  // 1. 사전 공격 (Dictionary Attack)
  dictionaryAttack: {
    description: '일반적인 비밀번호 목록을 사용한 공격',
    commonTargets: ['password', '123456', 'admin', 'qwerty'],
    prevention: '복잡하고 예측 불가능한 비밀번호 사용',
    timeToBreak: '몇 초 ~ 몇 분'
  },
  
  // 2. 무차별 대입 공격 (Brute Force)
  bruteForceAttack: {
    description: '모든 가능한 조합을 시도하는 공격',
    computingPower: '1초당 10억 회 시도 가능 (GPU 사용 시)',
    prevention: '길고 복잡한 비밀번호 + 계정 잠금 정책',
    timeToBreak: {
      '8자리 숫자': '2.5시간',
      '8자리 영문+숫자': '22일',
      '12자리 영문+숫자+특수문자': '34,000년'
    }
  },
  
  // 3. 레인보우 테이블 공격
  rainbowTableAttack: {
    description: '미리 계산된 해시 테이블을 이용한 공격',
    target: '해시화된 비밀번호 데이터베이스',
    prevention: '솔트(Salt) 사용 + 강력한 해시 함수',
    effectiveness: '일반적인 비밀번호 99% 크랙 가능'
  },
  
  // 4. 사회공학적 공격
  socialEngineering: {
    description: '개인 정보를 이용한 비밀번호 추측',
    commonSources: ['생년월일', '이름', '전화번호', '애완동물 이름'],
    prevention: '개인 정보와 무관한 무작위 비밀번호',
    successRate: '개인 정보 기반 비밀번호의 43% 추측 가능'
  }
};

비밀번호 복잡성 평가

강도 측정 알고리즘

class PasswordStrengthAnalyzer {
  constructor() {
    this.patterns = {
      lowercase: /[a-z]/,
      uppercase: /[A-Z]/,
      numbers: /[0-9]/,
      specialChars: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/,
      repeating: /(.)\1{2,}/,
      sequential: /(abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz|123|234|345|456|567|678|789)/i,
      commonWords: ['password', 'admin', 'user', 'login', '123456', 'qwerty']
    };
  }
  
  analyzeStrength(password) {
    const analysis = {
      score: 0,
      length: password.length,
      hasLowercase: this.patterns.lowercase.test(password),
      hasUppercase: this.patterns.uppercase.test(password),
      hasNumbers: this.patterns.numbers.test(password),
      hasSpecialChars: this.patterns.specialChars.test(password),
      hasRepeating: this.patterns.repeating.test(password),
      hasSequential: this.patterns.sequential.test(password),
      isCommonWord: this.isCommonPassword(password),
      entropy: this.calculateEntropy(password),
      timeToBreak: null,
      improvements: [],
      strength: 'very_weak'
    };
    
    // 점수 계산
    analysis.score += this.calculateLengthScore(password.length);
    analysis.score += this.calculateComplexityScore(analysis);
    analysis.score += this.calculatePatternPenalty(analysis);
    
    // 강도 분류
    analysis.strength = this.classifyStrength(analysis.score);
    analysis.timeToBreak = this.estimateBreakTime(analysis);
    analysis.improvements = this.generateImprovements(analysis);
    
    return analysis;
  }
  
  calculateLengthScore(length) {
    if (length < 6) return 0;
    if (length < 8) return 10;
    if (length < 12) return 25;
    if (length < 16) return 35;
    return 45;
  }
  
  calculateComplexityScore(analysis) {
    let score = 0;
    if (analysis.hasLowercase) score += 5;
    if (analysis.hasUppercase) score += 5;
    if (analysis.hasNumbers) score += 5;
    if (analysis.hasSpecialChars) score += 10;
    
    // 다양성 보너스
    const characterSets = [
      analysis.hasLowercase,
      analysis.hasUppercase,
      analysis.hasNumbers,
      analysis.hasSpecialChars
    ].filter(Boolean).length;
    
    if (characterSets >= 3) score += 10;
    if (characterSets === 4) score += 15;
    
    return score;
  }
  
  calculatePatternPenalty(analysis) {
    let penalty = 0;
    if (analysis.hasRepeating) penalty -= 15;
    if (analysis.hasSequential) penalty -= 10;
    if (analysis.isCommonWord) penalty -= 25;
    return penalty;
  }
  
  calculateEntropy(password) {
    // 문자 집합 크기 계산
    let charsetSize = 0;
    if (this.patterns.lowercase.test(password)) charsetSize += 26;
    if (this.patterns.uppercase.test(password)) charsetSize += 26;
    if (this.patterns.numbers.test(password)) charsetSize += 10;
    if (this.patterns.specialChars.test(password)) charsetSize += 32;
    
    // 엔트로피 = log2(charsetSize^length)
    return password.length * Math.log2(charsetSize);
  }
  
  estimateBreakTime(analysis) {
    // 현대적인 GPU 기준: 초당 10^9 회 시도
    const attemptsPerSecond = 1000000000;
    const keySpace = Math.pow(95, analysis.length); // 95개 인쇄 가능한 ASCII 문자
    const averageAttempts = keySpace / 2;
    const secondsToBreak = averageAttempts / attemptsPerSecond;
    
    return this.formatTime(secondsToBreak);
  }
  
  formatTime(seconds) {
    if (seconds < 1) return '즉시';
    if (seconds < 60) return `${Math.round(seconds)}초`;
    if (seconds < 3600) return `${Math.round(seconds / 60)}분`;
    if (seconds < 86400) return `${Math.round(seconds / 3600)}시간`;
    if (seconds < 31536000) return `${Math.round(seconds / 86400)}일`;
    return `${Math.round(seconds / 31536000)}년`;
  }
  
  classifyStrength(score) {
    if (score < 20) return 'very_weak';
    if (score < 40) return 'weak';
    if (score < 60) return 'fair';
    if (score < 80) return 'good';
    return 'very_strong';
  }
  
  generateImprovements(analysis) {
    const improvements = [];
    
    if (analysis.length < 12) {
      improvements.push('비밀번호를 12자리 이상으로 늘리세요');
    }
    
    if (!analysis.hasUppercase) {
      improvements.push('대문자를 추가하세요');
    }
    
    if (!analysis.hasLowercase) {
      improvements.push('소문자를 추가하세요');
    }
    
    if (!analysis.hasNumbers) {
      improvements.push('숫자를 추가하세요');
    }
    
    if (!analysis.hasSpecialChars) {
      improvements.push('특수문자를 추가하세요 (!@#$%^&* 등)');
    }
    
    if (analysis.hasRepeating) {
      improvements.push('반복되는 문자를 피하세요');
    }
    
    if (analysis.hasSequential) {
      improvements.push('연속된 문자나 숫자를 피하세요');
    }
    
    if (analysis.isCommonWord) {
      improvements.push('일반적인 단어나 패턴을 피하세요');
    }
    
    return improvements;
  }
  
  isCommonPassword(password) {
    const lowerPassword = password.toLowerCase();
    return this.patterns.commonWords.some(word => lowerPassword.includes(word));
  }
}

// 사용 예시
const analyzer = new PasswordStrengthAnalyzer();
const result = analyzer.analyzeStrength('MyP@ssw0rd123!');

console.log(result);
// {
//   score: 75,
//   strength: 'good',
//   entropy: 65.4,
//   timeToBreak: '34,000년',
//   improvements: ['비밀번호를 12자리 이상으로 늘리세요']
// }

2. 강력한 비밀번호 생성 방법 {#strong-passwords}

안전한 비밀번호 생성 전략

1. Passphrase (패스프레이즈) 방식

class PassphraseGenerator {
  constructor() {
    // 다양한 언어와 주제의 단어 목록
    this.wordLists = {
      korean: ['바다', '산', '하늘', '꽃', '나무', '별', '달', '구름', '강', '호수'],
      english: ['ocean', 'mountain', 'sky', 'flower', 'tree', 'star', 'moon', 'cloud', 'river', 'lake'],
      adjectives: ['빠른', '느린', '큰', '작은', '밝은', '어두운', '뜨거운', '차가운', '부드러운', '단단한'],
      verbs: ['달리다', '걷다', '뛰다', '날다', '수영하다', '춤추다', '노래하다', '읽다', '쓰다', '그리다'],
      colors: ['빨강', '파랑', '노랑', '초록', '보라', '주황', '분홍', '검정', '하양', '회색'],
      numbers: ['하나', '둘', '셋', '넷', '다섯', '여섯', '일곱', '여덟', '아홉', '열']
    };
    
    this.separators = ['!', '@', '#', '$', '%', '^', '&', '*', '-', '_', '+', '='];
  }
  
  generatePassphrase(options = {}) {
    const {
      wordCount = 4,
      includeNumbers = true,
      includeSymbols = true,
      capitalizeFirst = true,
      customSeparator = null,
      language = 'korean'
    } = options;
    
    const words = [];
    const availableWords = this.wordLists[language] || this.wordLists.korean;
    
    // 단어 선택
    for (let i = 0; i < wordCount; i++) {
      let word = this.getRandomElement(availableWords);
      
      if (capitalizeFirst && i === 0) {
        word = word.charAt(0).toUpperCase() + word.slice(1);
      }
      
      words.push(word);
    }
    
    // 구분자 선택
    let separator = customSeparator || (includeSymbols ? 
      this.getRandomElement(this.separators) : '');
    
    // 숫자 추가
    if (includeNumbers) {
      const randomNumber = Math.floor(Math.random() * 9999) + 1;
      words.push(randomNumber.toString());
    }
    
    return {
      passphrase: words.join(separator),
      words: words,
      separator: separator,
      strength: this.estimatePassphraseStrength(words.join(separator)),
      memorabilityTips: this.generateMemorabilityTips(words)
    };
  }
  
  generateMemorabilityTips(words) {
    return [
      `스토리 만들기: "${words.slice(0, -1).join(' ')}으로 ${words[words.length-1]}를 세어보세요"`,
      `첫 글자로 문장 만들기: ${words.map(w => w.charAt(0)).join('')}`,
      `리듬으로 기억하기: 단어들을 노래나 랩으로 만들어 보세요`,
      `시각적 연상: 각 단어를 그림으로 그려보고 연결해보세요`
    ];
  }
  
  getRandomElement(array) {
    return array[Math.floor(Math.random() * array.length)];
  }
  
  estimatePassphraseStrength(passphrase) {
    const analyzer = new PasswordStrengthAnalyzer();
    return analyzer.analyzeStrength(passphrase);
  }
}

// 사용 예시
const passphraseGen = new PassphraseGenerator();
const result = passphraseGen.generatePassphrase({
  wordCount: 4,
  includeNumbers: true,
  includeSymbols: true,
  language: 'korean'
});

console.log(result);
// {
//   passphrase: "바다!산!하늘!꽃!2847",
//   words: ["바다", "산", "하늘", "꽃", "2847"],
//   separator: "!",
//   strength: { score: 85, strength: 'very_strong' },
//   memorabilityTips: [...]
// }

2. 패턴 기반 생성 방식

class PatternBasedGenerator {
  constructor() {
    this.patterns = {
      // 위치별 문자 유형 지정
      positional: [
        'U', // Uppercase letter
        'l', // lowercase letter
        'l', // lowercase letter
        'd', // digit
        's', // symbol
        'U', // Uppercase letter
        'l', // lowercase letter
        'd', // digit
        'd', // digit
        's', // symbol
        'l', // lowercase letter
        'l'  // lowercase letter
      ],
      
      // 청크 기반 패턴 (기억하기 쉬운 덩어리)
      chunks: [
        { type: 'word', case: 'title' },    // 첫글자 대문자 단어
        { type: 'number', length: 2 },      // 2자리 숫자
        { type: 'symbol', count: 1 },       // 특수문자 1개
        { type: 'word', case: 'lower' },    // 소문자 단어
        { type: 'number', length: 2 }       // 2자리 숫자
      ]
    };
    
    this.characterSets = {
      uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
      lowercase: 'abcdefghijklmnopqrstuvwxyz', 
      digits: '0123456789',
      symbols: '!@#$%^&*()_+-=[]{}|;:,.<>?',
      safe_symbols: '!@#$%^&*-_=+' // 대부분 시스템에서 안전한 특수문자
    };
    
    this.commonWords = {
      short: ['cat', 'dog', 'sun', 'moon', 'star', 'blue', 'red', 'joy', 'hope', 'love'],
      medium: ['ocean', 'forest', 'mountain', 'rainbow', 'thunder', 'whisper', 'shadow', 'crystal']
    };
  }
  
  generateByPattern(patternType = 'positional', options = {}) {
    const {
      useCommonWords = true,
      avoidAmbiguous = true, // 0, O, l, 1 등 헷갈리기 쉬운 문자 제외
      customPattern = null
    } = options;
    
    if (avoidAmbiguous) {
      this.removeAmbiguousChars();
    }
    
    const pattern = customPattern || this.patterns[patternType];
    
    if (patternType === 'positional') {
      return this.generatePositionalPattern(pattern);
    } else if (patternType === 'chunks') {
      return this.generateChunkPattern(pattern, useCommonWords);
    }
  }
  
  generatePositionalPattern(pattern) {
    let password = '';
    const usedChars = new Set(); // 중복 방지를 위한 Set
    
    pattern.forEach(charType => {
      let char;
      let attempts = 0;
      
      do {
        char = this.getRandomCharByType(charType);
        attempts++;
      } while (usedChars.has(char) && attempts < 10);
      
      usedChars.add(char);
      password += char;
    });
    
    return {
      password,
      pattern: pattern.join(''),
      analysis: new PasswordStrengthAnalyzer().analyzeStrength(password),
      generationMethod: 'positional'
    };
  }
  
  generateChunkPattern(chunks, useCommonWords) {
    const parts = [];
    let password = '';
    
    chunks.forEach(chunk => {
      let part = '';
      
      switch (chunk.type) {
        case 'word':
          if (useCommonWords) {
            part = this.getRandomElement(this.commonWords.short);
            if (chunk.case === 'title') {
              part = part.charAt(0).toUpperCase() + part.slice(1);
            } else if (chunk.case === 'upper') {
              part = part.toUpperCase();
            }
          } else {
            // 무작위 문자로 단어 모양 생성
            const length = Math.floor(Math.random() * 4) + 3; // 3-6자
            for (let i = 0; i < length; i++) {
              if (i === 0 && chunk.case === 'title') {
                part += this.getRandomCharByType('U');
              } else {
                part += this.getRandomCharByType('l');
              }
            }
          }
          break;
          
        case 'number':
          for (let i = 0; i < chunk.length; i++) {
            part += this.getRandomCharByType('d');
          }
          break;
          
        case 'symbol':
          for (let i = 0; i < chunk.count; i++) {
            part += this.getRandomCharByType('s');
          }
          break;
      }
      
      parts.push(part);
      password += part;
    });
    
    return {
      password,
      chunks: parts,
      chunkTypes: chunks.map(c => c.type),
      analysis: new PasswordStrengthAnalyzer().analyzeStrength(password),
      generationMethod: 'chunks',
      memorabilityPattern: this.createMemorabilityPattern(parts, chunks)
    };
  }
  
  createMemorabilityPattern(parts, chunks) {
    const patterns = [];
    
    for (let i = 0; i < parts.length; i++) {
      const part = parts[i];
      const chunk = chunks[i];
      
      if (chunk.type === 'word') {
        patterns.push(`단어: ${part}`);
      } else if (chunk.type === 'number') {
        patterns.push(`숫자: ${part} (${this.numberToKorean(part)})`);
      } else if (chunk.type === 'symbol') {
        patterns.push(`기호: ${part}`);
      }
    }
    
    return patterns;
  }
  
  numberToKorean(number) {
    const korean = ['영', '일', '이', '삼', '사', '오', '육', '칠', '팔', '구'];
    return number.split('').map(digit => korean[parseInt(digit)]).join('');
  }
  
  getRandomCharByType(type) {
    let charset = '';
    
    switch (type) {
      case 'U': charset = this.characterSets.uppercase; break;
      case 'l': charset = this.characterSets.lowercase; break;
      case 'd': charset = this.characterSets.digits; break;
      case 's': charset = this.characterSets.safe_symbols; break;
    }
    
    return charset.charAt(Math.floor(Math.random() * charset.length));
  }
  
  removeAmbiguousChars() {
    // 헷갈리기 쉬운 문자 제거
    this.characterSets.uppercase = this.characterSets.uppercase.replace(/[0OIL]/g, '');
    this.characterSets.lowercase = this.characterSets.lowercase.replace(/[l1]/g, '');
    this.characterSets.digits = this.characterSets.digits.replace(/[01]/g, '');
  }
  
  getRandomElement(array) {
    return array[Math.floor(Math.random() * array.length)];
  }
}

// 사용 예시
const patternGen = new PatternBasedGenerator();

// 위치별 패턴 생성
const positionalResult = patternGen.generateByPattern('positional');
console.log(positionalResult);
// { password: "Ab3!De78*fg", pattern: "UllddsUldds", analysis: {...} }

// 청크 패턴 생성  
const chunkResult = patternGen.generateByPattern('chunks');
console.log(chunkResult);
// { 
//   password: "Cat42@moon89", 
//   chunks: ["Cat", "42", "@", "moon", "89"],
//   memorabilityPattern: ["단어: Cat", "숫자: 42 (사이)", "기호: @", ...]
// }

비밀번호 생성 도구 비교

생성 방식별 장단점

const generationMethods = {
  random: {
    pros: ['최고 수준의 보안', '예측 불가능', '무차별 대입 공격에 강함'],
    cons: ['기억하기 어려움', '입력 오류 가능성 높음', '사용자 불편'],
    useCases: ['시스템 간 통신', 'API 키', '일회성 계정'],
    example: 'Kj8#mP2$qR9!',
    memorability: 1,
    security: 10
  },
  
  passphrase: {
    pros: ['기억하기 쉬움', '긴 길이로 높은 보안', '입력 오류 적음'],
    cons: ['사전 공격 취약 가능성', '언어별 패턴 존재', '길이가 길어짐'],
    useCases: ['개인 계정', '마스터 비밀번호', '자주 사용하는 계정'],
    example: 'correct-horse-battery-staple-47',
    memorability: 9,
    security: 8
  },
  
  pattern: {
    pros: ['보안과 기억 가능성 균형', '일관된 형식', '교육 효과'],
    cons: ['패턴 노출 시 취약', '창의성 제한', '시스템별 호환성'],
    useCases: ['기업 정책', '교육용', '다중 계정 관리'],
    example: 'Work2024!',
    memorability: 7,
    security: 7
  },
  
  mnemonic: {
    pros: ['개인화 가능', '의미 있는 연결', '장기 기억 용이'],
    cons: ['개인 정보 노출 위험', '패턴 추측 가능', '복잡도 제한'],
    useCases: ['개인용', '중요도 중간 계정', '복구 질문 대체'],
    example: 'MyDog3Years@Home', // "My Dog is 3 Years old At Home"
    memorability: 8,
    security: 6
  }
};

3. 비밀번호 관리 전략 {#management-strategies}

체계적인 비밀번호 관리

계정별 중요도 분류

class PasswordTierSystem {
  constructor() {
    this.tiers = {
      critical: {
        description: '금융, 업무, 중요 개인정보 관련',
        requirements: {
          minLength: 16,
          complexity: 'very_strong',
          uniqueness: true, // 다른 곳에서 절대 재사용 금지
          mfa: true,        // 2단계 인증 필수
          changeFrequency: 90 // 90일마다 변경
        },
        examples: ['은행', '증권사', '회사 계정', '클라우드 스토리지', '이메일'],
        storageMethod: 'password_manager_only'
      },
      
      important: {
        description: '소셜미디어, 쇼핑몰, 구독 서비스',
        requirements: {
          minLength: 12,
          complexity: 'strong',
          uniqueness: true,
          mfa: 'recommended',
          changeFrequency: 180
        },
        examples: ['페이스북', '인스타그램', '쿠팡', '넷플릭스', '유튜브'],
        storageMethod: 'password_manager_preferred'
      },
      
      standard: {
        description: '일반 웹사이트, 포럼, 뉴스 사이트',
        requirements: {
          minLength: 10,
          complexity: 'good',
          uniqueness: 'recommended',
          mfa: 'optional',
          changeFrequency: 365
        },
        examples: ['뉴스 사이트', '커뮤니티', '무료 도구', '일회성 가입'],
        storageMethod: 'browser_ok'
      },
      
      low_risk: {
        description: '테스트용, 임시 계정',
        requirements: {
          minLength: 8,
          complexity: 'fair',
          uniqueness: false,
          mfa: false,
          changeFrequency: 'as_needed'
        },
        examples: ['테스트 사이트', '일회성 다운로드', '임시 계정'],
        storageMethod: 'simple_pattern_ok'
      }
    };
  }
  
  classifyAccount(accountInfo) {
    const { domain, accountType, dataTypes, financialAccess } = accountInfo;
    
    // 금융 관련
    if (financialAccess || 
        ['bank', 'finance', 'payment', 'crypto'].includes(accountType)) {
      return 'critical';
    }
    
    // 개인정보나 업무 관련
    if (dataTypes.includes('personal_info') || 
        dataTypes.includes('work_data') ||
        ['email', 'cloud_storage', 'work'].includes(accountType)) {
      return 'critical';
    }
    
    // 소셜미디어, 주요 서비스
    if (['social', 'shopping', 'subscription'].includes(accountType) ||
        ['facebook.com', 'instagram.com', 'twitter.com', 'linkedin.com'].includes(domain)) {
      return 'important';
    }
    
    // 일반 웹사이트
    if (accountType === 'general' || dataTypes.length === 0) {
      return 'standard';
    }
    
    return 'low_risk';
  }
  
  generatePasswordForTier(tier, options = {}) {
    const requirements = this.tiers[tier].requirements;
    const generator = new PatternBasedGenerator();
    
    let password;
    let attempts = 0;
    
    do {
      if (tier === 'critical') {
        // 최고 보안: 완전 무작위
        password = this.generateCryptoSecurePassword(requirements.minLength);
      } else if (tier === 'important') {
        // 패스프레이즈 방식
        const passphraseGen = new PassphraseGenerator();
        const result = passphraseGen.generatePassphrase({
          wordCount: 3,
          includeNumbers: true,
          includeSymbols: true
        });
        password = result.passphrase;
      } else {
        // 패턴 기반
        const result = generator.generateByPattern('chunks');
        password = result.password;
      }
      
      attempts++;
    } while (!this.meetsRequirements(password, requirements) && attempts < 10);
    
    return {
      password,
      tier,
      requirements,
      analysis: new PasswordStrengthAnalyzer().analyzeStrength(password),
      recommendations: this.getManagementRecommendations(tier)
    };
  }
  
  generateCryptoSecurePassword(length) {
    const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*';
    let password = '';
    
    // crypto.getRandomValues() 사용 (브라우저 환경)
    if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
      const array = new Uint8Array(length);
      crypto.getRandomValues(array);
      
      for (let i = 0; i < length; i++) {
        password += charset[array[i] % charset.length];
      }
    } else {
      // 폴백: Math.random() (보안성이 떨어지므로 경고)
      console.warn('암호학적으로 안전한 난수 생성기를 사용할 수 없습니다.');
      for (let i = 0; i < length; i++) {
        password += charset[Math.floor(Math.random() * charset.length)];
      }
    }
    
    return password;
  }
  
  meetsRequirements(password, requirements) {
    const analysis = new PasswordStrengthAnalyzer().analyzeStrength(password);
    
    return password.length >= requirements.minLength &&
           this.strengthToScore(analysis.strength) >= this.strengthToScore(requirements.complexity);
  }
  
  strengthToScore(strength) {
    const scoreMap = {
      'very_weak': 1,
      'weak': 2,
      'fair': 3,
      'good': 4,
      'strong': 5,
      'very_strong': 6
    };
    
    return scoreMap[strength] || 0;
  }
  
  getManagementRecommendations(tier) {
    const tierInfo = this.tiers[tier];
    
    return [
      `보관 방법: ${tierInfo.storageMethod}`,
      `2단계 인증: ${tierInfo.requirements.mfa ? '필수' : '권장'}`,
      `변경 주기: ${tierInfo.requirements.changeFrequency}일`,
      `고유성: ${tierInfo.requirements.uniqueness ? '필수' : '권장'}`,
      `최소 길이: ${tierInfo.requirements.minLength}자`
    ];
  }
}

// 사용 예시
const tierSystem = new PasswordTierSystem();

// 계정 분류
const accountInfo = {
  domain: 'mybank.com',
  accountType: 'bank',
  dataTypes: ['financial', 'personal_info'],
  financialAccess: true
};

const tier = tierSystem.classifyAccount(accountInfo);
console.log(`계정 등급: ${tier}`); // "critical"

// 해당 등급에 맞는 비밀번호 생성
const passwordResult = tierSystem.generatePasswordForTier(tier);
console.log(passwordResult);

비밀번호 매니저 활용

비밀번호 매니저 선택 기준

const passwordManagerComparison = {
  // 개인용 추천
  personal: {
    'Bitwarden': {
      pros: ['오픈소스', '무료 버전 충분', '크로스 플랫폼', '자체 호스팅 가능'],
      cons: ['UI가 다소 복잡', '고급 기능은 유료'],
      price: '무료 / $3/월',
      security: '최고급',
      usability: '중급',
      recommendation: '개인 사용자에게 최고의 선택'
    },
    
    '1Password': {
      pros: ['직관적 UI', '강력한 보안', '가족 공유', '여행 모드'],
      cons: ['무료 버전 없음', '상대적으로 비쌈'],
      price: '$3-8/월',
      security: '최고급',
      usability: '최고급',
      recommendation: '사용 편의성 중시 시 선택'
    },
    
    'LastPass': {
      pros: ['무료 버전', '브라우저 통합', '쉬운 사용법'],
      cons: ['과거 보안 사고', '무료 버전 제한'],
      price: '무료 / $3/월',
      security: '양호',
      usability: '고급',
      recommendation: '입문자용으로 적합'
    }
  },
  
  // 기업용 추천
  enterprise: {
    'Bitwarden Business': {
      features: ['SSO 지원', '관리자 콘솔', '감사 로그', '정책 관리'],
      price: '$3/사용자/월',
      deployment: '클라우드/온프레미스',
      compliance: 'SOC 2, GDPR, HIPAA'
    },
    
    'CyberArk': {
      features: ['PAM 통합', '권한 관리', '세션 모니터링', '위협 분석'],
      price: '문의',
      deployment: '온프레미스/하이브리드',
      compliance: '금융업 특화'
    }
  }
};

// 비밀번호 매니저 통합 클래스
class PasswordManagerIntegration {
  constructor(managerType = 'generic') {
    this.managerType = managerType;
    this.vault = new Map(); // 로컬 시뮬레이션용
    this.categories = ['critical', 'important', 'standard', 'low_risk'];
  }
  
  // 비밀번호 저장
  storePassword(entry) {
    const {
      title,
      username,
      password,
      url,
      category = 'standard',
      notes = '',
      customFields = {}
    } = entry;
    
    const passwordEntry = {
      id: this.generateId(),
      title,
      username,
      password: this.encrypt(password), // 실제로는 매니저가 암호화
      url,
      category,
      notes,
      customFields,
      createdAt: new Date(),
      lastModified: new Date(),
      lastUsed: null,
      strength: new PasswordStrengthAnalyzer().analyzeStrength(password),
      tags: this.generateTags(url, category)
    };
    
    this.vault.set(passwordEntry.id, passwordEntry);
    return passwordEntry.id;
  }
  
  // 비밀번호 검색
  searchPasswords(query) {
    const results = [];
    
    this.vault.forEach(entry => {
      const searchText = `${entry.title} ${entry.username} ${entry.url} ${entry.notes}`.toLowerCase();
      if (searchText.includes(query.toLowerCase())) {
        results.push({
          ...entry,
          password: this.decrypt(entry.password) // 실제로는 마스터 비밀번호 검증 후
        });
      }
    });
    
    return results.sort((a, b) => b.lastUsed - a.lastUsed); // 최근 사용 순
  }
  
  // 취약한 비밀번호 감지
  auditPasswords() {
    const audit = {
      weak: [],
      reused: [],
      old: [],
      compromised: [],
      total: this.vault.size
    };
    
    const passwords = new Map(); // 중복 체크용
    const currentDate = new Date();
    
    this.vault.forEach(entry => {
      const decryptedPassword = this.decrypt(entry.password);
      
      // 약한 비밀번호
      if (entry.strength.score < 60) {
        audit.weak.push({
          title: entry.title,
          score: entry.strength.score,
          improvements: entry.strength.improvements
        });
      }
      
      // 재사용 비밀번호
      if (passwords.has(decryptedPassword)) {
        const existing = passwords.get(decryptedPassword);
        audit.reused.push({
          password: '***hidden***',
          accounts: [existing.title, entry.title]
        });
      } else {
        passwords.set(decryptedPassword, entry);
      }
      
      // 오래된 비밀번호 (1년 이상)
      const daysSinceModified = (currentDate - entry.lastModified) / (1000 * 60 * 60 * 24);
      if (daysSinceModified > 365) {
        audit.old.push({
          title: entry.title,
          lastModified: entry.lastModified,
          daysOld: Math.floor(daysSinceModified)
        });
      }
      
      // 유출된 비밀번호 체크 (시뮬레이션)
      if (this.isCompromised(decryptedPassword)) {
        audit.compromised.push({
          title: entry.title,
          breach: 'Multiple breaches found'
        });
      }
    });
    
    return audit;
  }
  
  // 자동 비밀번호 생성 및 변경
  autoUpdatePassword(entryId, options = {}) {
    const entry = this.vault.get(entryId);
    if (!entry) return null;
    
    const tierSystem = new PasswordTierSystem();
    const tier = tierSystem.classifyAccount({
      domain: this.extractDomain(entry.url),
      accountType: entry.category,
      dataTypes: entry.customFields.dataTypes || [],
      financialAccess: entry.tags.includes('financial')
    });
    
    const newPasswordResult = tierSystem.generatePasswordForTier(tier, options);
    
    // 이전 비밀번호 백업
    const backup = {
      password: entry.password,
      changedAt: new Date(),
      reason: 'auto_update'
    };
    
    // 새 비밀번호 저장
    entry.password = this.encrypt(newPasswordResult.password);
    entry.lastModified = new Date();
    entry.strength = newPasswordResult.analysis;
    entry.previousPasswords = entry.previousPasswords || [];
    entry.previousPasswords.push(backup);
    
    // 최대 3개까지만 백업 유지
    if (entry.previousPasswords.length > 3) {
      entry.previousPasswords.shift();
    }
    
    return {
      newPassword: newPasswordResult.password,
      strength: newPasswordResult.analysis,
      recommendations: newPasswordResult.recommendations
    };
  }
  
  // 보안 점수 계산
  calculateSecurityScore() {
    if (this.vault.size === 0) return 0;
    
    let totalScore = 0;
    let criticalAccountsSecure = 0;
    let totalCriticalAccounts = 0;
    
    this.vault.forEach(entry => {
      const baseScore = Math.min(entry.strength.score, 100);
      let multiplier = 1;
      
      // 카테고리별 가중치
      if (entry.category === 'critical') {
        multiplier = 2;
        totalCriticalAccounts++;
        if (baseScore >= 80) criticalAccountsSecure++;
      } else if (entry.category === 'important') {
        multiplier = 1.5;
      }
      
      totalScore += baseScore * multiplier;
    });
    
    const averageScore = totalScore / this.vault.size;
    const criticalSecurityRatio = totalCriticalAccounts > 0 ? 
      criticalAccountsSecure / totalCriticalAccounts : 1;
    
    return {
      overallScore: Math.round(averageScore * criticalSecurityRatio),
      criticalAccountsSecurity: Math.round(criticalSecurityRatio * 100),
      recommendations: this.getSecurityRecommendations(averageScore, criticalSecurityRatio)
    };
  }
  
  getSecurityRecommendations(averageScore, criticalRatio) {
    const recommendations = [];
    
    if (averageScore < 70) {
      recommendations.push('전체적인 비밀번호 강도를 높이세요');
    }
    
    if (criticalRatio < 0.9) {
      recommendations.push('중요 계정의 비밀번호를 더욱 강화하세요');
    }
    
    const auditResults = this.auditPasswords();
    
    if (auditResults.weak.length > 0) {
      recommendations.push(`${auditResults.weak.length}개의 약한 비밀번호를 교체하세요`);
    }
    
    if (auditResults.reused.length > 0) {
      recommendations.push(`${auditResults.reused.length}개의 재사용 비밀번호를 변경하세요`);
    }
    
    if (auditResults.old.length > 0) {
      recommendations.push(`${auditResults.old.length}개의 오래된 비밀번호를 업데이트하세요`);
    }
    
    return recommendations;
  }
  
  // 유틸리티 메서드들
  generateId() {
    return Date.now().toString(36) + Math.random().toString(36).substr(2);
  }
  
  encrypt(password) {
    // 실제로는 AES-256 등 강력한 암호화 사용
    return btoa(password); // Base64는 예시용
  }
  
  decrypt(encryptedPassword) {
    return atob(encryptedPassword);
  }
  
  extractDomain(url) {
    try {
      return new URL(url).hostname;
    } catch {
      return url;
    }
  }
  
  generateTags(url, category) {
    const tags = [category];
    const domain = this.extractDomain(url);
    
    // 도메인 기반 태그
    if (domain.includes('bank') || domain.includes('finance')) {
      tags.push('financial');
    }
    if (domain.includes('work') || domain.includes('company')) {
      tags.push('work');
    }
    if (domain.includes('social') || ['facebook', 'twitter', 'instagram'].some(s => domain.includes(s))) {
      tags.push('social');
    }
    
    return tags;
  }
  
  isCompromised(password) {
    // 실제로는 HaveIBeenPwned API 등을 사용
    const commonCompromised = ['password123', '123456', 'password', 'admin'];
    return commonCompromised.includes(password.toLowerCase());
  }
}

4. 고급 보안 기법 {#advanced-security}

다중 인증 (Multi-Factor Authentication)

2FA/MFA 구현 전략

class MultiFactorAuth {
  constructor() {
    this.methods = {
      sms: {
        security: 'low',
        convenience: 'high',
        cost: 'low',
        risks: ['SIM 스와핑', '인터셉션', '네트워크 의존성'],
        useCases: ['일반 사용자', '초기 보안 강화']
      },
      
      authenticator_app: {
        security: 'high',
        convenience: 'high',
        cost: 'free',
        risks: ['디바이스 분실', '백업 부족'],
        useCases: ['개인 계정', '중급 보안', '대부분의 서비스'],
        recommended_apps: ['Google Authenticator', 'Authy', 'Microsoft Authenticator']
      },
      
      hardware_key: {
        security: 'very_high',
        convenience: 'medium',
        cost: 'medium',
        risks: ['디바이스 분실', '물리적 접근'],
        useCases: ['고보안 환경', '기업 계정', '암호화폐'],
        recommended_devices: ['YubiKey', 'Google Titan', 'SoloKeys']
      },
      
      biometric: {
        security: 'high',
        convenience: 'very_high',
        cost: 'hardware_dependent',
        risks: ['스푸핑', '프라이버시 우려', '하드웨어 의존성'],
        useCases: ['모바일 디바이스', '로컬 인증', 'UX 중시 환경']
      },
      
      backup_codes: {
        security: 'medium',
        convenience: 'low',
        cost: 'free',
        risks: ['분실', '노출', '단일 사용'],
        useCases: ['복구용', '비상시 접근', 'MFA 백업']
      }
    };
    
    this.implementationGuide = {
      personal_accounts: {
        primary: 'authenticator_app',
        backup: 'backup_codes',
        high_value: 'hardware_key + authenticator_app'
      },
      
      business_accounts: {
        employees: 'hardware_key + biometric',
        admin: 'hardware_key + authenticator_app + backup_codes',
        service_accounts: 'certificate_based + hardware_hsm'
      }
    };
  }
  
  // MFA 설정 가이드 생성
  generateMFASetupGuide(accountType, securityLevel) {
    const guide = {
      accountType,
      securityLevel,
      recommendedMethods: [],
      setupSteps: [],
      backupPlan: [],
      securityTips: []
    };
    
    // 보안 수준별 권장사항
    switch (securityLevel) {
      case 'maximum':
        guide.recommendedMethods = [
          { primary: 'hardware_key', secondary: 'authenticator_app', backup: 'backup_codes' }
        ];
        break;
      case 'high':
        guide.recommendedMethods = [
          { primary: 'authenticator_app', secondary: 'hardware_key', backup: 'backup_codes' }
        ];
        break;
      case 'standard':
        guide.recommendedMethods = [
          { primary: 'authenticator_app', backup: 'backup_codes' }
        ];
        break;
      case 'basic':
        guide.recommendedMethods = [
          { primary: 'sms', backup: 'backup_codes' }
        ];
        break;
    }
    
    // 설정 단계
    guide.setupSteps = this.generateSetupSteps(guide.recommendedMethods[0]);
    guide.backupPlan = this.generateBackupPlan(guide.recommendedMethods[0]);
    guide.securityTips = this.generateSecurityTips(securityLevel);
    
    return guide;
  }
  
  generateSetupSteps(methods) {
    const steps = [];
    
    if (methods.primary === 'authenticator_app') {
      steps.push({
        step: 1,
        action: 'TOTP 앱 설치',
        details: 'Google Authenticator, Authy, 또는 Microsoft Authenticator 설치',
        security_note: '여러 디바이스에 백업 설정 권장'
      });
      
      steps.push({
        step: 2,
        action: '서비스에서 MFA 활성화',
        details: '계정 설정 → 보안 → 2단계 인증 활성화',
        security_note: 'QR 코드 스캔 시 주변 환경 확인'
      });
      
      steps.push({
        step: 3,
        action: '백업 코드 저장',
        details: '복구 코드를 안전한 곳에 저장 (비밀번호 매니저 추천)',
        security_note: '복구 코드는 일회용이므로 사용 후 새로 생성'
      });
    }
    
    if (methods.secondary === 'hardware_key') {
      steps.push({
        step: 4,
        action: '하드웨어 키 등록',
        details: 'FIDO2/WebAuthn 호환 키를 USB 포트에 연결',
        security_note: '최소 2개의 키를 등록하여 백업 확보'
      });
    }
    
    return steps;
  }
  
  generateBackupPlan(methods) {
    return [
      {
        scenario: '주 인증 방법 사용 불가',
        solution: `${methods.backup || methods.secondary} 사용`,
        preparation: '미리 설정 및 테스트 완료'
      },
      {
        scenario: '모든 디바이스 분실',
        solution: '백업 코드 사용 + 계정 복구 절차',
        preparation: '백업 코드를 별도 위치에 안전 보관'
      },
      {
        scenario: '서비스 접근 불가',
        solution: '대체 연락 방법으로 고객센터 문의',
        preparation: '신원 확인용 정보 미리 정리'
      }
    ];
  }
  
  generateSecurityTips(securityLevel) {
    const baseTips = [
      '정기적으로 MFA 설정 상태 확인',
      '의심스러운 로그인 알림 즉시 확인',
      '백업 인증 방법 주기적 테스트',
      '피싱 시도 식별법 숙지'
    ];
    
    if (securityLevel === 'maximum' || securityLevel === 'high') {
      baseTips.push(
        '하드웨어 키는 신뢰할 수 있는 곳에서만 구매',
        '생체인증 데이터 로컬 저장 확인',
        '인증 방법별 위험도 이해하고 선택',
        '업무용과 개인용 인증 방법 분리'
      );
    }
    
    return baseTips;
  }
  
  // MFA 보안 평가
  evaluateMFASecurity(currentSetup) {
    const { primary, secondary, backup, accountImportance } = currentSetup;
    
    let score = 0;
    let recommendations = [];
    
    // 주 인증 방법 평가
    const primaryScore = this.getMethodScore(primary);
    score += primaryScore * 0.5;
    
    // 보조 인증 방법 평가
    if (secondary) {
      const secondaryScore = this.getMethodScore(secondary);
      score += secondaryScore * 0.3;
    } else {
      recommendations.push('보조 인증 방법 추가 설정 권장');
    }
    
    // 백업 방법 평가
    if (backup) {
      const backupScore = this.getMethodScore(backup);
      score += backupScore * 0.2;
    } else {
      recommendations.push('백업 인증 방법 필수 설정');
    }
    
    // 계정 중요도 대비 보안 수준 평가
    const requiredScore = this.getRequiredScore(accountImportance);
    if (score < requiredScore) {
      recommendations.push(`계정 중요도(${accountImportance})에 비해 보안 수준이 낮습니다`);
    }
    
    return {
      score: Math.round(score),
      grade: this.scoreToGrade(score),
      recommendations,
      compliance: score >= requiredScore
    };
  }
  
  getMethodScore(method) {
    const scores = {
      'hardware_key': 95,
      'authenticator_app': 85,
      'biometric': 80,
      'backup_codes': 60,
      'sms': 40,
      'email': 30
    };
    
    return scores[method] || 0;
  }
  
  getRequiredScore(importance) {
    const requirements = {
      'critical': 85,
      'high': 75,
      'medium': 65,
      'low': 50
    };
    
    return requirements[importance] || 50;
  }
  
  scoreToGrade(score) {
    if (score >= 90) return 'A+';
    if (score >= 85) return 'A';
    if (score >= 75) return 'B+';
    if (score >= 65) return 'B';
    if (score >= 55) return 'C';
    return 'D';
  }
}

// 사용 예시
const mfa = new MultiFactorAuth();

// 고보안 계정용 MFA 가이드 생성
const guide = mfa.generateMFASetupGuide('business', 'maximum');
console.log(guide);

// 현재 MFA 설정 평가
const currentSetup = {
  primary: 'authenticator_app',
  secondary: 'hardware_key',
  backup: 'backup_codes',
  accountImportance: 'critical'
};

const evaluation = mfa.evaluateMFASecurity(currentSetup);
console.log(evaluation);
// { score: 89, grade: 'A', recommendations: [], compliance: true }

제로 트러스트 비밀번호 전략

제로 트러스트 원칙 적용

class ZeroTrustPasswordStrategy {
  constructor() {
    this.principles = {
      'never_trust_always_verify': '모든 접근은 검증이 필요',
      'least_privilege': '최소 권한 원칙',
      'assume_breach': '침해 가정하에 설계',
      'verify_explicitly': '명시적 검증',
      'continuous_monitoring': '지속적 모니터링'
    };
    
    this.contextFactors = [
      'user_identity',
      'device_trust',
      'location',
      'time_patterns',
      'behavior_analytics',
      'network_security',
      'application_sensitivity'
    ];
  }
  
  // 컨텍스트 기반 인증 평가
  evaluateAuthenticationContext(authRequest) {
    const {
      userId,
      deviceId,
      location,
      timestamp,
      userAgent,
      applicationId,
      requestedResources
    } = authRequest;
    
    const context = {
      user: this.evaluateUserContext(userId),
      device: this.evaluateDeviceContext(deviceId),
      location: this.evaluateLocationContext(location, userId),
      temporal: this.evaluateTemporalContext(timestamp, userId),
      behavioral: this.evaluateBehavioralContext(authRequest),
      application: this.evaluateApplicationContext(applicationId),
      risk: { score: 0, factors: [] }
    };
    
    // 위험 점수 계산
    context.risk = this.calculateRiskScore(context);
    
    // 인증 요구사항 결정
    const authRequirements = this.determineAuthRequirements(context.risk.score);
    
    return {
      context,
      authRequirements,
      decision: this.makeAuthDecision(context, authRequirements),
      recommendations: this.generateSecurityRecommendations(context)
    };
  }
  
  evaluateUserContext(userId) {
    // 실제로는 사용자 프로필 데이터베이스에서 조회
    return {
      trustLevel: 'medium', // low, medium, high, verified
      recentActivity: 'normal',
      accountAge: 180, // days
      previousViolations: 0,
      mfaEnabled: true,
      passwordStrength: 85,
      lastPasswordChange: 45 // days ago
    };
  }
  
  evaluateDeviceContext(deviceId) {
    return {
      known: true,
      trusted: false,
      lastSeen: 1, // days ago
      operatingSystem: 'Windows 11',
      browser: 'Chrome 120',
      securityPatch: 'current',
      antivirusStatus: 'active',
      enrollment: 'managed' // managed, unmanaged, personal
    };
  }
  
  evaluateLocationContext(location, userId) {
    const userLocations = this.getUserLocationHistory(userId);
    
    return {
      country: location.country,
      region: location.region,
      isKnownLocation: userLocations.includes(location.region),
      travelDistance: this.calculateTravelDistance(userLocations[0], location),
      riskLevel: this.assessLocationRisk(location),
      vpnDetected: false,
      suspiciousProxy: false
    };
  }
  
  evaluateTemporalContext(timestamp, userId) {
    const userPatterns = this.getUserTimePatterns(userId);
    const currentHour = new Date(timestamp).getHours();
    
    return {
      isBusinessHours: currentHour >= 9 && currentHour <= 18,
      isTypicalTime: userPatterns.commonHours.includes(currentHour),
      consecutiveAttempts: 1,
      timeSinceLastLogin: 8, // hours
      frequencyDeviation: 'normal' // normal, high, suspicious
    };
  }
  
  evaluateBehavioralContext(authRequest) {
    return {
      typingPatterns: 'consistent',
      mouseMovements: 'natural',
      sessionDuration: 'typical',
      resourceAccess: 'normal',
      anomalyScore: 0.2 // 0-1, lower is better
    };
  }
  
  evaluateApplicationContext(applicationId) {
    return {
      sensitivityLevel: 'high', // low, medium, high, critical
      dataClassification: 'confidential',
      complianceRequirements: ['SOX', 'GDPR'],
      recentThreats: 'none',
      accessLevel: 'standard'
    };
  }
  
  calculateRiskScore(context) {
    let score = 0;
    const factors = [];
    
    // 사용자 요인 (30%)
    if (context.user.trustLevel === 'low') {
      score += 30;
      factors.push('낮은 사용자 신뢰도');
    } else if (context.user.trustLevel === 'medium') {
      score += 15;
    }
    
    if (context.user.lastPasswordChange > 90) {
      score += 10;
      factors.push('오래된 비밀번호');
    }
    
    // 디바이스 요인 (25%)
    if (!context.device.known) {
      score += 20;
      factors.push('알려지지 않은 디바이스');
    }
    
    if (!context.device.trusted) {
      score += 15;
      factors.push('신뢰되지 않은 디바이스');
    }
    
    // 위치 요인 (20%)
    if (!context.location.isKnownLocation) {
      score += 15;
      factors.push('새로운 위치에서의 접근');
    }
    
    if (context.location.travelDistance > 1000) {
      score += 20;
      factors.push('비정상적인 이동 거리');
    }
    
    // 시간 요인 (15%)
    if (!context.temporal.isTypicalTime) {
      score += 10;
      factors.push('비정상적인 접근 시간');
    }
    
    // 행동 요인 (10%)
    if (context.behavioral.anomalyScore > 0.7) {
      score += 25;
      factors.push('의심스러운 행동 패턴');
    }
    
    return {
      score: Math.min(score, 100),
      level: score < 30 ? 'low' : score < 60 ? 'medium' : 'high',
      factors
    };
  }
  
  determineAuthRequirements(riskScore) {
    if (riskScore < 20) {
      return {
        passwordRequired: true,
        mfaRequired: false,
        additionalVerification: false,
        sessionDuration: 8, // hours
        privilegeLevel: 'standard'
      };
    } else if (riskScore < 50) {
      return {
        passwordRequired: true,
        mfaRequired: true,
        additionalVerification: false,
        sessionDuration: 4,
        privilegeLevel: 'limited'
      };
    } else if (riskScore < 80) {
      return {
        passwordRequired: true,
        mfaRequired: true,
        additionalVerification: true,
        sessionDuration: 1,
        privilegeLevel: 'restricted',
        additionalSteps: ['manager_approval', 'security_questions']
      };
    } else {
      return {
        passwordRequired: true,
        mfaRequired: true,
        additionalVerification: true,
        sessionDuration: 0.5,
        privilegeLevel: 'minimal',
        additionalSteps: ['admin_approval', 'phone_verification', 'security_interview'],
        blockAccess: true
      };
    }
  }
  
  makeAuthDecision(context, requirements) {
    if (requirements.blockAccess) {
      return {
        decision: 'DENY',
        reason: '높은 위험도로 인한 접근 차단',
        nextSteps: '보안팀 검토 후 접근 재승인'
      };
    }
    
    return {
      decision: 'CONDITIONAL_ALLOW',
      conditions: requirements,
      monitoring: 'continuous',
      reevaluationInterval: 15 // minutes
    };
  }
  
  generateSecurityRecommendations(context) {
    const recommendations = [];
    
    if (context.user.passwordStrength < 80) {
      recommendations.push({
        priority: 'high',
        action: '비밀번호 강화',
        description: '더 복잡한 비밀번호로 변경'
      });
    }
    
    if (!context.device.trusted) {
      recommendations.push({
        priority: 'medium',
        action: '디바이스 신뢰 설정',
        description: '관리형 디바이스 등록 또는 보안 소프트웨어 설치'
      });
    }
    
    if (context.behavioral.anomalyScore > 0.5) {
      recommendations.push({
        priority: 'high',
        action: '행동 패턴 검토',
        description: '계정 탈취 가능성 조사 및 비밀번호 즉시 변경'
      });
    }
    
    return recommendations;
  }
  
  // 유틸리티 메서드들
  getUserLocationHistory(userId) {
    // 실제로는 사용자 위치 히스토리 데이터베이스에서 조회
    return ['Seoul, KR', 'Busan, KR'];
  }
  
  calculateTravelDistance(location1, location2) {
    // 실제로는 지리적 거리 계산
    return 0; // km
  }
  
  assessLocationRisk(location) {
    // 실제로는 위협 인텔리전스 데이터 기반 평가
    const highRiskCountries = ['XX', 'YY']; // 예시
    return highRiskCountries.includes(location.country) ? 'high' : 'low';
  }
  
  getUserTimePatterns(userId) {
    // 실제로는 사용자 접근 패턴 분석 데이터
    return {
      commonHours: [9, 10, 11, 13, 14, 15, 16, 17],
      commonDays: [1, 2, 3, 4, 5], // Monday to Friday
      averageSessionDuration: 4 // hours
    };
  }
}

// 사용 예시
const zeroTrust = new ZeroTrustPasswordStrategy();

const authRequest = {
  userId: 'user123',
  deviceId: 'device456',
  location: { country: 'KR', region: 'Seoul' },
  timestamp: new Date(),
  userAgent: 'Mozilla/5.0...',
  applicationId: 'finance_app',
  requestedResources: ['account_balance', 'transaction_history']
};

const evaluation = zeroTrust.evaluateAuthenticationContext(authRequest);
console.log(evaluation);

실무 적용 체크리스트

개인 사용자

  • 비밀번호 매니저 설치 및 설정
  • 중요 계정별 등급 분류 및 차별화된 비밀번호 적용
  • 주요 계정에 2단계 인증 활성화
  • 정기적인 비밀번호 강도 점검 및 업데이트
  • 피싱 및 사회공학 공격 대응법 숙지

기업 관리자

  • 비밀번호 정책 수립 및 시행
  • 직원 대상 보안 교육 프로그램 운영
  • 특권 계정 관리 시스템 구축
  • 정기적인 보안 감사 및 취약점 점검
  • 사고 대응 계획 수립 및 훈련

개발자

  • 안전한 비밀번호 저장 방식 구현 (해싱 + 솔트)
  • 비밀번호 복잡성 검증 로직 구현
  • 계정 잠금 및 공격 탐지 메커니즘 구현
  • 보안 로그 기록 및 모니터링 시스템 구축
  • 정기적인 보안 업데이트 및 패치 관리

마무리

강력한 비밀번호는 디지털 보안의 기초이지만, 완벽한 해결책은 아닙니다. 다층 보안 전략을 통해 비밀번호의 한계를 보완하고, 지속적인 보안 인식 제고를 통해 진화하는 위협에 대응해야 합니다.

효과적인 비밀번호 보안의 핵심:

  1. 강력한 생성: 예측 불가능하고 복잡한 비밀번호
  2. 체계적 관리: 비밀번호 매니저를 통한 안전한 보관
  3. 다중 인증: 2FA/MFA로 보안 강화
  4. 지속적 개선: 정기적인 점검과 업데이트

뚝딱툴 비밀번호 생성으로 지금 바로 안전하고 강력한 비밀번호를 만들어보세요!