diff -urpN john-1.7.8-jumbo-8.orig/run/dynamic.conf john-1.7.8-jumbo-8/run/dynamic.conf
--- john-1.7.8-jumbo-8.orig/run/dynamic.conf	2011-10-04 21:00:25.000000000 +0000
+++ john-1.7.8-jumbo-8/run/dynamic.conf	2011-12-07 22:56:53.000000000 +0000
@@ -196,19 +196,34 @@ Test=$dynamic_1007$de56b00bb15d6db79204b
 Test=$dynamic_1007$fb685c6f469f6e549c85e4c1fb5a65a6$\\H:;test3
 
 ####################################################################
-# Simple DYNAMIC type for joomla md5($p.$s)   Included here to 'exercise' the script parser
+# Dynamic type for algorithm used in RADIUS User-Password attrinute md5($p.$s)
 ####################################################################
 [List.Generic:dynamic_1008]
-# expression shown will be the string:   dynamic_1008 md5($p.$s) [joomla]
-Expression=md5($p.$s) [joomla]
-# Flag needed here, is Salt.  There is no 'fixed' saltlen.
+# expression shown will be this string:
+Expression=md5($p.$s) [RADIUS User-Password]
+# Flag needed here, is Salt
 Flag=MGF_SALTED
-# here is the optimized 'script' to perform the md5 8 times on itself.
+# The salt has a fixed length of 16 bytes
+Saltlen=16
 Func=DynamicFunc__clean_input
 Func=DynamicFunc__append_keys
 Func=DynamicFunc__append_salt
 Func=DynamicFunc__crypt
-Test=$dynamic_1008$ed52af63d8ecf0c682442dfef5f36391$1aDNNojYGSc7pSzcdxKxhbqvLtEe4deG:test1
-Test=$dynamic_1008$4fa1e9d54d89bfbe48b4c0f0ca0a3756$laxcaXPjgcdKdKEbkX1SIjHKm0gfYt1c:thatsworking
-Test=$dynamic_1008$82568eeaa1fcf299662ccd59d8a12f54$BdWwFsbGtXPGc0H1TBxCrn0GasyAlJBJ:test3
+Test=$dynamic_1008$b962b0d40fc9111ce5f8efab424bad73$NormalSaltNormal:secret
+Test=$dynamic_1008$0ef808cbe6c786c56fbf8f42d8175273$HEX$followed3456:secret
+Test=$dynamic_1008$8bfccd9d67ec0bcdc38e9ae3c19a2903$FinishingwitHEX$:secret
+Test=$dynamic_1008$bf239357f3aa95508a53fe41b7e5f2e3$inthem$HEXiddle6:secret
+Test=$dynamic_1008$7fe3c4d1bf2ac68e94ee9f2bf75b9601$HEX$00000000000000000000000000000000:secret
+Test=$dynamic_1008$658bbf9f04538d6bede09a4a52a77504$HEX$626c6168003637383930313233343536:secret
 
+######################################################################
+# Dynamic Type for algorithm used in RADIUS Responses md5($p.$s)
+######################################################################
+[List.Generic:dynamic_1009]
+Expression=md5($s.$p) [RADIUS Responses]
+Flag=MGF_SALTED
+Func=DynamicFunc__clean_input
+Func=DynamicFunc__append_salt
+Func=DynamicFunc__append_keys
+Func=DynamicFunc__crypt
+Test=$dynamic_1009$0b9b9fdf75fc79d85c5b69aa1de26288$Salt:test1
diff -urpN john-1.7.8-jumbo-8.orig/src/dynamic_fmt.c john-1.7.8-jumbo-8/src/dynamic_fmt.c
--- john-1.7.8-jumbo-8.orig/src/dynamic_fmt.c	2011-11-08 22:42:11.000000000 +0000
+++ john-1.7.8-jumbo-8/src/dynamic_fmt.c	2011-12-07 22:49:35.000000000 +0000
@@ -3,7 +3,7 @@
  * in 2009. No copyright is claimed, and the software is hereby
  * placed in the public domain. In case this attempt to disclaim
  * copyright and place the software in the public domain is deemed
