Loading repository dataβ¦
Loading repository dataβ¦
aakashsakhalkar / repository
π Production-ready Android password generator library built in pure Java. Generate cryptographically secure passwords with customizable rules, required characters, custom pools, strength evaluation, and zero third-party dependencies.
A production-ready, highly configurable, cryptographically secure password generator library for Android β written in pure Java, with zero third-party dependencies.
Full control over character categories, exclusions, whitelists, required characters, custom pools, and ambiguous-character stripping β plus a built-in password strength evaluator. Built with SOLID principles and a clean, extensible architecture so new generator types (PIN, passphrase, OTP, username) can be added without touching existing code.
Most "password generator" snippets floating around either use java.util.Random
(not cryptographically secure), hardcode character sets, or offer no way to guarantee
required characters without biasing their position. SecurePasswordGen was built to solve
all three at once, as a real, reusable Android library rather than a copy-pasted utility class:
SecureRandom, and the
final password is always Fisher-Yates shuffled so required characters aren't predictably
placed at the start.Builder, and the generator figures out how.PasswordException
with a specific ErrorType, not a generic message you have to string-match.| Category | Capability |
|---|---|
| Length | Configurable length with validated min/max bounds (1β1024) |
| Categories | Independently toggle uppercase, lowercase, numbers, special characters, in any combination |
| Exclusions | Exclude individual characters even from an otherwise-enabled category |
| Whitelist | Restrict generation to an exact, explicit set of allowed characters |
| Required characters | Guarantee at least one character from each required group (per category) appears in the result |
| Custom pools | Replace the default character set for any category |
| Ambiguous stripping | Auto-exclude visually confusing characters (O0Il1S5B8), with a customizable list |
| Strength evaluation | VERY_WEAK β VERY_STRONG rating based on entropy, diversity, repetition, sequences, and known weak patterns |
| Batch generation | Generate any number of independent passwords in one call |
| Thread safety | Fully stateless, static API β safe to call from any thread |
Step 1. Add the JitPack repository to your root settings.gradle:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the dependency to your app module's build.gradle:
dependencies {
implementation 'com.github.aakashsakhalkar:SecurePasswordGen:1.0.0'
}
PasswordOptions options = new PasswordOptions.Builder()
.setLength(20)
.includeUppercase(true)
.includeLowercase(true)
.includeNumbers(true)
.includeSpecialCharacters(false)
.excludeCharacters("O0Il1")
.requireUppercase("AZ")
.requireLowercase("abc")
.requireNumbers("79")
.requireSpecial("@#")
.excludeAmbiguousCharacters(true)
.build();
String password = PasswordGenerator.generate(options);
Independently toggle uppercase, lowercase, numbers, and special characters β enable any one, any combination, or all four:
// Uppercase + numbers only
new PasswordOptions.Builder()
.setLength(16)
.includeUppercase(true)
.includeNumbers(true)
.build();
Remove individual characters even if their category is enabled:
new PasswordOptions.Builder()
.setLength(16)
.includeLowercase(true)
.excludeCharacters("aeiou")
.build();
When set, this overrides all category flags β generation draws only from this exact set:
new PasswordOptions.Builder()
.setLength(12)
.allowedCharacters("ABCXYZ123@#")
.build();
Guarantees at least one character from each non-empty required group appears in the
result. A required group must be a subset of the effective pool β if its category is
disabled, or every character in it has been excluded, generation throws
REQUIRED_CHARACTER_NOT_IN_POOL. If the combined size of all required groups exceeds the
requested length, generation throws REQUIRED_EXCEEDS_LENGTH.
new PasswordOptions.Builder()
.setLength(16)
.includeUppercase(true).includeLowercase(true).includeNumbers(true)
.requireUppercase("AMZ") // at least one of A, M, Z
.requireLowercase("akx") // at least one of a, k, x
.requireNumbers("37") // at least one of 3, 7
.build();
Replace the default set for any category, without changing which categories are enabled:
new PasswordOptions.Builder()
.setLength(16)
.includeUppercase(true).customUppercase("ABCDEFG")
.includeLowercase(true).customLowercase("abcdefg")
.includeNumbers(true).customNumbers("123456")
.includeSpecialCharacters(true).customSpecial("!@#$%^&*")
.build();
Strip visually confusing characters for better readability β useful for passwords a person has to type or read off a screen:
new PasswordOptions.Builder()
.setLength(16)
.includeUppercase(true).includeLowercase(true).includeNumbers(true)
.excludeAmbiguousCharacters(true) // strips O0Il1S5B8 by default
.customAmbiguousCharacters("O0Il1") // optional: override the default list
.build();
PasswordStrength strength = PasswordStrengthEvaluator.evaluate(password);
// VERY_WEAK, WEAK, MEDIUM, STRONG, VERY_STRONG
Scoring combines estimated Shannon entropy, the number of distinct character classes used,
the longest run of a repeated character, runs of sequential characters (abc, 321), and a
check against common weak substrings (password, qwerty, 1234, ...).
List<String> passwords = PasswordGenerator.generateMultiple(options, 10);
Every configuration or generation error throws PasswordException, which carries a typed
ErrorType so you can branch on the failure reason instead of parsing a message string:
| ErrorType | Thrown when |
|---|---|
INVALID_LENGTH | Length is outside PasswordOptions.MIN_ALLOWED_LENGTHβMAX_ALLOWED_LENGTH (1β1024) |
NO_CATEGORY_SELECTED | No category is enabled and no allowedCharacters whitelist is set |
EMPTY_CHARACTER_POOL | Every candidate character was excluded, leaving nothing to draw from |
REQUIRED_EXCEEDS_LENGTH | The combined size of all required-character groups exceeds the requested length |
INVALID_CUSTOM_POOL | A custom or allowed-character pool was set but is blank |
REQUIRED_CHARACTER_NOT_IN_POOL | A required character's category is disabled or the character was excluded |
INVALID_CONFIGURATION | The PasswordOptions object itself is null |
try {
String password = PasswordGenerator.generate(options);
} catch (PasswordException e) {
switch (e.getErrorType()) {
case NO_CATEGORY_SELECTED:
// prompt the user to pick a category
break;
case REQUIRED_EXCEEDS_LENGTH:
// shorten the required set or increase length
break;
default:
// show e.getMessage() to the user / logs
}
}
com.aakash.passwordgen
βββ PasswordOptions // Immutable config, built via nested Builder
β βββ Builder
βββ PasswordValidator // Validates config + derived state, throws PasswordException
βββ CharacterPool // Default character sets + combine/subtract/dedupe utilities
βββ PasswordUtils // SecureRandom-backed helpers (random pick, Fisher-Yates shuffle)
βββ PasswordGenerator // Orchestrates: validate β build pool β required chars β fill β shuffle
βββ PasswordStrength // Strength rating enum
βββ PasswordStrengthEvaluator // Entropy / diversity / repetition / sequence / pattern scoring
βββ PasswordException // Typed unchecked exception for all failures
Each class has a single, well-defined responsibility:
PasswordOptions never validates itself β it's a pure data holder, so it stays cheap
to construct, inspect, and reuse.PasswordValidator owns every validation rule, so rules live in one place and are
independently unit-testable.CharacterPool and PasswordUtils are stateless static utilities with no
knowledge of PasswordOptions, which keeps them reusable by future generator types.PasswordGenerator is the only class that knows the end-to-end algorithm; everything
else is a building block it composes.This separation is what makes the library open for extension (new generator types) without modification of existing, already-tested code β see Extending the Library.
The included app module is a full Material3 demo Activity exposing every configuration
option live:
Run the library's unit test suite:
./gradlew :passwordgen:testDebugUnitTest
Coverage includes: every single category and every category combination, required
characters (including the REQUIRED_EXCEEDS_LENGTH and REQUIRED_CHARACTER_NOT_IN_POOL
failure paths), specific-character exclusion, category exclusion, the allowed-characters
whitelist, custom pools, default and custom ambiguous-character stripping, every
invalid-configuration error path, minimum/maximum length edge cases, and statistical
randomness/uniquene