claude-flow-novice
Version:
Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture Includes Local RuVector Accelerator and all CFN skills for complete functionality.
166 lines (165 loc) • 6.1 kB
JavaScript
/**
* Secure Password Generator
*
* Generates cryptographically secure passwords for database authentication
* with configurable complexity requirements and validation.
*
* Security Standards:
* - Uses crypto.randomBytes() for cryptographic randomness
* - Default minimum 32 characters for high entropy
* - Requires mixed character types (uppercase, lowercase, digits, special)
* - No ambiguous characters (0/O, 1/l, etc.)
* - Suitable for Redis requirepass and PostgreSQL authentication
*/ import { randomBytes } from 'crypto';
/**
* Default character sets for password generation
*/ const CHAR_SETS = {
uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
uppercaseNoAmbiguous: 'ABCDEFGHJKMNPQRSTUVWXYZ',
lowercase: 'abcdefghijklmnopqrstuvwxyz',
lowercaseNoAmbiguous: 'abcdefghjkmnpqrstuvwxyz',
digits: '0123456789',
digitsNoAmbiguous: '23456789',
special: '!@#$%^&*()_+-=[]{}|;:,.<>?',
specialSafe: '!@#%^&*_+-='
};
/**
* Generate a cryptographically secure random password
*/ export function generatePassword(options = {}) {
const { length = 32, uppercase = true, lowercase = true, digits = true, special = true, excludeAmbiguous = true } = options;
if (length < 16) {
throw new Error('Password length must be at least 16 characters');
}
// Build character pool
let charPool = '';
const selectedSets = [];
if (uppercase) {
const chars = excludeAmbiguous ? CHAR_SETS.uppercaseNoAmbiguous : CHAR_SETS.uppercase;
charPool += chars;
selectedSets.push('uppercase');
}
if (lowercase) {
const chars = excludeAmbiguous ? CHAR_SETS.lowercaseNoAmbiguous : CHAR_SETS.lowercase;
charPool += chars;
selectedSets.push('lowercase');
}
if (digits) {
const chars = excludeAmbiguous ? CHAR_SETS.digitsNoAmbiguous : CHAR_SETS.digits;
charPool += chars;
selectedSets.push('digits');
}
if (special) {
charPool += CHAR_SETS.specialSafe;
selectedSets.push('special');
}
if (charPool.length === 0) {
throw new Error('At least one character type must be enabled');
}
// Ensure password contains at least one character from each required type
const password = new Array(length);
let generated = 0;
// First, place one character from each required set
for (const setName of selectedSets){
let setChars;
switch(setName){
case 'uppercase':
setChars = uppercase ? excludeAmbiguous ? CHAR_SETS.uppercaseNoAmbiguous : CHAR_SETS.uppercase : '';
break;
case 'lowercase':
setChars = lowercase ? excludeAmbiguous ? CHAR_SETS.lowercaseNoAmbiguous : CHAR_SETS.lowercase : '';
break;
case 'digits':
setChars = digits ? excludeAmbiguous ? CHAR_SETS.digitsNoAmbiguous : CHAR_SETS.digits : '';
break;
case 'special':
setChars = special ? CHAR_SETS.specialSafe : '';
break;
default:
setChars = '';
}
if (setChars.length > 0 && generated < length) {
const index = cryptoRandom(0, setChars.length - 1);
password[generated] = setChars[index];
generated++;
}
}
// Fill remaining positions with random characters from pool
while(generated < length){
const index = cryptoRandom(0, charPool.length - 1);
password[generated] = charPool[index];
generated++;
}
// Shuffle password to avoid predictable patterns
return shuffleArray(password).join('');
}
/**
* Validate password meets security requirements
*/ export function validatePassword(password, minLength = 32) {
const errors = [];
const hasUppercase = /[A-Z]/.test(password);
const hasLowercase = /[a-z]/.test(password);
const hasDigits = /\d/.test(password);
const hasSpecial = /[!@#$%^&*()_+\-=\[\]{}|;:,.<>?]/.test(password);
if (password.length < minLength) {
errors.push(`Password must be at least ${minLength} characters long (current: ${password.length})`);
}
if (!hasUppercase) {
errors.push('Password must contain at least one uppercase letter');
}
if (!hasLowercase) {
errors.push('Password must contain at least one lowercase letter');
}
if (!hasDigits) {
errors.push('Password must contain at least one digit');
}
if (!hasSpecial) {
errors.push('Password must contain at least one special character');
}
return {
valid: errors.length === 0,
length: password.length,
hasUppercase,
hasLowercase,
hasDigits,
hasSpecial,
errors
};
}
/**
* Generate a cryptographically secure random integer in range [min, max]
*/ function cryptoRandom(min, max) {
if (min < 0 || max < 0 || min > max) {
throw new Error('Invalid range: min must be >= 0 and min must be <= max');
}
const range = max - min + 1;
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
const randomBytes_ = randomBytes(bytesNeeded);
// Convert bytes to integer and apply modulo to ensure uniform distribution
let randomValue = 0;
for(let i = 0; i < bytesNeeded; i++){
randomValue = randomValue << 8 | randomBytes_[i];
}
// Use rejection sampling to ensure uniform distribution
const limit = Math.floor(256 ** bytesNeeded / range) * range;
if (randomValue < limit) {
return min + randomValue % range;
}
// Recursively try again if we exceeded the limit (very rare)
return cryptoRandom(min, max);
}
/**
* Shuffle array in-place using Fisher-Yates algorithm
*/ function shuffleArray(array) {
const shuffled = [
...array
];
for(let i = shuffled.length - 1; i > 0; i--){
const j = cryptoRandom(0, i);
[shuffled[i], shuffled[j]] = [
shuffled[j],
shuffled[i]
];
}
return shuffled;
}
//# sourceMappingURL=password-generator.js.map