do pretty much anything; emailer and stock messages are now managed through the GlobalSite; security-releated generation is now handled through the Generator class instead of several different ones
211 lines
6.7 KiB
Java
211 lines
6.7 KiB
Java
/*
|
|
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
|
* (the "License"); you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
|
|
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
|
|
* language governing rights and limitations under the License.
|
|
*
|
|
* The Original Code is the Venice Web Communities System.
|
|
*
|
|
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
|
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
|
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
package com.silverwrist.venice.security;
|
|
|
|
import java.security.MessageDigest;
|
|
import java.util.*;
|
|
|
|
public class Generator
|
|
{
|
|
/*--------------------------------------------------------------------------------
|
|
* Static data members
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
public static final int CONFIRM_MIN = 1000000;
|
|
public static final int CONFIRM_MAX = 9999999;
|
|
|
|
private static final String AUTH_ALPHABET =
|
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
|
|
private static final int AUTH_STRING_LEN = 32;
|
|
|
|
private static final String[] syllabary = {
|
|
"ba", "be", "bi", "bo", "bu",
|
|
"da", "de", "di", "do", "du",
|
|
"cha", "chi", "cho", "chu",
|
|
"fa", "fe", "fi", "fo", "fu",
|
|
"ga", "ge", "gi", "go", "gu",
|
|
"ha", "he", "hi", "ho", "hu",
|
|
"ja", "je", "ji", "jo", "ju",
|
|
"ka", "ke", "ki", "ko", "ku",
|
|
"la", "le", "li", "lo", "lu",
|
|
"ma", "me", "mi", "mo", "mu",
|
|
"na", "ne", "ni", "no", "nu",
|
|
"pa", "pe", "pi", "po", "pu",
|
|
"ra", "re", "ri", "ro", "ru",
|
|
"sa", "se", "si", "so", "su",
|
|
"sha", "she", "sho", "shu",
|
|
"ta", "te", "ti", "to", "tu",
|
|
"va", "ve", "vi", "vo", "vu",
|
|
"wa", "we", "wi", "wo", "wu",
|
|
"ya", "ye", "yi", "yo", "yu",
|
|
"za", "ze", "zi", "zo", "zu"
|
|
}; // 98 syllables
|
|
|
|
private static final char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
|
|
|
|
private static Generator self = null; // my own personal instance
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* Attributes
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
private Random rng; // my random number generator
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* Constructor
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
private Generator()
|
|
{
|
|
// Initialize the random number generator.
|
|
java.util.Date seed_date = new java.util.Date();
|
|
rng = new Random(seed_date.getTime());
|
|
|
|
} // end constructor
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* External operations
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
public final String generateRandomAuthString()
|
|
{
|
|
StringBuffer buf = new StringBuffer(AUTH_STRING_LEN);
|
|
for (int i=0; i<AUTH_STRING_LEN; i++)
|
|
buf.append(AUTH_ALPHABET.charAt(rng.nextInt(AUTH_ALPHABET.length())));
|
|
return buf.toString();
|
|
|
|
} // end generateRandomAuthString
|
|
|
|
public final int getNewConfirmationNumber()
|
|
{
|
|
return rng.nextInt(CONFIRM_MAX - CONFIRM_MIN + 1) + CONFIRM_MIN;
|
|
|
|
} // end getNewConfirmationNumber
|
|
|
|
public final int getAuthorizationNumber()
|
|
{
|
|
return rng.nextInt(Integer.MAX_VALUE);
|
|
|
|
} // end getAuthorizationNumber
|
|
|
|
public final String generateRandomPassword()
|
|
{
|
|
StringBuffer buf = new StringBuffer();
|
|
int i;
|
|
for (i=0; i<4; i++) // 4 random syllables
|
|
buf.append(syllabary[rng.nextInt(syllabary.length)]);
|
|
for (i=0; i<3; i++) // 3 random digits
|
|
buf.append(digits[rng.nextInt(digits.length)]);
|
|
return buf.toString();
|
|
// total possible number of passwords = 92,236,816,000
|
|
|
|
} // end generateRandomPassword
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* External static operations
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
public static final boolean isValidRandomAuthString(String s)
|
|
{
|
|
if (s.length()!=AUTH_STRING_LEN)
|
|
return false;
|
|
for (int i=0; i<AUTH_STRING_LEN; i++)
|
|
{ // verify each authentication character in turn
|
|
if (AUTH_ALPHABET.indexOf(s.charAt(i))<0)
|
|
return false;
|
|
|
|
} // end for
|
|
|
|
return true; // all tests passed - ship it!
|
|
|
|
} // end isValidRandomAuthString
|
|
|
|
public static final String hashPassword(String password)
|
|
{
|
|
if ((password!=null) && (password.length()>0))
|
|
{ // hash the password and save the hash value
|
|
MessageDigest hasher;
|
|
|
|
try
|
|
{ // get a hasher implementing the Secure Hashing Algorithm
|
|
hasher = MessageDigest.getInstance("SHA");
|
|
|
|
} // end try
|
|
catch (java.security.NoSuchAlgorithmException e)
|
|
{ // SHA should be a standard algorithm...if it isn't, we're h0sed
|
|
throw new RuntimeException("HOSED JRE - SHA should be a standard algorithm");
|
|
|
|
} // end catch
|
|
|
|
try
|
|
{ // update the hasher with the UTF-8 bytes of the password
|
|
hasher.update(password.getBytes("UTF8"));
|
|
|
|
} // end try
|
|
catch (java.io.UnsupportedEncodingException e)
|
|
{ // WTF? How can the JRE NOT know about UTF-8? HOW?!?
|
|
throw new RuntimeException("HOSED JRE - UTF-8 encoding should be supported");
|
|
|
|
} // end catch
|
|
|
|
// Retrieve the raw hash value (should be 160 bits, or 20 bytes)
|
|
byte[] raw_hash = hasher.digest();
|
|
|
|
// Convert the hash value to a hexadecimal string (40 chars in length)
|
|
StringBuffer hash_buf = new StringBuffer(raw_hash.length * 2);
|
|
StringBuffer tmp_buf = new StringBuffer();
|
|
String tmp;
|
|
for (int i=0; i<raw_hash.length; i++)
|
|
{ // N.B.: Integer.toHexString does not zero-pad on the left, so that's why this is
|
|
// a little complex
|
|
tmp_buf.setLength(0);
|
|
tmp_buf.append("00").append(Integer.toHexString(raw_hash[i]).trim());
|
|
tmp = tmp_buf.toString();
|
|
hash_buf.append(tmp.substring(tmp.length()-2));
|
|
|
|
} // end for
|
|
|
|
// finally, save off the password hash value
|
|
return hash_buf.toString().toUpperCase();
|
|
|
|
} // end if
|
|
else // no password
|
|
return "";
|
|
|
|
} // end hashPassword
|
|
|
|
public static final Generator get()
|
|
{
|
|
synchronized (Generator.class)
|
|
{ // create me if I don't exist
|
|
if (self==null)
|
|
self = new Generator();
|
|
|
|
} // end synchronized block
|
|
|
|
return self;
|
|
|
|
} // end get
|
|
|
|
} // end class Generator
|