/*::.
==================================================================================================================================
=================================================¦ Copyright © 2007 Allen Baker ¦=================================================
                                                 +------------------------------+
File:       Password.java
Originator: Allen Baker (2007.02.01 14:26)
LayoutRev:  5
================================================================================================================================== */



/*.
==========================================================================================
Package
------------------------------------------------------------------------------------------ */
package cosmicabyss.com.lib;



/*.
==========================================================================================
Imports
------------------------------------------------------------------------------------------ */
import java.io.*;
import java.util.*;



/*::
======================================================================================================================== *//**
Instances of this class generate unique and strong passwords from user-created passwords of any strength. Given the same
user-created password, instances of this class will always generate the same strong password. The user passes the
constructor a seed XString (user-created password) which is used to generate a password XString. The password XString is
128 printable ascii characters in the range of the 95 characters from ' ' to '~'. The characters are approximately
random and approximately evenly distributed.<P>

The number of possible unique passwords is 95<SUP>128</SUP> or 1.40806e+253 possible passwords. (There are approximately
1.0e+79 atoms in the universe.)

<P>
   <DL>
      <DT>
         <B>
            Example usage:
         </B>
         <DD>
            <BLOCKQUOTE>
               <PRE id="unindent">
                  System.out.println(new Password(""               ));
                  System.out.println(new Password("xxxna"          ));
                  System.out.println(new Password("xxxs@256"       ));
                  System.out.println(new Password("xx10293847"     ));
                  System.out.println(new Password("xxccccord"      ));
                  System.out.println(new Password("sxx!@#$%^&*()ay"));

                  System.out.println();
                  System.out.println(new Password(""               ).iterate());
                  System.out.println(new Password("xxxna"          ).iterate());
                  System.out.println(new Password("xxxs@256"       ).iterate());
                  System.out.println(new Password("xx10293847"     ).iterate());
                  System.out.println(new Password("xxccccord"      ).iterate());
                  System.out.println(new Password("sxx!@#$%^&*()ay").iterate());
               </PRE>
            </BLOCKQUOTE>
         </DD>
      </DT>
      <DT>
         <B>
            View Source:
         </B>
         <DD>
            <A href="Password.java.html">
               Password.java
            </A>
         </DD>
      </DT>
      <DT>
         <B>
            Author:
         </B>
         <DD>
            <A href="mailto:sourcecode.v01@cosmicabyss.com">
               Allen Baker
            </A>
         </DD>
      </DT>
   </DL>
*//*
======================================================================================================================== */
public class Password
   {



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a Password class object.

   <P><B>Implementation: </B><A HREF="Password.java.html#000">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public Password() throws Exception
      {
      iPassword = this.thePassword(null);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a Password class object.

   <P><B>Implementation: </B><A HREF="Password.java.html#001">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type> Password(Type pSeed) throws Exception
      {
      iPassword = this.thePassword(pSeed);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method rehashes the password 1 time.

   <P><B>Implementation: </B><A HREF="Password.java.html#002">View source</A>

   @return
      A reference to this object
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public Password iterate()
      {
      return this.iterate(1);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method rehashes the password the specified number of times.

   <P><B>Implementation: </B><A HREF="Password.java.html#003">View source</A>

   @return
      A reference to this object

   @param
      pIterations is the number of times to rehash the password.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public Password iterate(int pIterations)
      {
      for (int i=0; i<pIterations; i++)
         {
         iPassword = iPassword.asciiHash();
         }
      return this;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns the password as a String.

   <P><B>Implementation: </B><A HREF="Password.java.html#004">View source</A>

   @return
      A String containing the password.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public String string()
      {
      return iPassword.string();
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns the password as a String. It is equivalent to the string() method and is here to
   override the toString() method defined by the Object class for use in String expressions.

   <P><B>Implementation: </B><A HREF="Password.java.html#005">View source</A>

   @return
      A String containing the password.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public String toString()
      {
      return this.string();
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns the password as an XString

   <P><B>Implementation: </B><A HREF="Password.java.html#006">View source</A>

   @return
      An XString containing the password.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public XString xstring()
      {
      return iPassword;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method sets the ConsoleStream for this object.

   <P><B>Implementation: </B><A HREF="Password.java.html#007">View source</A>

   @return
      A reference to this object

   @param
      pConsole is a ConsoleStream through which this objects sends its output.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public Password setOut(ConsoleStream pConsole)
      {
      cOut = pConsole;
      return this;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method ...

   <P><B>Implementation: </B><A HREF="Password.java.html#008">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public Password test() throws Exception
      {
      cOut.titledPrintf
         (
         "\"HELLO WORLD!\"",
         "%s  %s  %s",
         "I'm an object of the", CLASS_NAME, "class, and I approved this message."
         );
      return this;
      }



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Protected  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Private  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*.
   ==========================================================================================
   Class Constants
      <BLOCKQUOTE>
         <PRE id="unindent">
            CLASS_NAME    : the name of this class
            DFLT_LINE_LEN : the default line length for word wrapping
            DFLT_SEED     : default password seed
         </PRE>
      </BLOCKQUOTE>
   ------------------------------------------------------------------------------------------ */
   private static final XString  CLASS_NAME    = new XString(Password.class.getName());
   private static final int      DFLT_LINE_LEN = ConsoleMessage.defaultLineLength();
   private static final XString  DFLT_SEED     = new XString("mYCRxHEWtfPXINYvjioNyfsAE6KRBSXXtJBuURtY60MEUFaF7rhQatuMMDwbo0ULeny2nhOGsO4HHuE8YzkYXmvbVPT58FtpD4gByKVlS9MjS4JrnoBZkpB7160qzo6W");
   /*.
   ==========================================================================================
   <BLOCKQUOTE>
      <PRE id="unindent">
         private static final XString  DFLT_SEED     = new XString("mYCRxHEWtfPXINYvjioNyfsAE6KRBSXXtJBuURtY60MEUFaF7rhQatuMMDwbo0ULeny2nhOGsO4HHuE8YzkYXmvbVPT58FtpD4gByKVlS9MjS4JrnoBZkpB7160qzo6W");
         private static final XString  DFLT_SEED     = new XString("DorymyrmexInsanus");
      </PRE>
   </BLOCKQUOTE>
   ------------------------------------------------------------------------------------------ */
   /*.
   ==========================================================================================
   Class variables
      cOut : console output.
   ------------------------------------------------------------------------------------------ */
   private static ConsoleStream  cOut = ConsoleStream.getSingleton();
   /*.
   ==========================================================================================
   Instance variables
         iPassword:
            Where we store the password. (not secure for public use)
   ------------------------------------------------------------------------------------------ */
   private XString  iPassword = null;



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method generates a password from the specified seed

   <P><B>Implementation: </B><A HREF="Password.java.html#009">View source</A>

   @return
      A XString containing the newly generated password.

   @param
      pSeed is the seed from which a password is generated.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   private <Type> XString thePassword(Type pSeed) throws Exception
      {
      /*.
      ==========================================================================================
      Set the seed value
      ------------------------------------------------------------------------------------------ */
      XString  seed = null;
      if (pSeed == null)
         {
         seed = DFLT_SEED;
         }
      else
         {
         if (pSeed instanceof Password) seed = ((Password)pSeed).xstring();
         else                           seed = XString.toXString(pSeed);
         }
      /*.
      ==========================================================================================
      Compute the pasword
      ------------------------------------------------------------------------------------------ */
      return new Digest("SHA-512",seed).xstring().asciiHash();
      }



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Inner Classes  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Public Static Methods  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method allows this class file to be unit tested as a standalone application. It's the method
   that's called when the class is invoked from the command line by using the java application launcher
   - "java". Main() is not a required method, but the practice of putting one in each class and
   wrapping class test code within it allows easy unit testing of the class; and main does not need to
   be removed when testing is complete.

   <P>
      <DL>
         <DT>
            <B>
               Command line usage:
            </B>
            <DD>
               Java cosmicabyss.com.lib.Password
            </DD>
         </DT>
      </DL>

   <P><B>Implementation: </B><A HREF="Password.java.html#010">View source</A>

   @param
      pArgs contains the command line arguments with which this class was invoked as an application.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static void main(String[] pArgs) throws Exception
      {
      /*.
      ==========================================================================================
      Greetings !
      ------------------------------------------------------------------------------------------ */
      cOut.banner(CLASS_NAME);
      /*.
      ==========================================================================================
      Create an object and send its output to the ConsoleStream
      ------------------------------------------------------------------------------------------ */
      Password  obj = new Password();
      /*.
      ==========================================================================================
      Test code
      ------------------------------------------------------------------------------------------ */
      obj.test();
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */

      cOut.println("         1         2         3         4         5         6         7         8         9         0         1         2         3         4");
      cOut.println("12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");

      cOut.setLineLength(150);
      cOut.println(new Password(                 ));
      cOut.println(new Password(""               ));
      cOut.println(new Password("1"              ));
      cOut.println(new Password("ABCDEDCBA"      ));
      cOut.println(new Password("My Password"    ));
      cOut.println(new Password("sxx!@#$%^&*()Ly"));

      cOut.println();
      cOut.println(new Password(                 ).iterate());
      cOut.println(new Password(""               ).iterate());
      cOut.println(new Password("1"              ).iterate());
      cOut.println(new Password("ABCDEDCBA"      ).iterate());
      cOut.println(new Password("My Password"    ).iterate());
      cOut.println(new Password("sxx!@#$%^&*()Ly").iterate());

      cOut.println();
      cOut.println(UMath.average((new Password(                 ).xstring().getBytes())));
      cOut.println(UMath.average((new Password(""               ).xstring().getBytes())));
      cOut.println(UMath.average((new Password("1"              ).xstring().getBytes())));
      cOut.println(UMath.average((new Password("ABCDEDCBA"      ).xstring().getBytes())));
      cOut.println(UMath.average((new Password("My Password"    ).xstring().getBytes())));
      cOut.println(UMath.average((new Password("sxx!@#$%^&*()Ly").xstring().getBytes())));

      cOut.println();
      cOut.println(UMath.average((new Password(                 ).iterate().xstring().getBytes())));
      cOut.println(UMath.average((new Password(""               ).iterate().xstring().getBytes())));
      cOut.println(UMath.average((new Password("1"              ).iterate().xstring().getBytes())));
      cOut.println(UMath.average((new Password("ABCDEDCBA"      ).iterate().xstring().getBytes())));
      cOut.println(UMath.average((new Password("My Password"    ).iterate().xstring().getBytes())));
      cOut.println(UMath.average((new Password("sxx!@#$%^&*()Ly").iterate().xstring().getBytes())));

      cOut.println();
      cOut.println(UMath.stdDev((new Password(                 ).xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password(""               ).xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password("1"              ).xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password("ABCDEDCBA"      ).xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password("My Password"    ).xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password("sxx!@#$%^&*()Ly").xstring().getBytes())));

      cOut.println();
      cOut.println(UMath.stdDev((new Password(                 ).iterate().xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password(""               ).iterate().xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password("1"              ).iterate().xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password("ABCDEDCBA"      ).iterate().xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password("My Password"    ).iterate().xstring().getBytes())));
      cOut.println(UMath.stdDev((new Password("sxx!@#$%^&*()Ly").iterate().xstring().getBytes())));
      }



   }  // class Password



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Notes  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */