How to use the 'generic' MD5. 

John has been enhanced to be able to handle MANY md5 variants easily.

'variants' of MD5 are things like:

md5($p)      (Note, $p is the password, $s will be the salt, etc)
md5(md5($p)) (Note, this is md5 of the 32 byte result of a prior md5)
md5($p.$s)   (Note, . is the concatenate operator, so $p.$s is 
              password with salt appended)
...
          
Most of the above rules are php 'style' rules, but I think in php, 
$pass is used, and $salt is used.  In this document, they have been
simplified to $p and $s.

This is done by using a new file format string:  md5_gen(#)   where
the # is a number.  John reserves numbers from md5_gen(0) up to
md5_gen(999) for 'built-in' formats.  Not all are defined at this
time, but those have been reserved.

The format of the input file lines will be:

userID:md5_gen(#)base_16_hash[$salt]

There may be a 2nd salt added in the near future, but not sure how it
will be implemented.

Here is an 'example' of the format required:

userID:md5_gen(0)28fc2782ea7ef51c1104ccf7b9bea13d

which is 'raw' md5, with a password of 1402

userID:md5_gen(6)8d8cac84f234f42e32daeb94e7cd49e8$*.*

which is in the vBulletin format:  md5(md5($p).$s), and which has a 
fixed 3 byte salt (the $*.* above is the salt signature, and the 
salt is *.*), solomon1 is the password for the above hash.  NOTE 
vBulletin is actually md5_gen(7). It is the expression format, but
puts to additional constraints on input. md5_gen(7) forces a 3 byte
salt, and it will NOT allow ':' character to be used as a separator,
since vBulletin salts can contain that character.  However, the
above md5_gen(6) works for this document, since *.* salt does not
have a ':'

Expressions can be added to john.conf (john.ini) to allow an end
user to add a new format type, without having to do ANY coding
at all.  The end user would have to learn the generic md5
primitives, and how the data is used (input data, key data,
encryption data, etc).  Also, the user would have to build
properly formatted SAMPLE test values (john requires this).
For the full 'HOW TO USE' documentation, see the john.conf.


How to build the 'test' value is beyond the scope of this readme,
but a trivial example might help.
Expression format:  md5(md5($p).md5($p))
Password test1
md5(test1) == 5a105e8b9d40e1329780d62ea2265d8a
so we want to md5 that result concatenated
so md5(md5(test1).md5(test1)) is the same as
md5(5a105e8b9d40e1329780d62ea2265d8a5a105e8b9d40e1329780d62ea2265d8a)
which equals 478b10974f15e7295883224fd286ccba
so a proper 'test' line is:
Test=md5_gen(1003)478b10974f15e7295883224fd286ccba:test1
( as can be seen in john.conf for md5_gen(1003) )

The builtiin formats that john has right now are:

------------+-------------------------+-------+------------------
Signature   | expression              | Salt  | notes
------------+-------------------------+-------+------------------
md5_gen(0)  | md5($p)                 | No    | raw-md5 
md5_gen(1)  | md5($p.$s)              | Yes   | (joomla)
md5_gen(2)  | md5(md5($p))            | No    | double md5 (e107)
md5_gen(3)  | md5(md5(md5($p)))       | No    | triple md5
md5_gen(4)  | md5($s.$p)              | Yes   | (OS Commerce)
md5_gen(5)  | md5($s.$p.$s)           | Yes   |  
md5_gen(6)  | md5(md5($p).$s)         | Yes   | 
md5_gen(7)  | md5(md5($p).$s)         | Yes   | vBulletin. 3 byte salt, salt uses ':' char
md5_gen(8)  | md5(md5($s).$p)         | Yes   | 
md5_gen(9)  | md5($s.md5($p))         | Yes   | 
md5_gen(10) | md5($s.md5($s.$p))      | Yes   | 
md5_gen(11) | md5($s.md5($p.$s))      | Yes   | 
md5_gen(12) | md5(md5($s).md5($p))    | Yes   | (IPB) NOTE NOT SSE2/MMX usable
md5_gen(13) | md5(md5($p).md5($s))    | Yes   |       NOTE NOT SSE2/MMX usable
md5_gen(14) | md5($s.md5($p).$s)      | Yes   | 
md5_gen(15) | md5($u.md5($p).$s)      | Yes   | NOTE uses UserID in hash (not working yet)
md5_gen(16) | md5(md5(md5($p).$s).$s2)| Yes   | NOTE uses 2 salts (not working yet)
md5_gen(17) | phpass ($H$ and $P$)    | Yes   | phpass and PHPbb-v3 hashes
md5_gen(18) | RESERVED                | UNK   | 
........    | RESERVED                | UNK   | 
md5_gen(999)| RESERVED                | UNK   |

The 'samples' stored in john.conf (to be used as is, or as examples) are:

md5_gen(1001) md5(md5(md5(md5($p))))
md5_gen(1002) md5(md5(md5(md5(md5($p)))))
md5_gen(1003) md5(md5($p).md5($p))
md5_gen(1004) md5(md5(md5(md5(md5(md5($p))))))
md5_gen(1005) md5(md5(md5(md5(md5(md5(md5($p)))))))
md5_gen(1006) md5(md5(md5(md5(md5(md5(md5(md5($p))))))))
md5_gen(1007) md5(md5($p).$s) [vBulletin]
md5_gen(1008) md5($p.$s) [joomla]



NOTE the documentation section of john.conf is listed here.  It shows
how to setup md5_generic functions (above 1000).  All of the primitives
are defined, the data structures are defined, the expression, flags, 
saltlen, etc.  Following the 'howto use' section, are some working
examples (this whole list is also found in john.conf).

####################################################################
####################################################################
# here are some examples of GENERIC-MD5
####################################################################
####################################################################

####################################################################
# Documenation of how to 'setup' GENERIC-MD5
####################################################################
# 
#   Variables / workspaces:
#
# keys[]     -  Array Used to stored keys (optionally used, we 'may' be able to use input field 1 array)
# input1[]   -  Array used for encryption, key appending, salt appending, etc happens to/from these
#                   NOTE if MD5GenBaseFunc__InitialLoadKeysToInput then this is used to store the keys
#                   and MUST NOT be damaged, since any later key retrieval will come from this buffer.
#                   This is done as an optimization. Thus input2 is required for additional scratch buffer work.
# output1[]  -  Array encryption happens and output is put here.  
#                   NOTE final result MUST be put here. This is what the 'hash' array is checked against.
# salt       -  the salt is put here
# input2[]   -  Array same as input 1, but a totally different array
# output2[]  -  Array same as output 2, but totally different array  (can not be used as 'final' result)
#
#   NOTE within the scratch work spaces (input1[] and input2[] arrays), we can only do things like append_keys
#   append_salt or other things.  Thus, each work space keeps track of each array element (knowing it's contents),
#   and keeps track of the length.  In the way the scripting works, we can clear them (sets lengths of all
#   elements to 0, and 'might' clear out the actual memory).  We can append to them (keys, output conversions,
#   salt, etc) or we can force set their length to 32 ('special' optimization used in conjunction with
#   MD5GenBaseFunc__InitialLoadKeys_md5crypt_ToOutput2_Base16_to_Input1).
#
#   NOTE there is NO length validation done, other than input keys are reduced to the max allowable length.
#   Thus, if building, and you attempt something like: clear_keys append_keys append_keys append_keys append_keys
#   append_keys append_keys and the keys are too long, then they will overflow.  The maximal sizes of the 
#   input arrays are 95 bytes for x86 and 54 bytes for SSE/MMX.   Above this will simply give invalid results
#   (garbage in, garbage out).
#
#####################################################################################
#
#   Function primitives, and what they do  (REQUIRED in each format section) 
#
#################
#
#    Special input flags (all flags listed later).  They have certain 'side-effects', and some have special
#    rules that MUST be maintained within the script, and thus may not be usable for all scripts.
#    These are here mostly for optimization.  They do NOT have to be used.  If not used, then when
#    john adds keys one at a time, they are placed into the array of keys.  Then, when loading keys
#    the keys are copied from the keys array, into the input1 (2) as needed.
#
#  MGF_KEYS_INPUT
#     It will not use the keys[] array, but put the keys right
#     into the input1[] array.  This buffer must not be destroyed. john will NOT use the keys[]
#     array, and later retrieval of the key will happen from here (if there are any hashes broken).
#     For this to be able to be used.
#        $pass must be at the START of the expression.  expressions like md5($s.$p) would not work, since
#             $pass is not the 'start' of the expression.  
#        the $pass expression 'may' have to be all by itself.  Thus md5($p.$s) would not work (such as joomla)
#             but md5(md5($p).$s) can be made to work.
#        The input1[] array must NOT be touched (after it is loaded).  Thus the below set of functions can NOT
#        be used in the script.
#               MD5GenBaseFunc__append_keys 
#               MD5GenBaseFunc__append_keys2
#               MD5GenBaseFunc__clean_input
#               MD5GenBaseFunc__append_salt
#               MD5GenBaseFunc__append_from_last_output2_to_input1_as_base16
#               MD5GenBaseFunc__overwrite_from_last_output2_to_input1_as_base16_no_size_fix
#               MD5GenBaseFunc__append_from_last_output_as_base16
#               MD5GenBaseFunc__overwrite_from_last_output_as_base16_no_size_fix
#               MD5GenBaseFunc__append_2nd_salt MD5GenBaseFunc__append_userid
#               MD5GenBaseFunc__append_2nd_salt
#               MD5GenBaseFunc__set_input_len_32
#               MD5GenBaseFunc__set_input_len_64
#               MD5GenBaseFunc__overwrite_salt_to_input1_no_size_fix
#               MD5GenBaseFunc__append_input_from_input2
#
#  MGF_KEYS_CRYPT_IN2
#     This will load keys into the keys[] array.  It will then perform a md5() and put the ouput
#     into output2.   This was done a signficant enhancement for forms like md5(md5($p).$s) so that we 
#     load ALL of the inner md5($p) only once, then re-used them over and over again for each new salt.
#
#  MGF_KEYS_BASE16_IN1
#     This is like the above flag, but it takes the extra step of storing the base16 conversion
#     of the md5 into input1[] array.  Due to this function, we have md5(md5($p).$s) actually working
#     FASTER than simple md5($p)  (if there are many salts).  This is a significant optimization if it can
#     be used properly.
#
#  MGF_KEYS_BASE16_IN1_Offset32
#     This flag is a not valid for SSE2 (will build a 64 byte password, and 54 bytes is max SSE2 size)
#     Psudo function that does the same work as MD5GenBaseFunc__InitialLoadKeys_md5crypt_ToOutput2_Base16_to_Input1
#     however, it loaded the hext to offset 32 (instead of the 'start' of the buffer). When done, the
#     input1[] buffers will have 64 byte passwords.  The first 32 bytes are null, and the last 
#     32 bytes are the hex values.  This function is for md5(md5($s).md5($p)) (but certainly could
#     be used for other formats.
#
#  MGF_PHPassSetup
#     Special flag used to link the salt, set_salt and set_hash members of the format object to the 'special'
#     functions for phpass encryption.
#
#################
#
#  MD5GenBaseFunc__clean_input
#     Sets lengths of all input1[] array to ZERO, and sets the memory null (memory only set in SSE2, since it does
#     not matter in x86 builds)
#
#  MD5GenBaseFunc__clean_input_kwik
#     Sets lengths of all input1[] array to ZERO. Memory not cleared.  Optimization that can be used when you KNOW
#     that the length of any of the input1 strings will never be less than they once were.  So if you load keys,
#     crypt, clean_input, then repeatedly append_base16 to input and crypt, then during that repeated set of work
#     you can call clean_kwik since ALL things being crypted, would be 32 bytes, and the single 'deep' clean would
#     get the buffers read to go, and they would not need fully cleaning again.
#
#  MD5GenBaseFunc__clean_input_full
#     This makes sure that the entire keys are set with NULL's prior to running.  This is a full 'deep' clean.
#
#  MD5GenBaseFunc__append_keys
#     append the array of keys to the array input1[]
#
#  MD5GenBaseFunc__crypt
#     performs a md5 on all elements of input1[] and places the results into output1[]  The output will be the 
#     16 byte BINARY blob of the 'raw' md5.
#
#  MD5GenBaseFunc__append_from_last_output_as_base16
#     Takes the 16 byte binary values from the output1[] array, and does a base-16 conversion, appending the
#     results into the elements of the input1[] array.  ALL of the lengths of the array1[] elements will be
#     32 bytes more than they were (the base-16 of each 16 byte binary value is 32 bytes long).
#
#  MD5GenBaseFunc__overwrite_from_last_output_as_base16_no_size_fix
#     Takes the 16 byte binary values from the output1[] array, and overwrites from byte 0 to byte 31 of each 
#     element of the input1[] array.  This is used as an optimizations for formats such as:  md5(md5($s).$p)
#     in this format, we can place the keys into input1[] at 32 bytes past the start of the buffer, and set
#     the lengths to be the length of each key + 32, and then simply call this function for each salt, to 
#     drop the 32 bytes of md5 data to the start of the strings, without touching the passwords that were 
#     already stored, or the lengths of the strings.
#
#  MD5GenBaseFunc__overwrite_salt_to_input1_no_size_fix
#     Inserts the salt to the start of the first input buffer.  DOES NOT append null bytes, nor does it
#     adjust the length of the strings.  Used if the 'top' part of input buffer 1 stays constant, and
#     the salt gets inserted to the start of input buffer (but lengths never change).
#
#  MD5GenBaseFunc__append_salt
#     Appends the salt to each element of input1[], and adjusts the length of each element.
#
#  MD5GenBaseFunc__set_input_len_16
#     Sets the length of each element of input1[] to 16.
#
#  MD5GenBaseFunc__set_input2_len_16
#     Sets the length of each element of input2[] to 16.
#
#  MD5GenBaseFunc__set_input_len_32
#     Sets the length of each element of input1[] to 32.  This was designed as is used in conjunction with
#     the funtion overwrite_from_last_output_as_base16_no_size_fix in mind, but would not
#     be the 'only' reason to use it (but is the only reason I have at this time).  This function does NOT
#     clean the input[] items prior to this.  Usually a call to clean_input would be required priot to 
#     calling this function, to make sure the buffer is 'clean'.
#
#  MD5GenBaseFunc__set_input_len_64
#     Like the above function, but sets lengths to 64 bytes.
#
#  MD5GenBaseFunc__clean_input2
#     Same as MD5GenBaseFunc__clean_input but this one works on input2[] array.
#
#  MD5GenBaseFunc__clean_input2_kwik
#     Same as MD5GenBaseFunc__clean_input_kwik but this one works on input2[] array.
#
#  MD5GenBaseFunc__append_keys2
#     Same as MD5GenBaseFunc__append_keys but this one works on input2[] array.
#
#  MD5GenBaseFunc__crypt2
#     Same as MD5GenBaseFunc__crypt but this one works on input2[] -> output2[] arrays.
#
#  MD5GenBaseFunc__append_from_last_output2_as_base16
#     Same as MD5GenBaseFunc__append_from_last_output_as_base16 but this one works on output2[] -> input2[] arrays.
#
#  MD5GenBaseFunc__overwrite_from_last_output2_as_base16_no_size_fix
#     Same as MD5GenBaseFunc__overwrite_from_last_output_as_base16_no_size_fix but this one works on output2[] -> input2[] arrays.
#
#  MD5GenBaseFunc__overwrite_salt_to_input2_no_size_fix
#     Same as MD5GenBaseFunc__overwrite_salt_to_input1_no_size_fix but this one works on salt -> input2[] arrays.
#
#  MD5GenBaseFunc__append_salt2
#     Same as MD5GenBaseFunc__append_salt but this one works on input2[] array.
#
#  MD5GenBaseFunc__set_input2_len_32
#     Same as MD5GenBaseFunc__set_input_len_32 but this one works on input2[] array.
#
#  MD5GenBaseFunc__set_input2_len_64
#     Same as MD5GenBaseFunc__set_input2_len_64 but this one works on input2[] array.
#
#  MD5GenBaseFunc__append_input1_from_CONST1
#     This will append the first constant value to the input1[] array
#  MD5GenBaseFunc__append_input1_from_CONST2
#  MD5GenBaseFunc__append_input1_from_CONST3
#  MD5GenBaseFunc__append_input1_from_CONST4
#  MD5GenBaseFunc__append_input1_from_CONST5
#  MD5GenBaseFunc__append_input1_from_CONST6
#  MD5GenBaseFunc__append_input1_from_CONST7
#  MD5GenBaseFunc__append_input1_from_CONST8
#     Same as MD5GenBaseFunc__append_input1_from_CONST1 but they load the other constant
#     values into input1.
#
#  MD5GenBaseFunc__append_input2_from_CONST1  
#     This loads the first constant value into the input2[] array
#  MD5GenBaseFunc__append_input2_from_CONST2
#  MD5GenBaseFunc__append_input2_from_CONST3
#  MD5GenBaseFunc__append_input2_from_CONST4
#  MD5GenBaseFunc__append_input2_from_CONST5
#  MD5GenBaseFunc__append_input2_from_CONST6
#  MD5GenBaseFunc__append_input2_from_CONST7
#  MD5GenBaseFunc__append_input2_from_CONST8
#     Same as MD5GenBaseFunc__append_input2_from_CONST1 but they load the other constant
#     values into input2.
#
####################
#  functions where input buffer and output buffer are different from 'each' other
#   i.e. input buffer #1 to output buffer #2, etc
####################
#
#  MD5GenBaseFunc__append_from_last_output_to_input2_as_base16
#     output1[] append -> input2[] arrays.  (note, output #1 appending to input #2, base-16)
#
#  MD5GenBaseFunc__append_from_last_output2_to_input1_as_base16
#     output2[] append -> input1[] arrays.  (note, output #2 appending to input #1, base-16)
#
#  MD5GenBaseFunc__overwrite_from_last_output_to_input2_as_base16_no_size_fix
#     output1[] overwrite start of input2[] arrays.  (note, output #1 going to start of input #2, base-16, no size 'fix')
#     like MD5GenBaseFunc__overwrite_from_last_output_as_base16_no_size_fix but different input output vars.
#
#  MD5GenBaseFunc__overwrite_from_last_output2_to_input1_as_base16_no_size_fix
#     output2[] overwrite start of input1[] arrays.  (note, output #2 going to start of input #1, base-16, no size 'fix')
#     like MD5GenBaseFunc__overwrite_from_last_output_as_base16_no_size_fix but different input output vars.
#
#  MD5GenBaseFunc__append_input_from_input2
#     Appends input2 to input   input += input2
#
#  MD5GenBaseFunc__append_input2_from_input
#     Appends input1 to input2   input2 += input
#
#
#  MD5GenBaseFunc__crypt_in1_to_out2
#     Performs the work of MD5GenBaseFunc__crypt, but uses input1[] -> output2[]
#
#  MD5GenBaseFunc__crypt_in2_to_out1
#     Performs the work of MD5GenBaseFunc__crypt, but uses input2[] -> output1[]
#
####################
#  These are special functions written SPECIFCALLY for usage by phpass code, in builtin 
#  function md5_gen(17).  These are likely NOT useful.  However, they 'are' open to be used.
####################
#
#  MD5GenBaseFunc__crypt_to_input_raw
#     Used as 'first' step of phpass crypt.  it will put 16 binary bytes of md5 encryption
#     into array1[].  It will write this to the beginning of the arrays (does not append), and
#     when done, sets ALL lengths of array1[] to 16.  Once this function is called, the keys
#     are appended (see spec for phpass encryption), which sets the length of input1[] elements
#     to 16 + strlen(keys).  Then there is a loop that calls the next function.
#
#  MD5GenBaseFunc__crypt_to_input_raw_Overwrite_NoLen
#     This function will encrypt input1[] and drop the 16 bytes of MD5 binary right back over
#     the first 16 bytes of input1[]  The length of each input1[] item is NOT touched, thus
#     whatever the length was before is what it is now. 
#
#  MD5GenBaseFunc__PHPassCrypt
#     Special function for phpass, probably not useful in john.conf scripting
#
####################
#  These functions are 'defined', but have not been implemented.
####################
#
#  MD5GenBaseFunc__append_2nd_salt
#    append salt2 to array1[]
#  MD5GenBaseFunc__append_2nd_salt2
#    append salt2 to array2[]
#  MD5GenBaseFunc__append_userid
#    append userID to array1[]
#  MD5GenBaseFunc__append_userid2
#    append userID to array2[]
#
####################################################################
#
#   Test= line(s)   (REQUIRED in each format section) 
#
#    NOTE within these lines, if there are binary values which need to
#    be inserted, then use the format of \xHH  (2 hex digits which will
#    be converted into the 1 byte).  So, \xF7 will output the single
#    byte "\xF7" which in some ASCII formats, it is the squiggly 
#    'about' equals sign.  To output some UNICODE or 'wide' type 
#    characters, you will need to know the exact bytes that are used
#    and place a \xHH for each byte.  To output the actual \ character
#    use \\   So, to output \\ use \\\\  (2 \\ which each get replaced
#    with a single \ character).  
#    NOTE that HH MUST be uppercased for the A to F values, and the 'x'
#    MUST be lowercase.
#    NOTE, you MUST use \xHH.  So, to put a ASCII(1) value, you would
#    use \x01  (not \x1 ).  
#    ALL conversions are done prior to the line being 'looked at' within
#    the parser.
#
#################
#
# The testing line is simply of this format:
#
#  test=md5_gen(#)hash[$salt]:password 
#
#  the hash listed, MUST be the hash generated for this password (and
#  salt) for the expression.  John uses this at startup to validate
#  that the format is 'valid'.  If this Test= line(s) are not right
#  john will not work.  NOTE if the format does not allow a colon
#  in the format (such as md5_gen(1007), then the exact same field
#  separator must be used in the Test= line, as what is specified
#  in the --field-separator-char=c used on the command line
#
####################################################################
#
#   Expression= line   (Optional) 
#
#################
#
#  If the Expression= line is there, then the value shown there will
#  also be used on the startup line of john.  If missing, john will
#  output md5_gen(1001)  (or whatever number was used), and if
#  Expression=, then the md5_gen(1001) will be followed by the 
#  expression line. 
#
####################################################################
#
#   Flag= line(s)   (Optional, but required IF the format needs them)
#
#################
#
#  Flags are just that, switches that tell the generic md5 parser that
#  certain things need to be handled.  One common used flag is MGF_SALTED
#  If the format is a salted hash, then this flag must be present.
#  Here is the list of flags, and what they mean, and when you should
#  use them
#
#  Flag=MGF_SALTED
#     Use this for any salted format
#
#  Flag=MGF_ColonNOTValid
#     If there is some reason why the : char should not be used by john
#     (such as the : is a valid character in the salt.  If this is
#     set, then the character to be used should be put into the Test=
#     lines, AND the user should use that on the command line
#
#  Flag=MGF_NOTSSE2Safe
#     The max encryption the SSE2 code can handle is 54 bytes.  The max
#     size encryption for the 'generic' is 125 bytes.  So, if it is
#     OBVIOUS that sse2 can not be used, due to encryption lengths, 
#     then set this flag.  An example is md5(md5($p).md5($s))  In this
#     case, will be 3 md5's.  2 of them will be over the salt, and
#     one over the password.  Thus, if the password and salt are each
#     under 54 bytes, then sse2 could be used.  HOWEVER, the 3rd md5
#     (the final one), is done against the concatenation of 2 32 byte
#     strings (the md5 results of the first 2 encryptions).  THUS we
#     KNOW this is a 64 byte string. That will not work in the current
#     SSE2 (or mmx) code, and thus, the SSE2/MMX builds can NOT be used
#     to test that format.
#
#  Flag=MGF_INPBASE64
#     If the hashes are in base-64 (such as phpass), then use this 
#     flag.  Note, the base 64 'format' used is that of phpass.  If there
#     are other orderings, then this will not work.  I know of no formats
#     in use, other than phpass (phpbb, wordpress, etc) which use base-64
#     for md5.
#
#  Flag=MGF_INPBASE64_4x6
#     If this flag is set, then the input will be base-64, where 4 bytes are
#     loaded 6 bits at a time (i.e. 16 bytes of hash).  Used in Cisco PIX-MD5
#     Thus, only the lowest 24 bits of each part of the MD5 hash are used.
#     This has to happen on the binary loader and comparison functions.
#
#  Flag=MGF_SALTED2
#     If there are 2 salts in the format, use this flag.  NOTE 2 salts
#     is defined, but has not be implemented yet in john.
#
#  Flag=MGF_USERID
#     If there is a UserID in the format, use this flag.  NOTE the UserID
#     is defined, but has not be implemented yet in john.
#
#  Flag=MGF_SALT_AS_HEX
#     This flag is for formats such as md5(md5($p).md5($s))  What this
#     does, is to return the md5($s) to john as the salt, and not simply
#     return the 'original' salt. Thus, we run md5's for the salt at
#     initialization, and never MD5 them again.  DO NOT use this for a 
#     format like md5($s.md5($p).md5($s))  In that format, you NEED 
#     the salt (along with the md5 of that salt).  This flag can not
#     be used in that instance.
#
####################################################################
#
#   SaltLen=# line   (Optional, but required IF the format needs it)
#
#################
#
#  If this is a salted hash, and ALL valid salts must be a specific
#  length (vBulletin is an example, where 3 byte salts are specified
#  and OSCommerce is another with 2 byte hashes).  If this is the
#  case, add a SaltLen=# line and john will validate, and only test
#  lines which have valid salts (i.e. right length salt is part of
#  the initial validation of the line)
#
####################################################################
#
#   MaxInputLen=# line   (Optional, but required IF the format needs it)
#
#################
#
#  If a format has a 'max' length of password (such as Cisco PIX has 
#  a max length of 16 byte PW), then this must be set.
#
####################################################################
#
#   CONST#=str    line   (Optional, but required IF the format needs it)
#
#   These lines will also use the \xHH  (or \\ for a \ ) same as the
#   'Test=' lines.
#
#################
#
#  This will allow a constant value to be 'set' and then later used
#  in the format.  So a format such as md5($p.CONSTANT.$s) can be 
#  done by setting const 1 to 'CONSTANT' (whatever that string is)
#  and then calling MD5GenBaseFunc__append_input1_from_CONST1 at the
#  proper time to insert it into the string.  
#  CONST1=str   to CONST8=str   are valid (8 constant values.)  NOTE
#  if you have 3 constants, then use CONST1, CONST2 and CONST3 (i.e.
#  pack them into the first X number constants).
#
####################################################################


####################################################################
# Simple GENERIC-MD5 type for md5($p)^^4  (i.e. 4 steps of md5 recursively) 
####################################################################
[List.Generic:md5_gen(1001)]
# expression shown will be the string:   md5_gen(1001) md5(md5(md5(md5($p))))
Expression=md5(md5(md5(md5($p))))
Flag=MGF_KEYS_INPUT
# here is the optimized 'script' to perform the md5 4 times on itself.
Func=MD5GenBaseFunc__crypt
Func=MD5GenBaseFunc__clean_input2
Func=MD5GenBaseFunc__append_from_last_output_to_input2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt_in2_to_out1
Test=md5_gen(1001)57200e13b490d4ae47d5e19be026b057:test1
Test=md5_gen(1001)c6cc44f9e7fb7efcde62ba2e627a49c6:thatsworking
Test=md5_gen(1001)0ae9549604e539a249c1fa9f5e5fb73b:test3

####################################################################
# Simple GENERIC-MD5 type for md5($p)^^5  (i.e. 5 steps of md5 recursively) 
####################################################################
[List.Generic:md5_gen(1002)]
# expression shown will be the string:   md5_gen(1002) md5(md5(md5(md5(md5($p)))))
Expression=md5(md5(md5(md5(md5($p)))))
Flag=MGF_KEYS_INPUT
# here is the optimized 'script' to perform the md5 5 times on itself.
Func=MD5GenBaseFunc__crypt
Func=MD5GenBaseFunc__clean_input2
Func=MD5GenBaseFunc__append_from_last_output_to_input2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt_in2_to_out1
# These are test strings for this format.
Test=md5_gen(1002)25de8cd0b0cf69c5b5bc19c8ee64adab:test1
Test=md5_gen(1002)a0b535420ea47849f7c2cc09a3ad0ac3:thatsworking
Test=md5_gen(1002)4cb029bd5b4ef79f785ca685caf17bf8:test3

####################################################################
# Simple GENERIC-MD5 type for md5(md5($p).md5($p)) 
####################################################################
[List.Generic:md5_gen(1003)]
# expression shown will be the string:   md5_gen(1003) md5(md5($p).md5($p))
Expression=md5(md5($p).md5($p))
# NOTE, this format does NOT work on SSE2.  It requires a md5() of a 64 byte string.
# SSE (or MMX) is limtited to 54 byte max password, due to 'enhancements'
# Thus, we need a non-sse2 safe flag.
Flag=MGF_NOTSSE2Safe
Flag=MGF_KEYS_INPUT
# here is the optimized 'script' to perform hash 'like' IPB but salt replaced with password.
Func=MD5GenBaseFunc__crypt
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output_to_input2_as_base16
Func=MD5GenBaseFunc__append_from_last_output_to_input2_as_base16
Func=MD5GenBaseFunc__crypt_in2_to_out1
# These are test strings for this format.
Test=md5_gen(1003)478b10974f15e7295883224fd286ccba:test1
Test=md5_gen(1003)18a59101e6c6fb38260d542a394ecb22:thatsworking
Test=md5_gen(1003)630b01b68b6db6fd43a751f8147d1faf:test3

####################################################################
# Simple GENERIC-MD5 type for md5($p)^^6  (i.e. 6 steps of md5 recursively)
####################################################################
[List.Generic:md5_gen(1004)]
# expression shown will be the string:   md5_gen(1004) md5(md5(md5(md5(md5(md5($p))))))
Expression=md5(md5(md5(md5(md5(md5($p))))))
Flag=MGF_KEYS_INPUT
# here is the optimized 'script' to perform the md5 6 times on itself.
Func=MD5GenBaseFunc__crypt
Func=MD5GenBaseFunc__clean_input2
Func=MD5GenBaseFunc__append_from_last_output_to_input2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt_in2_to_out1
# These are test strings for this format.
Test=md5_gen(1004)de1b991dd27fb9813e88b957a455dccd:test1
Test=md5_gen(1004)6a62cd3c4d81139f61fb2553cdef0dc7:thatsworking
Test=md5_gen(1004)a977990e521c5d1d17c6d65fdf2681b4:test3


####################################################################
# Simple GENERIC-MD5 type for md5($p)^^7  (i.e. 7 steps of md5 recursively)
####################################################################
[List.Generic:md5_gen(1005)]
# expression shown will be the string:   md5_gen(1005) md5(md5(md5(md5(md5(md5(md5($p)))))))
Expression=md5(md5(md5(md5(md5(md5(md5($p)))))))
Flag=MGF_KEYS_INPUT
# here is the optimized 'script' to perform the md5 7 times on itself.
Func=MD5GenBaseFunc__crypt
Func=MD5GenBaseFunc__clean_input2
Func=MD5GenBaseFunc__append_from_last_output_to_input2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt_in2_to_out1
# These are test strings for this format.
Test=md5_gen(1005)784c527d0d92873ff9c0773e1c35621d:test1
Test=md5_gen(1005)efcbbe6331caecf0e7f40160e65aadcc:thatsworking
Test=md5_gen(1005)abb8bdd2c6ac2dfea2b2af6f5aed5446:test3

####################################################################
# Simple GENERIC-MD5 type for md5($p)^^8  (i.e. 8 steps of md5 recursively)
####################################################################
[List.Generic:md5_gen(1006)]
# expression shown will be the string:   md5_gen(1006) md5(md5(md5(md5(md5(md5(md5(md5($p))))))))
Expression=md5(md5(md5(md5(md5(md5(md5(md5($p))))))))
Flag=MGF_KEYS_INPUT
# here is the optimized 'script' to perform the md5 8 times on itself.
Func=MD5GenBaseFunc__crypt
Func=MD5GenBaseFunc__clean_input2
Func=MD5GenBaseFunc__append_from_last_output_to_input2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt2
Func=MD5GenBaseFunc__clean_input2_kwik
Func=MD5GenBaseFunc__append_from_last_output2_as_base16
Func=MD5GenBaseFunc__crypt_in2_to_out1
# These are test strings for this format.
Test=md5_gen(1006)1ec1f32398f64cab51183f63630eceea:test1
Test=md5_gen(1006)f66b339ac21d6fd6af216f2b70aab2c9:thatsworking
Test=md5_gen(1006)e9d38522b5eeec753332e576e2e0fe5d:test3

####################################################################
# Simple GENERIC-MD5 type for vBulletin md5(md5($p).$s)   Included here to 'exercise' the script parser
####################################################################
[List.Generic:md5_gen(1007)]
# expression shown will be the string:   md5_gen(1007) md5(md5($p).$s) [vBulletin]
Expression=md5(md5($p).$s) [vBulletin]
# Flag needed here, is Salt.  There is no 'fixed' saltlen.
Flag=MGF_SALTED
Flag=MGF_ColonNOTValid
Flag=MGF_KEYS_BASE16_IN1
# vBulletin has a 'fixed' 3 byte salt, so list the fixed size
SaltLen=3
ColonChar=;
# here is the optimized 'script' to perform vBulletin hash
Func=MD5GenBaseFunc__set_input_len_32
Func=MD5GenBaseFunc__append_salt
Func=MD5GenBaseFunc__crypt
# NOTE, vBulletin is setup to 'override' the ':'.  USUALLY, it is good to use something 
# outside of the ASCII values from 0x20 to 0x7F.  0x1F is a 'good' choice, but it will
# cause john.conf to have a 'non-normal' ASCII char.  Thus for this 'simple' example, I 
# have used the ';' character.  NOTE this would have the same 'problems' as the ':' character
# if used for real, since ; is also a valid character within the salt of vBulletin.
# NOTE to run, you MUST use the command line switch:   -field-separator-char=;
Test=md5_gen(1007)daa61d77e218e42060c2fa198ac1feaf$SXB;test1
Test=md5_gen(1007)de56b00bb15d6db79204bd44383469bc$T &;thatsworking
Test=md5_gen(1007)fb685c6f469f6e549c85e4c1fb5a65a6$\\H:;test3

####################################################################
# Simple GENERIC-MD5 type for joomla md5($p.$s)   Included here to 'exercise' the script parser
####################################################################
[List.Generic:md5_gen(1008)]
# expression shown will be the string:   md5_gen(1008) md5($p.$s) [joomla]
Expression=md5($p.$s) [joomla]
# Flag needed here, is Salt.  There is no 'fixed' saltlen.
Flag=MGF_SALTED
# here is the optimized 'script' to perform the md5 8 times on itself.
Func=MD5GenBaseFunc__clean_input
Func=MD5GenBaseFunc__append_keys
Func=MD5GenBaseFunc__append_salt
Func=MD5GenBaseFunc__crypt
Test=md5_gen(1008)ed52af63d8ecf0c682442dfef5f36391$1aDNNojYGSc7pSzcdxKxhbqvLtEe4deG:test1
Test=md5_gen(1008)4fa1e9d54d89bfbe48b4c0f0ca0a3756$laxcaXPjgcdKdKEbkX1SIjHKm0gfYt1c:thatsworking
Test=md5_gen(1008)82568eeaa1fcf299662ccd59d8a12f54$BdWwFsbGtXPGc0H1TBxCrn0GasyAlJBJ:test3


####################################################################
# Simple GENERIC-MD5 type for PostOffice-MD5 md5($s.Y.$p.\xF7.$s)
#    Included here to 'exercise' the script parser (constants)
#    NOTE, the internal md5_gen(18) has a specialized crypt
#          function.  It does the same as what this script does
#          but does not have the overhead of this script work, and
#          runs 10-15% faster.
####################################################################
[List.Generic:md5_gen(1009)]
Expression=md5_gen(1009): md5($s.Y.$p.\xF7.$s) [Post.Office MD5]
Flag=MGF_SALTED
Flag=MGF_NOTSSE2Safe
Func=MD5GenBaseFunc__clean_input_kwik
Func=MD5GenBaseFunc__append_salt
Func=MD5GenBaseFunc__append_input1_from_CONST1
Func=MD5GenBaseFunc__append_keys
Func=MD5GenBaseFunc__append_input1_from_CONST2
Func=MD5GenBaseFunc__append_salt
Func=MD5GenBaseFunc__crypt
Test=md5_gen(1009)550c41c11bab48f9dbd8203ed313eef0$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:abc123
Test=md5_gen(1009)0c78bdef7d5448105cfbbc9aaa490a44$550c41c11bab48f9dbd8203ed313eef0:abc123
Test=md5_gen(1009)9be296cf73d2f548dae3cccafaff1dd9$82916963c701200625cba2acd40d6569:FRED
Test=md5_gen(1009)a0e2078f0354846ec5bc4c7d7be08a46$82916963c701200625cba2acd40d6569:
CONST1=Y
CONST2=\xF7
SaltLen=32

####################################################################
# Simple GENERIC-MD5 type for Cisco PIX hash (same as pixMD5_fmt.c
####################################################################
[List.Generic:md5_gen(1010)]
Expression=md5_gen(1010): pixMD5
Flag=MGF_INPBASE64_4x6
# has problem with MMX / SSE, so simply for now, do not allow it.
# the MGF_INPBASE64_4x6 is busted under SSE.
Flag=MGF_NOTSSE2Safe
Func=MD5GenBaseFunc__clean_input_full
Func=MD5GenBaseFunc__append_keys
Func=MD5GenBaseFunc__set_input_len_16
Func=MD5GenBaseFunc__crypt
Test=md5_gen(1010)NuLKvvWGg.x9HEKO:password
Test=md5_gen(1010).7nfVBEIEu4KbF/1:0123456789abcdef
Test=md5_gen(1010)2KFQnbNIdI.2KYOU:cisco
Test=md5_gen(1010)OMT6mXmAvGyzrCtp:test2
MaxInputLen=16

####################################################################
# Simple GENERIC-MD5 type for Cisco PIX hash with a salt.  The salt
# is the first 4 bytes of the user name.  I have made an assumption
# about PW len. I assume it maxes at 12 chars, so the full salt is
# allowed.
####################################################################
[List.Generic:md5_gen(1011)]
Expression=md5_gen(1011): pixMD5-salted
Flag=MGF_INPBASE64_4x6
# has problem with MMX / SSE, so simply for now, do not allow it.
Flag=MGF_NOTSSE2Safe
Func=MD5GenBaseFunc__clean_input_full
Func=MD5GenBaseFunc__append_keys
Func=MD5GenBaseFunc__append_salt
Func=MD5GenBaseFunc__set_input_len_16
Func=MD5GenBaseFunc__crypt
Test=md5_gen(1011)h3mJrcH0901pqX/m$alex:ripper
Test=md5_gen(1011)3USUcOPFUiMCO4Jk$cisc:cisco
Test=md5_gen(1011)lZt7HSIXw3.QP7.R$admc:CscFw-ITC!
Test=md5_gen(1011)hN7LzeyYjw12FSIU$john:cisco
Test=md5_gen(1011)7DrfeZ7cyOj/PslD$jack:cisco
MaxInputLen=12
SaltLen=4

####################################################################
# Simple GENERIC-MD5 type for PostOffice-MD5 md5($s.Y.$p.\xF7.$s)
#    Included here to 'exercise' the script parser (constants)
#    NOTE, the internal md5_gen(18) has a specialized crypt
#          function, as does this version.  This is same as md5_gen(18)
####################################################################
[List.Generic:md5_gen(1012)]
Expression=md5_gen(1012): md5($s.Y.$p.\xF7.$s) [Post.Office MD5]
Flag=MGF_SALTED
Flag=MGF_NOTSSE2Safe
Flag=MGF_POSetup
Func=MD5GenBaseFunc__POcrypt
Test=md5_gen(1012)550c41c11bab48f9dbd8203ed313eef0$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:abc123
Test=md5_gen(1012)0c78bdef7d5448105cfbbc9aaa490a44$550c41c11bab48f9dbd8203ed313eef0:abc123
Test=md5_gen(1012)9be296cf73d2f548dae3cccafaff1dd9$82916963c701200625cba2acd40d6569:FRED
Test=md5_gen(1012)a0e2078f0354846ec5bc4c7d7be08a46$82916963c701200625cba2acd40d6569:
SaltLen=32

####################################################################
# Simple GENERIC-MD5 type for phpass-MD5.  Same as md5_gen(17)
####################################################################
[List.Generic:md5_gen(1013)]
Expression=md5_gen(1013): phpass ($P$ or $H$)
Flag=MGF_SALTED
Flag=MGF_PHPassSetup
Flag=MGF_INPBASE64
Func=MD5GenBaseFunc__PHPassCrypt
Test=md5_gen(1013)jgypwqm.JsMssPLiS8YQ00$9aaaaaSXB:test1
Test=md5_gen(1013)5R3ueot5zwV.7MyzAItyg/$912345678:thatsworking
Test=md5_gen(1013)yhzfTrJXcouTpLleLSbnY/$7aaaaaSXB:test1
Test=md5_gen(1013)mwulIMWPGe6RPXG1/R8l50$712345678:thatsworking
Test=md5_gen(1013)nfKm8qpXa88RVUjLgjY/u1$7555555hh:test3
Test=md5_gen(1013)JSe8S8ufpLrsNE7utOpWc/$BaaaaaSXB:test1
Test=md5_gen(1013)aqkw6carDzQ67zCLOvVp60$B12345678:thatsworking
Test=md5_gen(1013)o2j.1E7X1NvVyEJ/QY9hX0$B555555hh:test3
Test=md5_gen(1013)Y5RwgMij0xFsUIrr33lM1/$9555555hh:test3
SaltLen=9

####################################################################
####################################################################
# END of GENERIC-MD5 examples
####################################################################
####################################################################