- * null and void, then the software is Copyright � 2009 Jim Fougeron
+ * null and void, then the software is Copyright (c) 2009 Jim Fougeron
  * and it is hereby released to the general public under the following
  * terms:
  *
@@ -578,7 +578,7 @@ static private_subformat_data curdat;
  *********************************************************************************/
 static int valid(char *ciphertext, struct fmt_main *pFmt)
 {
-	int i, cipherTextLen;
+	int i, cipherTextLen, expectedSize;
 	char *cp;
 	private_subformat_data *pPriv = pFmt->private.data;
 
@@ -650,15 +650,42 @@ static int valid(char *ciphertext, struc
 		return 0;
 	if (pPriv->dynamic_FIXED_SALT_SIZE && ciphertext[pPriv->dynamic_SALT_OFFSET-1] != '$')
 		return 0;
-	if (pPriv->dynamic_FIXED_SALT_SIZE > 0 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) != pPriv->dynamic_FIXED_SALT_SIZE) {
+    if (pPriv->dynamic_FIXED_SALT_SIZE) {
+        // compute the real salt size if needed, which will be used in the next tests
+        cp = &ciphertext[pPriv->dynamic_SALT_OFFSET] ; //start of salt string
+        expectedSize =  ( pPriv->dynamic_FIXED_SALT_SIZE > 0) ?  pPriv->dynamic_FIXED_SALT_SIZE 
+                                                              : -pPriv->dynamic_FIXED_SALT_SIZE;
+        // check for HEX$ at start of salt, followed by valid hexadecimal chars
+        if (!strncmp(cp, FMT_HEX_STR, FMT_HEX_LEN)) {
+            cp+=FMT_HEX_LEN ;
+            i=0 ;
+            while ( cp[i] && ( (('0' <= cp[i])&&(cp[i] <= '9')) ||
+                               (('a' <= cp[i])&&(cp[i] <= 'f')) ||
+                               (('A' <= cp[i])&&(cp[i] <= 'F'))    )
+                   ) ++i ;
+            
+            if (((i % 2) == 0) && 
+                ( (cp[i] == 0) || ( (cp[i]=='$') && 
+                              (cp[i+1]=='$') && 
+                             ((cp[i+2]=='2') || (cp[i+2]=='F') || (cp[i+2]=='U'))
+                ))) {                
+                // we have a valid HEX$ string,
+                //it will later be converted to binary, so let's take that into account  
+                expectedSize = FMT_HEX_LEN + 2*expectedSize;   
+            } 
+        }
+    }
+	if (pPriv->dynamic_FIXED_SALT_SIZE > 0 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) != expectedSize) {
+        // salt length should be exactly pPriv->dynamic_FIXED_SALT_SIZE
 		// check if there is a 'salt-2' or 'username', etc  If that is the case, then this is still valid.
-		if (strncmp(&ciphertext[pPriv->dynamic_SALT_OFFSET+pPriv->dynamic_FIXED_SALT_SIZE], "$$", 2))
+		// aren't we 'out of bonds' with this check if the salt was too small ?
+        if (strncmp(&ciphertext[pPriv->dynamic_SALT_OFFSET+expectedSize], "$$", 2))
 			return 0;
 	}
-	else if (pPriv->dynamic_FIXED_SALT_SIZE < -1 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) > -(pPriv->dynamic_FIXED_SALT_SIZE)) {
+	else if (pPriv->dynamic_FIXED_SALT_SIZE < -1 && strlen(&ciphertext[pPriv->dynamic_SALT_OFFSET]) > expectedSize) {
 		// check if there is a 'salt-2' or 'username', etc  If that is the case, then this is still 'valid'
-		char *cpX = mem_alloc(-(pPriv->dynamic_FIXED_SALT_SIZE) + 3);
-		strnzcpy(cpX, &ciphertext[pPriv->dynamic_SALT_OFFSET], -(pPriv->dynamic_FIXED_SALT_SIZE) + 3);
+		char *cpX = mem_alloc(expectedSize + 3);
+		strnzcpy(cpX, &ciphertext[pPriv->dynamic_SALT_OFFSET], expectedSize + 3);
 		if (!strstr(cpX, "$$")) {
 			MEM_FREE(cpX);
 			return 0;
@@ -832,10 +859,11 @@ static char *split(char *ciphertext, int
 static void set_salt(void *salt)
 {
 	char *cp;
+    int i;
 	memset(cursalt, 0, sizeof(cursalt));
 	strnzcpy(cursalt, salt, sizeof(cursalt));
 	// without this, the 3 byte salt for dynamic_7 gets 4 bytes 'sometimes'.
-	if (curdat.dynamic_FIXED_SALT_SIZE > 0)
+	if ( (curdat.dynamic_FIXED_SALT_SIZE > 0) && strncmp(cursalt, FMT_HEX_STR, FMT_HEX_LEN) )
 		cursalt[curdat.dynamic_FIXED_SALT_SIZE] = 0;
 
 	// find user, salt2, domain, host, etc, etc.
@@ -878,6 +906,29 @@ static void set_salt(void *salt)
 			}
 		}
 	}
+    
+    // detect 'HEX$' in front of salt and convert from base16 if found    
+    if (!strncmp(cursalt, FMT_HEX_STR, FMT_HEX_LEN))
+    {
+        // check if all chars after HEX$ are valid hexadecimal chars.
+        cp=&cursalt[FMT_HEX_LEN - 1];
+        while (*++cp && (atoi16[ARCH_INDEX(*cp)] != 0x7F));
+        if (*cp) return;
+        
+        //odd number of chars
+        if ((cp - &cursalt[FMT_HEX_LEN]) % 2) return; 
+        
+        saltlen=0;
+        cp=cursalt ;         
+        for (i=FMT_HEX_LEN; cursalt[i]!=0; i+=2) 
+        {
+            *cp= atoi16[ARCH_INDEX(cursalt[i])]*16 +
+                 atoi16[ARCH_INDEX(cursalt[i+1])];
+            ++cp; ++saltlen;
+        }
+        *cp=0 ;
+    }
+
 }
 
 /*********************************************************************************
diff -urpN john-1.7.8-jumbo-8.orig/src/formats.h john-1.7.8-jumbo-8/src/formats.h
--- john-1.7.8-jumbo-8.orig/src/formats.h	2011-11-08 18:22:41.000000000 +0000
+++ john-1.7.8-jumbo-8/src/formats.h	2011-12-07 21:44:09.000000000 +0000
@@ -43,6 +43,12 @@ struct fmt_main;
 /* We've already warned the user about hashes of this type being present */
 #define FMT_WARNED			0x80000000
 
+/* signature for base16 salt. If the salt starts with this str,
+ * it will be parsed as a base16 string: HEX$31324145 => '12AB'
+ */
+#define FMT_HEX_STR "HEX$"
+#define FMT_HEX_LEN 4
+
 /*
  * A password to test the methods for correct operation.
  */
diff -urpN john-1.7.8-jumbo-8.orig/src/loader.c john-1.7.8-jumbo-8/src/loader.c
--- john-1.7.8-jumbo-8.orig/src/loader.c	2011-11-08 19:18:10.000000000 +0000
+++ john-1.7.8-jumbo-8/src/loader.c	2011-12-07 23:15:15.000000000 +0000
@@ -506,11 +506,11 @@ static void ldr_load_pw_line(struct db_m
 			current_salt = db->salt_hash[salt_hash] =
 				mem_alloc_tiny(salt_size, MEM_ALIGN_WORD);
 			current_salt->next = last_salt;
-
-			current_salt->salt = mem_alloc_copy(
-				format->params.salt_size, MEM_ALIGN_WORD,
+			current_salt->salt = mem_alloc_copy( 
+                strncmp(salt, FMT_HEX_STR, FMT_HEX_LEN) ? 
+                    format->params.salt_size : FMT_HEX_LEN + 2 * format->params.salt_size, 
+				MEM_ALIGN_WORD,
 				salt);
-
 			current_salt->index = fmt_dummy_hash;
 			current_salt->list = NULL;
 			current_salt->hash = &current_salt->list;
