xypriss-security
Version:
XyPriss Security is an advanced JavaScript security library designed for enterprise applications. It provides military-grade encryption, secure data structures, quantum-resistant cryptography, and comprehensive security utilities for modern web applicatio
367 lines (363 loc) • 14.3 kB
JavaScript
;
var randomCore = require('../random/random-core.js');
require('../random/random-types.js');
require('crypto');
require('../random/random-sources.js');
require('nehonix-uri-processor');
require('../../utils/memory/index.js');
require('../../types.js');
require('../random/random-security.js');
var passwordSecurity = require('./password-security.js');
var swlist = require('./swlist.js');
/**
* 🔐 Password Generator Module
*
* Secure password generation with customizable requirements
*/
/**
* Secure password generation
*/
class PasswordGenerator {
constructor(config) {
this.config = config;
this.security = new passwordSecurity.PasswordSecurity(config);
}
/**
* Update configuration
*/
updateConfig(config) {
this.config = config;
this.security.updateConfig(config);
}
/**
* Generate a secure password
*/
generate(options = {}) {
const opts = this.mergeOptions(options);
let attempts = 0;
const maxAttempts = 100;
while (attempts < maxAttempts) {
const password = this.generatePassword(opts);
const strength = this.security.analyzeStrength(password);
if (strength.score >= opts.minStrengthScore) {
return {
password,
strength,
metadata: {
generatedAt: Date.now(),
algorithm: "xypriss-secure-random",
entropy: strength.entropy,
},
};
}
attempts++;
}
throw new Error("Unable to generate password meeting strength requirements");
}
/**
* Generate multiple passwords
*/
generateBatch(count, options = {}) {
if (count <= 0 || count > 1000) {
throw new Error("Count must be between 1 and 1000");
}
const results = [];
for (let i = 0; i < count; i++) {
results.push(this.generate(options));
}
return results;
}
/**
* Generate passphrase (word-based password)
*/
generatePassphrase(options = {}) {
const opts = {
wordCount: 4,
separator: "-",
includeNumbers: true,
includeSymbols: false,
minStrengthScore: 70,
...options,
};
// Comprehensive EFF word list for maximum security (2048 words for 11 bits of entropy per word)
const words = this.getSecureWordList();
let attempts = 0;
const maxAttempts = 50;
while (attempts < maxAttempts) {
const selectedWords = [];
// Use cryptographically secure random selection with no duplicates
const usedIndices = new Set();
for (let i = 0; i < opts.wordCount; i++) {
let randomIndex;
let wordAttempts = 0;
// Ensure no duplicate words in the passphrase
do {
randomIndex = randomCore.SecureRandom.getSecureRandomInt(0, words.length - 1);
wordAttempts++;
} while (usedIndices.has(randomIndex) && wordAttempts < 50);
usedIndices.add(randomIndex);
selectedWords.push(words[randomIndex]);
}
// Randomly capitalize some words for additional entropy
const capitalizedWords = selectedWords.map((word) => {
if (randomCore.SecureRandom.getSecureRandomBoolean()) {
return word.charAt(0).toUpperCase() + word.slice(1);
}
return word;
});
let passphrase = capitalizedWords.join(opts.separator);
// Add numbers if requested (use larger range for better entropy)
if (opts.includeNumbers) {
const number = randomCore.SecureRandom.getSecureRandomInt(100, 9999);
passphrase += opts.separator + number;
}
// Add symbols if requested (use more diverse symbols)
if (opts.includeSymbols) {
const symbols = "!@#$%^&*()_+-=[]{}|;:,.<>?";
const symbolCount = randomCore.SecureRandom.getSecureRandomInt(1, 3);
let symbolString = "";
for (let i = 0; i < symbolCount; i++) {
const randomSymbol = symbols[randomCore.SecureRandom.getSecureRandomInt(0, symbols.length - 1)];
symbolString += randomSymbol;
}
passphrase += symbolString;
}
const strength = this.security.analyzeStrength(passphrase);
// Calculate theoretical entropy for passphrase
const wordEntropy = opts.wordCount * Math.log2(words.length);
const numberEntropy = opts.includeNumbers ? Math.log2(9900) : 0; // 100-9999 range
const symbolEntropy = opts.includeSymbols
? Math.log2(26 * 26 * 26)
: 0; // Up to 3 symbols
const totalEntropy = wordEntropy + numberEntropy + symbolEntropy;
if (strength.score >= opts.minStrengthScore && totalEntropy >= 50) {
return {
password: passphrase,
strength: {
...strength,
entropy: Math.max(strength.entropy, totalEntropy),
},
metadata: {
generatedAt: Date.now(),
algorithm: "xypriss-passphrase-eff",
entropy: totalEntropy,
},
};
}
attempts++;
}
throw new Error("Unable to generate passphrase meeting strength requirements after maximum attempts");
}
/**
* Generate PIN (numeric password)
*/
generatePIN(length = 6) {
if (length < 4 || length > 20) {
throw new Error("PIN length must be between 4 and 20");
}
let pin = "";
for (let i = 0; i < length; i++) {
pin += randomCore.SecureRandom.getSecureRandomInt(0, 9).toString();
}
// Ensure PIN doesn't have obvious patterns
if (this.hasObviousPattern(pin)) {
return this.generatePIN(length); // Retry
}
return pin;
}
/**
* Generate memorable password (pronounceable)
*/
generateMemorable(options = {}) {
const opts = {
length: 12,
includeNumbers: true,
includeSymbols: false,
minStrengthScore: 60,
...options,
};
// Consonants and vowels for pronounceable passwords
const consonants = "bcdfghjklmnpqrstvwxyz";
const vowels = "aeiou";
const numbers = "0123456789";
const symbols = "!@#$%^&*";
let attempts = 0;
const maxAttempts = 50;
while (attempts < maxAttempts) {
let password = "";
let useConsonant = true;
// Generate base pronounceable part
for (let i = 0; i < opts.length - 2; i++) {
if (useConsonant) {
password +=
consonants[randomCore.SecureRandom.getSecureRandomInt(0, consonants.length - 1)];
}
else {
password +=
vowels[randomCore.SecureRandom.getSecureRandomInt(0, vowels.length - 1)];
}
useConsonant = !useConsonant;
}
// Add numbers if requested
if (opts.includeNumbers) {
password +=
numbers[randomCore.SecureRandom.getSecureRandomInt(0, numbers.length - 1)];
}
// Add symbols if requested
if (opts.includeSymbols) {
password +=
symbols[randomCore.SecureRandom.getSecureRandomInt(0, symbols.length - 1)];
}
// Capitalize some letters randomly
password = password
.split("")
.map((char) => {
if (char.match(/[a-z]/) &&
randomCore.SecureRandom.getSecureRandomBoolean()) {
return char.toUpperCase();
}
return char;
})
.join("");
const strength = this.security.analyzeStrength(password);
if (strength.score >= opts.minStrengthScore) {
return {
password,
strength,
metadata: {
generatedAt: Date.now(),
algorithm: "xypriss-memorable",
entropy: strength.entropy,
},
};
}
attempts++;
}
throw new Error("Unable to generate memorable password meeting strength requirements");
}
// ===== PRIVATE HELPER METHODS =====
mergeOptions(options) {
return {
length: 16,
includeUppercase: true,
includeLowercase: true,
includeNumbers: true,
includeSymbols: true,
excludeSimilar: true,
minStrengthScore: 80,
customCharset: "",
excludeChars: "",
requireAll: true,
...options,
};
}
generatePassword(options) {
let charset = "";
// Build character set
if (options.customCharset) {
charset = options.customCharset;
}
else {
if (options.includeUppercase) {
charset += options.excludeSimilar
? "ABCDEFGHJKLMNPQRSTUVWXYZ"
: "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
if (options.includeLowercase) {
charset += options.excludeSimilar
? "abcdefghjkmnpqrstuvwxyz"
: "abcdefghijklmnopqrstuvwxyz";
}
if (options.includeNumbers) {
charset += options.excludeSimilar ? "23456789" : "0123456789";
}
if (options.includeSymbols) {
charset += "!@#$%^&*()_+-=[]{}|;:,.<>?";
}
}
// Remove excluded characters
if (options.excludeChars) {
for (const char of options.excludeChars) {
charset = charset.replace(new RegExp(char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), "");
}
}
if (charset.length === 0) {
throw new Error("No valid characters available for password generation");
}
// Generate password
let password = "";
for (let i = 0; i < options.length; i++) {
const randomIndex = randomCore.SecureRandom.getSecureRandomInt(0, charset.length - 1);
password += charset[randomIndex];
}
// Ensure all required character types are present if requireAll is true
if (options.requireAll && !options.customCharset) {
password = this.ensureAllCharacterTypes(password, options);
}
return password;
}
ensureAllCharacterTypes(password, options) {
const chars = password.split("");
if (options.includeUppercase && !/[A-Z]/.test(password)) {
const upperChars = options.excludeSimilar
? "ABCDEFGHJKLMNPQRSTUVWXYZ"
: "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const randomIndex = randomCore.SecureRandom.getSecureRandomInt(0, chars.length - 1);
chars[randomIndex] =
upperChars[randomCore.SecureRandom.getSecureRandomInt(0, upperChars.length - 1)];
}
if (options.includeLowercase && !/[a-z]/.test(password)) {
const lowerChars = options.excludeSimilar
? "abcdefghjkmnpqrstuvwxyz"
: "abcdefghijklmnopqrstuvwxyz";
const randomIndex = randomCore.SecureRandom.getSecureRandomInt(0, chars.length - 1);
chars[randomIndex] =
lowerChars[randomCore.SecureRandom.getSecureRandomInt(0, lowerChars.length - 1)];
}
if (options.includeNumbers && !/[0-9]/.test(password)) {
const numberChars = options.excludeSimilar
? "23456789"
: "0123456789";
const randomIndex = randomCore.SecureRandom.getSecureRandomInt(0, chars.length - 1);
chars[randomIndex] =
numberChars[randomCore.SecureRandom.getSecureRandomInt(0, numberChars.length - 1)];
}
if (options.includeSymbols && !/[^A-Za-z0-9]/.test(password)) {
const symbolChars = "!@#$%^&*()_+-=[]{}|;:,.<>?";
const randomIndex = randomCore.SecureRandom.getSecureRandomInt(0, chars.length - 1);
chars[randomIndex] =
symbolChars[randomCore.SecureRandom.getSecureRandomInt(0, symbolChars.length - 1)];
}
return chars.join("");
}
hasObviousPattern(pin) {
// Check for sequential numbers
for (let i = 0; i < pin.length - 2; i++) {
const a = parseInt(pin[i]);
const b = parseInt(pin[i + 1]);
const c = parseInt(pin[i + 2]);
if (b === a + 1 && c === b + 1)
return true;
if (b === a - 1 && c === b - 1)
return true;
}
// Check for repeated digits
if (/(\d)\1{2,}/.test(pin))
return true;
// Check for common patterns
const commonPatterns = ["1234", "4321", "1111", "0000", "1212"];
return commonPatterns.some((pattern) => pin.includes(pattern));
}
/**
* Returns a comprehensive word list for secure passphrase generation
* Based on EFF's long wordlist for maximum security (2048 words = 11 bits entropy per word)
*/
getSecureWordList() {
// EFF Long Wordlist - 2048 carefully selected words
// Each word provides 11 bits of entropy (2^11 = 2048)
// Words are 3-9 characters, easy to type, and memorable
return swlist.SWLIST;
}
}
exports.PasswordGenerator = PasswordGenerator;
//# sourceMappingURL=password-generator.js.map