venice-main-classic/src/com/silverwrist/venice/security/Generator.java
Eric J. Bowersox 3ee3e4abeb upgraded the internal Emailer class into the new MailSend class that can
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
2002-05-22 07:38:29 +00:00

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