package com.citrus.citrususer;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class RandomPassword implements PasswordGenerator{
private MessageDigest md5;
/**
* Creates a new pseudo random password generator.
*/
public RandomPassword() {
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsax) {
throw new RuntimeException(nsax);
}
}
/**
* Generates a 8 character ([a-zA-Z]{8}) pseudo random password using the
* email as a seed.
*
* As a consequence, same email will result in same password. Mobile number
* is ignored and can be null.
*/
@Override
public String generate(String email, String mobile) {
PseudoRandomNumberGenerator ran = new PseudoRandomNumberGenerator(
generateSeed(email));
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 8; i++) {
builder.append(ran.nextLetter());
}
return builder.toString();
}
/**
* Generates a non-random positive number from a string.
*
* @param data
* the string to generate seed from.
* @return the value of the 3 highest bytes of the MD5 sum of data.
*/
public int generateSeed(String data) {
byte hash[] = md5.digest(data.getBytes());
md5.reset();
hash = rangeCopy(hash, hash.length - 3, hash.length);
return new BigInteger(1, hash).intValue();
}
public static byte[] rangeCopy(byte[] original, int from, int to) {
int lengthNew = to - from;
if (lengthNew < 0)
throw new IllegalArgumentException(from + " > " + to);
byte[] hash = new byte[lengthNew];
System.arraycopy(original, from, hash, 0,
Math.min(original.length - from, lengthNew));
return hash;
}
/**
* A pseudo random integer generator.
*/
public static class PseudoRandomNumberGenerator {
private int state;
/**
* Creates a new pseudo random number generator.
*
* @param seed
* the seed to start the generation from.
*/
public PseudoRandomNumberGenerator(int seed) {
this.state = seed;
}
/**
* Generates the next pseudo-random integer. The number is positive in
* the [0-max[ interval.
*
* @param max
* the exclusive upper boundary of the interval to generate
* the pseudo-random in.
* @return the next number in the pseudo-random suite modulo max.
*/
public int nextInt(int max) {
state = 7 * state % 3001;
return (state - 1) % max;
}
/**
* Generates the next pseudo-random alphabetical character. The letter
* is in the [a-zA-Z] range.
*
* @return the next letter in the pseudo-random suite.
*/
public char nextLetter() {
int n = nextInt(52);
return (char) (n + ((n < 26) ? 'A' : 'a' - 26));
}
}
}