Import pwgen classes
This commit is contained in:
parent
8c885882dc
commit
d2a252a06b
4 changed files with 439 additions and 0 deletions
206
app/src/main/java/com/zeapo/pwdstore/pwgen/pw_phonemes.java
Normal file
206
app/src/main/java/com/zeapo/pwdstore/pwgen/pw_phonemes.java
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
package com.zeapo.pwdstore.pwgen;
|
||||||
|
|
||||||
|
public class pw_phonemes {
|
||||||
|
private static final int CONSONANT = 0x0001;
|
||||||
|
private static final int VOWEL = 0x0002;
|
||||||
|
private static final int DIPTHONG = 0x0004;
|
||||||
|
private static final int NOT_FIRST = 0x0008;
|
||||||
|
|
||||||
|
private static final element elements[] = {
|
||||||
|
new element("a", VOWEL),
|
||||||
|
new element("ae", VOWEL | DIPTHONG),
|
||||||
|
new element("ah", VOWEL | DIPTHONG),
|
||||||
|
new element("ai", VOWEL | DIPTHONG),
|
||||||
|
new element("b", CONSONANT),
|
||||||
|
new element("c", CONSONANT),
|
||||||
|
new element("ch", CONSONANT | DIPTHONG),
|
||||||
|
new element("d", CONSONANT),
|
||||||
|
new element("e", VOWEL),
|
||||||
|
new element("ee", VOWEL | DIPTHONG),
|
||||||
|
new element("ei", VOWEL | DIPTHONG),
|
||||||
|
new element("f", CONSONANT),
|
||||||
|
new element("g", CONSONANT),
|
||||||
|
new element("gh", CONSONANT | DIPTHONG | NOT_FIRST),
|
||||||
|
new element("h", CONSONANT),
|
||||||
|
new element("i", VOWEL),
|
||||||
|
new element("ie", VOWEL | DIPTHONG),
|
||||||
|
new element("j", CONSONANT),
|
||||||
|
new element("k", CONSONANT),
|
||||||
|
new element("l", CONSONANT),
|
||||||
|
new element("m", CONSONANT),
|
||||||
|
new element("n", CONSONANT),
|
||||||
|
new element("ng", CONSONANT | DIPTHONG | NOT_FIRST),
|
||||||
|
new element("o", VOWEL),
|
||||||
|
new element("oh", VOWEL | DIPTHONG),
|
||||||
|
new element("oo", VOWEL | DIPTHONG),
|
||||||
|
new element("p", CONSONANT),
|
||||||
|
new element("ph", CONSONANT | DIPTHONG),
|
||||||
|
new element("qu", CONSONANT | DIPTHONG),
|
||||||
|
new element("r", CONSONANT),
|
||||||
|
new element("s", CONSONANT),
|
||||||
|
new element("sh", CONSONANT | DIPTHONG),
|
||||||
|
new element("t", CONSONANT),
|
||||||
|
new element("th", CONSONANT | DIPTHONG),
|
||||||
|
new element("u", VOWEL),
|
||||||
|
new element("v", CONSONANT),
|
||||||
|
new element("w", CONSONANT),
|
||||||
|
new element("x", CONSONANT),
|
||||||
|
new element("y", CONSONANT),
|
||||||
|
new element("z", CONSONANT)
|
||||||
|
};
|
||||||
|
|
||||||
|
private static class element {
|
||||||
|
String str;
|
||||||
|
int flags;
|
||||||
|
element(String str, int flags) {
|
||||||
|
this.str = str;
|
||||||
|
this.flags = flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int NUM_ELEMENTS = elements.length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a human-readable password.
|
||||||
|
*
|
||||||
|
* @param size length of password to generate
|
||||||
|
* @param pwFlags flag field where set bits indicate conditions the
|
||||||
|
* generated password must meet
|
||||||
|
* <table summary="bits of flag field">
|
||||||
|
* <tr><td>Bit</td><td>Condition</td></tr>
|
||||||
|
* <tr><td>0</td><td>include at least one number</td></tr>
|
||||||
|
* <tr><td>1</td><td>include at least one uppercase letter</td></tr>
|
||||||
|
* <tr><td>2</td><td>include at least one symbol</td></tr>
|
||||||
|
* <tr><td>3</td><td>don't include ambiguous characters</td></tr>
|
||||||
|
* </table>
|
||||||
|
* @return the generated password
|
||||||
|
*/
|
||||||
|
public static String phonemes(int size, int pwFlags) {
|
||||||
|
String password;
|
||||||
|
int curSize, i, length, flags, featureFlags, prev, shouldBe;
|
||||||
|
boolean first;
|
||||||
|
String str;
|
||||||
|
char cha;
|
||||||
|
|
||||||
|
do {
|
||||||
|
password = "";
|
||||||
|
featureFlags = pwFlags;
|
||||||
|
curSize = 0;
|
||||||
|
prev = 0;
|
||||||
|
first = true;
|
||||||
|
|
||||||
|
shouldBe = randnum.number(2) == 1 ? VOWEL : CONSONANT;
|
||||||
|
|
||||||
|
while (curSize < size) {
|
||||||
|
i = randnum.number(NUM_ELEMENTS);
|
||||||
|
str = elements[i].str;
|
||||||
|
length = str.length();
|
||||||
|
flags = elements[i].flags;
|
||||||
|
// Filter on the basic type of the next element
|
||||||
|
if ((flags & shouldBe) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Handle the NOT_FIRST flag
|
||||||
|
if (first && (flags & NOT_FIRST) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Don't allow VOWEL followed a Vowel/Dipthong pair
|
||||||
|
if ((prev & VOWEL) > 0 && (flags & VOWEL) > 0
|
||||||
|
&& (flags & DIPTHONG) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Don't allow us to overflow the buffer
|
||||||
|
if (length > size - curSize) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// OK, we found an element which matches our criteria, let's do
|
||||||
|
// it
|
||||||
|
password += str;
|
||||||
|
|
||||||
|
// Handle UPPERS
|
||||||
|
if ((pwFlags & pwgen.UPPERS) > 0) {
|
||||||
|
if ((first || (flags & CONSONANT) > 0)
|
||||||
|
&& (randnum.number(10) < 2)) {
|
||||||
|
int index = password.length() - length;
|
||||||
|
password = password.substring(0, index)
|
||||||
|
+ str.toUpperCase();
|
||||||
|
featureFlags &= ~pwgen.UPPERS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle the AMBIGUOUS flag
|
||||||
|
if ((pwFlags & pwgen.AMBIGUOUS) > 0) {
|
||||||
|
for (char ambiguous : pwgen.AMBIGUOUS_STR.toCharArray()) {
|
||||||
|
if (password.contains(String.valueOf(ambiguous))) {
|
||||||
|
password = password.substring(0, curSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (password.length() == curSize)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
curSize += length;
|
||||||
|
|
||||||
|
// Time to stop?
|
||||||
|
if (curSize >= size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Handle DIGITS
|
||||||
|
if ((pwFlags & pwgen.DIGITS) > 0) {
|
||||||
|
if (!first && (randnum.number(10) < 3)) {
|
||||||
|
String val;
|
||||||
|
do {
|
||||||
|
cha = Character.forDigit(randnum.number(10), 10);
|
||||||
|
val = String.valueOf(cha);
|
||||||
|
} while ((pwFlags & pwgen.AMBIGUOUS) > 0
|
||||||
|
&& pwgen.AMBIGUOUS_STR.contains(val));
|
||||||
|
password += val;
|
||||||
|
curSize++;
|
||||||
|
|
||||||
|
featureFlags &= ~pwgen.DIGITS;
|
||||||
|
|
||||||
|
first = true;
|
||||||
|
prev = 0;
|
||||||
|
shouldBe = randnum.number(2) == 1 ? VOWEL : CONSONANT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle SYMBOLS
|
||||||
|
if ((pwFlags & pwgen.SYMBOLS) > 0) {
|
||||||
|
if (!first && (randnum.number(10) < 2)) {
|
||||||
|
String val;
|
||||||
|
int num;
|
||||||
|
do {
|
||||||
|
num = randnum.number(pwgen.SYMBOLS_STR.length());
|
||||||
|
cha = pwgen.SYMBOLS_STR.toCharArray()[num];
|
||||||
|
val = String.valueOf(cha);
|
||||||
|
} while ((pwFlags & pwgen.AMBIGUOUS) > 0
|
||||||
|
&& pwgen.AMBIGUOUS_STR.contains(val));
|
||||||
|
password += val;
|
||||||
|
curSize++;
|
||||||
|
|
||||||
|
featureFlags &= ~pwgen.SYMBOLS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK, figure out what the next element should be
|
||||||
|
if (shouldBe == CONSONANT) {
|
||||||
|
shouldBe = VOWEL;
|
||||||
|
} else {
|
||||||
|
if ((prev & VOWEL) > 0 || (flags & DIPTHONG) > 0
|
||||||
|
|| (randnum.number(10) > 3)) {
|
||||||
|
shouldBe = CONSONANT;
|
||||||
|
} else {
|
||||||
|
shouldBe = VOWEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev = flags;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
} while ((featureFlags & (pwgen.UPPERS | pwgen.DIGITS | pwgen.SYMBOLS))
|
||||||
|
> 0);
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
}
|
69
app/src/main/java/com/zeapo/pwdstore/pwgen/pw_rand.java
Normal file
69
app/src/main/java/com/zeapo/pwdstore/pwgen/pw_rand.java
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package com.zeapo.pwdstore.pwgen;
|
||||||
|
|
||||||
|
public class pw_rand {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a completely random password.
|
||||||
|
*
|
||||||
|
* @param size length of password to generate
|
||||||
|
* @param pwFlags flag field where set bits indicate conditions the
|
||||||
|
* generated password must meet
|
||||||
|
* <table summary ="bits of flag field">
|
||||||
|
* <tr><td>Bit</td><td>Condition</td></tr>
|
||||||
|
* <tr><td>0</td><td>include at least one number</td></tr>
|
||||||
|
* <tr><td>1</td><td>include at least one uppercase letter</td></tr>
|
||||||
|
* <tr><td>2</td><td>include at least one symbol</td></tr>
|
||||||
|
* <tr><td>3</td><td>don't include ambiguous characters</td></tr>
|
||||||
|
* <tr><td>4</td><td>don't include vowels</td></tr>
|
||||||
|
* </table>
|
||||||
|
* @return the generated password
|
||||||
|
*/
|
||||||
|
public static String rand(int size, int pwFlags) {
|
||||||
|
String password = "";
|
||||||
|
char cha;
|
||||||
|
int i, featureFlags, num;
|
||||||
|
String val;
|
||||||
|
|
||||||
|
String bank = "";
|
||||||
|
if ((pwFlags & pwgen.DIGITS) > 0) {
|
||||||
|
bank += pwgen.DIGITS_STR;
|
||||||
|
}
|
||||||
|
if ((pwFlags & pwgen.UPPERS) > 0) {
|
||||||
|
bank += pwgen.UPPERS_STR;
|
||||||
|
}
|
||||||
|
bank += pwgen.LOWERS_STR;
|
||||||
|
if ((pwFlags & pwgen.SYMBOLS) > 0) {
|
||||||
|
bank += pwgen.SYMBOLS_STR;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
featureFlags = pwFlags;
|
||||||
|
i = 0;
|
||||||
|
while (i < size) {
|
||||||
|
num = randnum.number(bank.length());
|
||||||
|
cha = bank.toCharArray()[num];
|
||||||
|
val = String.valueOf(cha);
|
||||||
|
if ((pwFlags & pwgen.AMBIGUOUS) > 0
|
||||||
|
&& pwgen.AMBIGUOUS_STR.contains(val)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((pwFlags & pwgen.NO_VOWELS) > 0
|
||||||
|
&& pwgen.VOWELS_STR.contains(val)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
password += val;
|
||||||
|
i++;
|
||||||
|
if (pwgen.DIGITS_STR.contains(val)) {
|
||||||
|
featureFlags &= ~pwgen.DIGITS;
|
||||||
|
}
|
||||||
|
if (pwgen.UPPERS_STR.contains(val)) {
|
||||||
|
featureFlags &= ~pwgen.UPPERS;
|
||||||
|
}
|
||||||
|
if (pwgen.SYMBOLS_STR.contains(val)) {
|
||||||
|
featureFlags &= ~pwgen.SYMBOLS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ((featureFlags & (pwgen.UPPERS | pwgen.DIGITS | pwgen.SYMBOLS))
|
||||||
|
> 0);
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
}
|
138
app/src/main/java/com/zeapo/pwdstore/pwgen/pwgen.java
Normal file
138
app/src/main/java/com/zeapo/pwdstore/pwgen/pwgen.java
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
package com.zeapo.pwdstore.pwgen;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class pwgen {
|
||||||
|
static final int DIGITS = 0x0001;
|
||||||
|
static final int UPPERS = 0x0002;
|
||||||
|
static final int SYMBOLS = 0x0004;
|
||||||
|
static final int AMBIGUOUS = 0x0008;
|
||||||
|
static final int NO_VOWELS = 0x0010;
|
||||||
|
|
||||||
|
static final String DIGITS_STR = "0123456789";
|
||||||
|
static final String UPPERS_STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
static final String LOWERS_STR = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
static final String SYMBOLS_STR = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||||
|
static final String AMBIGUOUS_STR = "B8G6I1l0OQDS5Z2";
|
||||||
|
static final String VOWELS_STR = "01aeiouyAEIOUY";
|
||||||
|
|
||||||
|
// No a, c, n, h, H, C, 1, N
|
||||||
|
private static final String pwOptions = "0ABsvy";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets password generation preferences.
|
||||||
|
*
|
||||||
|
* @param ctx context from which to retrieve SharedPreferences from
|
||||||
|
* preferences file 'pwgen'
|
||||||
|
* @param argv options for password generation
|
||||||
|
* <table summary="options for password generation">
|
||||||
|
* <tr><td>Option</td><td>Description</td></tr>
|
||||||
|
* <tr><td>0</td><td>don't include numbers</td></tr>
|
||||||
|
* <tr><td>A</td><td>don't include uppercase letters</td></tr>
|
||||||
|
* <tr><td>B</td><td>don't include ambiguous charactersl</td></tr>
|
||||||
|
* <tr><td>s</td><td>generate completely random passwords</td></tr>
|
||||||
|
* <tr><td>v</td><td>don't include vowels</td></tr>
|
||||||
|
* <tr><td>y</td><td>include at least one symbol</td></tr>
|
||||||
|
* </table>
|
||||||
|
* @param numArgv numerical options for password generation: length of
|
||||||
|
* generated passwords followed by number of passwords to
|
||||||
|
* generate
|
||||||
|
* @return <code>false</code> if a numerical options is invalid,
|
||||||
|
* <code>true</code> otherwise
|
||||||
|
*/
|
||||||
|
public static boolean setPrefs(Context ctx, ArrayList<String> argv
|
||||||
|
, int... numArgv) {
|
||||||
|
SharedPreferences prefs
|
||||||
|
= ctx.getSharedPreferences("pwgen", Context.MODE_PRIVATE);
|
||||||
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
|
|
||||||
|
for (char option : pwOptions.toCharArray()) {
|
||||||
|
if (argv.contains(String.valueOf(option))) {
|
||||||
|
editor.putBoolean(String.valueOf(option), true);
|
||||||
|
argv.remove(String.valueOf(option));
|
||||||
|
} else {
|
||||||
|
editor.putBoolean(String.valueOf(option), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < numArgv.length && i < 2; i++) {
|
||||||
|
if (numArgv[i] <= 0) {
|
||||||
|
// Invalid password length or number of passwords
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String name = i == 0 ? "length" : "num";
|
||||||
|
editor.putInt(name, numArgv[i]);
|
||||||
|
}
|
||||||
|
editor.apply();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates passwords using the preferences set by
|
||||||
|
* {@link #setPrefs(Context, ArrayList, int...)}.
|
||||||
|
*
|
||||||
|
* @param ctx context from which to retrieve SharedPreferences from
|
||||||
|
* preferences file 'pwgen'
|
||||||
|
* @return list of generated passwords
|
||||||
|
*/
|
||||||
|
public static ArrayList<String> generate(Context ctx) {
|
||||||
|
SharedPreferences prefs
|
||||||
|
= ctx.getSharedPreferences("pwgen", Context.MODE_PRIVATE);
|
||||||
|
|
||||||
|
boolean phonemes = true;
|
||||||
|
int pwgenFlags = DIGITS | UPPERS;
|
||||||
|
|
||||||
|
for (char option : pwOptions.toCharArray()) {
|
||||||
|
if (prefs.getBoolean(String.valueOf(option), false)) {
|
||||||
|
switch(option) {
|
||||||
|
case '0':
|
||||||
|
pwgenFlags &= ~DIGITS;
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
pwgenFlags &= ~UPPERS;
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
pwgenFlags |= AMBIGUOUS;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
phonemes = false;
|
||||||
|
// pwgenFlags = DIGITS | UPPERS;
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
pwgenFlags |= SYMBOLS;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
phonemes = false;
|
||||||
|
pwgenFlags |= NO_VOWELS; // | DIGITS | UPPERS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int length = prefs.getInt("length", 8);
|
||||||
|
if (length < 5) {
|
||||||
|
phonemes = false;
|
||||||
|
}
|
||||||
|
if (length <= 2) {
|
||||||
|
pwgenFlags &= ~UPPERS;
|
||||||
|
}
|
||||||
|
if (length <= 1) {
|
||||||
|
pwgenFlags &= ~DIGITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<String> passwords = new ArrayList<>();
|
||||||
|
int num = prefs.getInt("num", 1);
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
if (phonemes) {
|
||||||
|
passwords.add(pw_phonemes.phonemes(length, pwgenFlags));
|
||||||
|
} else {
|
||||||
|
passwords.add(pw_rand.rand(length, pwgenFlags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return passwords;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
26
app/src/main/java/com/zeapo/pwdstore/pwgen/randnum.java
Normal file
26
app/src/main/java/com/zeapo/pwdstore/pwgen/randnum.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package com.zeapo.pwdstore.pwgen;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
public class randnum {
|
||||||
|
private static SecureRandom random;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
random = SecureRandom.getInstance("SHA1PRNG");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new SecurityException("SHA1PRNG not available", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random number n, where 0 <= n < maxNum.
|
||||||
|
*
|
||||||
|
* @param maxNum the bound on the random number to be returned
|
||||||
|
* @return the generated random number
|
||||||
|
*/
|
||||||
|
public static int number(int maxNum) {
|
||||||
|
return random.nextInt(maxNum);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue