Sorcerer's IsleCode cfPassphrase / diff

b4b6e52 Extend PassphraseInfo to return information for common crypt algorithms.

 src/sorcerersisle/cfpassphrase/Impl.java  | 66 +++++++++++++++++++-
 src/sorcerersisle/cfpassphrase/Utils.java | 24 ++++++-
 2 files changed, 88 insertions(+), 2 deletions(-)
diff --git a/src/sorcerersisle/cfpassphrase/Impl.java b/src/sorcerersisle/cfpassphrase/Impl.java
index b98171d..30e3d3c 100644
--- a/src/sorcerersisle/cfpassphrase/Impl.java
+++ b/src/sorcerersisle/cfpassphrase/Impl.java
@@ -160,8 +160,72 @@ public final class Impl
 
 				return Info;
 
+			case unix_crypt_md5:
+				Parts = Hash.substring(3).split("\\$");
+				
+				Info.put("Algorithm" , "md5crypt" );
+				Info.put("Status"    , "Obsolete" );
+
+				Info.put("Salt"      , Parts[0] );
+				Info.put("Hash"      , Parts[1] );
+			
+				return Info;
+
+			case unix_crypt_nthash:
+				
+				Info.put("Algorithm" , "NT-Hash" );
+				Info.put("Status"    , "Obsolete" );
+
+				Info.put("Hash"      , Hash.substring(4) );
+			
+				return Info;
+
+			case unix_crypt_sha256:
+			case unix_crypt_sha512:
+				Parts = Hash.substring(1).split("\\$");
+				
+				Info.put("Algorithm" , "SHA-2" );
+				Info.put("Version"   , Parts[0].equals(5) ? "256" : "512");
+				Info.put("Status"    , "Unsupported" );
+
+				if ( Parts[1].startsWith("rounds=") )
+				{
+					Info.put("Rounds"    , Parts[1].split("=")[1] );
+					Info.put("Salt"      , Parts[2] );
+					Info.put("Hash"      , Parts[3] );
+				}
+				else
+				{
+					Info.put("Rounds"    , "5000" );
+					Info.put("Salt"      , Parts[1] );
+					Info.put("Hash"      , Parts[2] );
+				}
+			
+				return Info;
+
+			case sun_crypt_md5:
+				Parts = Hash.substring(5).split("\\$");
+				
+				Info.put("Algorithm" , "SunMD5" );
+				Info.put("Status"    , "Obsolete" );
+
+				if ( Parts[1].startsWith("rounds=") )
+				{
+					Info.put("Rounds"    , Parts[0].split("=")[1] );
+					Info.put("Salt"      , Parts[1] );
+					Info.put("Hash"      , Parts[2] );
+				}
+				else
+				{
+					Info.put("Rounds"    , "4096" );
+					Info.put("Salt"      , Parts[0] );
+					Info.put("Hash"      , Parts[1] );
+				}
+			
+				return Info;
+
 			default:
-				throw new Exception("Unsupported Algorithm");
+				throw new Exception("Unknown Algorithm");
 
 		}
 	}
diff --git a/src/sorcerersisle/cfpassphrase/Utils.java b/src/sorcerersisle/cfpassphrase/Utils.java
index 0a4cf47..3a1fe9f 100644
--- a/src/sorcerersisle/cfpassphrase/Utils.java
+++ b/src/sorcerersisle/cfpassphrase/Utils.java
@@ -7,6 +7,13 @@ public final class Utils
 
 	public static enum Algorithm
 	{ bcrypt , pbkdf2 , scrypt
+	// Unimplemented algorithms:
+	, unix_crypt_md5    // $1$
+	, unix_crypt_nthash // $3$
+	, unix_crypt_sha256 // $5$
+	, unix_crypt_sha512 // $6$
+	, sun_crypt_md5     // $md5
+	//
 	; public static Algorithm fromString(String Str)
 		{
 			if ( Str == null ) return DefaultAlgorithm;
@@ -22,7 +29,7 @@ public final class Utils
 		( String Hash )
 	throws Exception
 	{
-		if ( Hash.matches("^\\$2a?\\$\\d+\\$[0-9A-Za-z./]+$") )
+		if ( Hash.matches("^\\$2[axy]?\\$\\d+\\$[0-9A-Za-z./]+$") )
 			return Algorithm.bcrypt;
 
 		else if ( Hash.matches("^\\d+:[0-9a-f]+:[0-9a-f]+$") )
@@ -30,6 +37,21 @@ public final class Utils
 
 		else if ( Hash.matches("^\\$s0\\$[0-9a-z]+(?:\\$[0-9A-Za-z+=/]+){2}$") )
 			return Algorithm.scrypt;
+		
+		else if ( Hash.matches("^\\$1\\$[0-9A-Za-z./]{8}\\$[0-9A-Za-z./]{22}$") )
+			return Algorithm.unix_crypt_md5;
+
+		else if ( Hash.matches("^\\$3\\$\\$[0-9A-Fa-f]{32}$") )
+			return Algorithm.unix_crypt_nthash;
+			
+		else if ( Hash.matches("^\\$5\\$(?:rounds=\\d{1,9}\\$)?[0-9A-Za-z./]{16}\\$[0-9A-Za-z./]{43}$") )
+			return Algorithm.unix_crypt_sha256;
+			
+		else if ( Hash.matches("^\\$6\\$(?:rounds=\\d{1,9}\\$)?[0-9A-Za-z./]{16}\\$[0-9A-Za-z./]{86}$") )
+			return Algorithm.unix_crypt_sha512;
+		
+		else if ( Hash.matches("^\\$md5(?:[$,]rounds=\\d+)?\\$[./0-9A-Za-z]+\\$[./0-9A-Za-z]+$") )
+			return Algorithm.sun_crypt_md5;
 
 		else
 			throw new Exception("Unknown Algorithm Signature");