04bb783 Add initial code.
readme.md | 12 ++
src/sorcerersisle/cfpassphrase/Impl.java (new) | 158 ++++++++++++++++++++
src/sorcerersisle/cfpassphrase/Utils.java (new) | 60 ++++++++
src/sorcerersisle/cfpassphrase/cfPassphrase.java (new) | 41 +++++
src/sorcerersisle/cfpassphrase/coldfusion/Passphrase.cfc (new) | 77 ++++++++++
src/sorcerersisle/cfpassphrase/coldfusion/Passphrase.cfm (new) | 106 +++++++++++++
src/sorcerersisle/cfpassphrase/coldfusion/PassphraseCheck.java (new) | 26 ++++
src/sorcerersisle/cfpassphrase/coldfusion/PassphraseHash.java (new) | 39 +++++
src/sorcerersisle/cfpassphrase/coldfusion/PassphraseInfo.java (new) | 30 ++++
src/sorcerersisle/cfpassphrase/openbd/PassphraseCheck.java (new) | 46 ++++++
src/sorcerersisle/cfpassphrase/openbd/PassphraseHash.java (new) | 52 +++++++
src/sorcerersisle/cfpassphrase/openbd/PassphraseInfo.java (new) | 47 ++++++
src/sorcerersisle/cfpassphrase/openbd/PassphraseTag.java (new) | 81 ++++++++++
src/sorcerersisle/cfpassphrase/openbd/cfPassphrasePlugin.java (new) | 42 ++++++
src/sorcerersisle/cfpassphrase/railo/PassphraseCheck.java (new) | 40 +++++
src/sorcerersisle/cfpassphrase/railo/PassphraseHash.java (new) | 56 +++++++
src/sorcerersisle/cfpassphrase/railo/PassphraseInfo.java (new) | 43 ++++++
src/sorcerersisle/cfpassphrase/railo/PassphraseTag.java (new) | 92 ++++++++++++
src/sorcerersisle/cfpassphrase/railo/cfPassphrase.fld (new) | 40 +++++
src/sorcerersisle/cfpassphrase/railo/cfPassphrase.tld (new) | 61 ++++++++
20 files changed, 1149 insertions(+)
diff --git a/readme.md b/readme.md
index 80769fa..614a28a 100644
--- a/readme.md
+++ b/readme.md
@@ -26,6 +26,18 @@ REQUIREMENTS
cfPassphrase is intended to run on any CFML engine.
+At present, it has been tested with:
+
+* ColdFusion 10 (10,0,0,282462)
+* ColdFusion 9 (9,0,1,274733)
+* OpenBD 3.1 (nightly 2013-03-12)
+* Railo 4.0 (4.0.2.002)
+
+It may or not work with other versions.
+
+Please log any issues found:
+https://github.com/boughtonp/cfpassphrase/issues
+
LICENSING
---------
diff --git a/src/sorcerersisle/cfpassphrase/Impl.java b/src/sorcerersisle/cfpassphrase/Impl.java
new file mode 100644
index 0000000..c4fec89
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/Impl.java
@@ -0,0 +1,158 @@
+package sorcerersisle.cfpassphrase;
+
+import mindrot.jbcrypt.BCrypt;
+import crackstation.PBKDF2.PasswordHash;
+import com.lambdaworks.crypto.SCryptUtil;
+import java.util.Map;
+import java.util.HashMap;
+
+
+public final class Impl
+{
+
+
+ public static String hash
+ ( String Passphrase
+ , String Algorithm
+ , Map<String,Object> AlgorithmParams
+ )
+ throws Exception
+ {
+
+ switch ( Utils.Algorithm.fromString(Algorithm) )
+ {
+
+ case bcrypt:
+ Integer Rounds = Utils.StructGetInt(AlgorithmParams,"Rounds",16);
+
+ String Salt = ( Rounds == null )
+ ? BCrypt.gensalt()
+ : BCrypt.gensalt(Rounds)
+ ;
+
+ return BCrypt.hashpw
+ ( Passphrase
+ , Salt
+ );
+
+ case pbkdf2:
+ return PasswordHash.createHash
+ ( Passphrase
+ , Utils.StructGetInt(AlgorithmParams,"Iterations",86000)
+ , Utils.StructGetInt(AlgorithmParams,"SaltBytes",24)
+ , Utils.StructGetInt(AlgorithmParams,"HashBytes",24)
+ );
+
+ case scrypt:
+ return SCryptUtil.scrypt
+ ( Passphrase
+ , Utils.StructGetInt(AlgorithmParams,"CpuCost",2^16)
+ , Utils.StructGetInt(AlgorithmParams,"MemoryCost",8)
+ , Utils.StructGetInt(AlgorithmParams,"Parallelization",1)
+ );
+
+ default:
+ throw new Exception("Unsupported Algorithm");
+
+ }
+ }
+
+
+ public static Boolean check
+ ( String Passphrase
+ , String Hash
+ , String Algorithm
+ )
+ throws Exception
+ {
+ switch
+ ( Algorithm == null
+ ? Utils.identifyAlgorithm(Hash)
+ : Utils.Algorithm.fromString(Algorithm)
+ )
+ {
+
+ case bcrypt:
+ return BCrypt.checkpw
+ ( Passphrase
+ , Hash
+ );
+
+ case pbkdf2:
+ return PasswordHash.validatePassword
+ ( Passphrase
+ , Hash
+ );
+
+ case scrypt:
+ return SCryptUtil.check
+ ( Passphrase
+ , Hash
+ );
+
+ default:
+ throw new Exception("Unsupported Algorithm");
+
+ }
+ }
+
+
+ public static Map<String,String> info
+ ( String Hash
+ , String Algorithm
+ )
+ throws Exception
+ {
+ String[] Parts;
+ Map<String,String> Info = new HashMap<String,String>();
+
+ switch
+ ( Algorithm == null
+ ? Utils.identifyAlgorithm(Hash)
+ : Utils.Algorithm.fromString(Algorithm)
+ )
+ {
+
+ case bcrypt:
+ Parts = Hash.substring(1).split("\\$");
+
+ Info.put("Algorithm" , "bcrypt" );
+ Info.put("Version" , Parts[0] );
+ Info.put("Rounds" , Parts[1] );
+ Info.put("Salt" , Parts[2].substring(0,16) );
+ Info.put("Hash" , Parts[2].substring(16) );
+
+ return Info;
+
+ case pbkdf2:
+ Parts = Hash.split(":");
+
+ Info.put("Algorithm" , "pbkdf2" );
+ Info.put("Iterations" , Parts[0] );
+ Info.put("Salt" , Parts[1] );
+ Info.put("Hash" , Parts[2] );
+
+ return Info;
+
+ case scrypt:
+ Parts = Hash.substring(2).split("\\$");
+ long Params = Long.parseLong(Parts[1],16);
+
+ Info.put("Algorithm" , "scrypt" );
+ Info.put("Version" , Parts[0] );
+ Info.put("CpuCost" , String.valueOf(Math.round((Math.pow(2, Params >> 16 & 0xffff)))) );
+ Info.put("MemoryCost" , String.valueOf(Params >> 8 & 0xff) );
+ Info.put("Parallelization" , String.valueOf(Params & 0xff) );
+ Info.put("Salt" , Parts[2] );
+ Info.put("Hash" , Parts[3] );
+
+ return Info;
+
+ default:
+ throw new Exception("Unsupported Algorithm");
+
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/Utils.java b/src/sorcerersisle/cfpassphrase/Utils.java
new file mode 100644
index 0000000..0a4cf47
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/Utils.java
@@ -0,0 +1,60 @@
+package sorcerersisle.cfpassphrase;
+
+import java.util.Map;
+
+public final class Utils
+{
+
+ public static enum Algorithm
+ { bcrypt , pbkdf2 , scrypt
+ ; public static Algorithm fromString(String Str)
+ {
+ if ( Str == null ) return DefaultAlgorithm;
+ try { return valueOf(Str.toLowerCase());}
+ catch (Exception ex){return null;}
+ }
+ }
+
+ static Algorithm DefaultAlgorithm = Algorithm.bcrypt;
+
+
+ static Algorithm identifyAlgorithm
+ ( String Hash )
+ throws Exception
+ {
+ if ( Hash.matches("^\\$2a?\\$\\d+\\$[0-9A-Za-z./]+$") )
+ return Algorithm.bcrypt;
+
+ else if ( Hash.matches("^\\d+:[0-9a-f]+:[0-9a-f]+$") )
+ return Algorithm.pbkdf2;
+
+ else if ( Hash.matches("^\\$s0\\$[0-9a-z]+(?:\\$[0-9A-Za-z+=/]+){2}$") )
+ return Algorithm.scrypt;
+
+ else
+ throw new Exception("Unknown Algorithm Signature");
+ }
+
+
+ static Integer StructGetInt
+ ( Map<String,Object> Struct
+ , String KeyName
+ , Integer Default
+ )
+ throws Exception
+ {
+ if ( Struct == null || ! Struct.containsKey(KeyName) )
+ return Default;
+
+ Object Value = Struct.get(KeyName);
+
+ if ( Value instanceof Integer )
+ return (Integer) Value;
+ else if ( Value instanceof Double )
+ return (int) Math.round( (Double)Value );
+ else
+ return Integer.valueOf( (String)Value );
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/cfPassphrase.java b/src/sorcerersisle/cfpassphrase/cfPassphrase.java
new file mode 100644
index 0000000..93fc527
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/cfPassphrase.java
@@ -0,0 +1,41 @@
+package sorcerersisle.cfpassphrase;
+
+import java.io.IOException;
+import javax.swing.JOptionPane;
+
+
+public final class cfPassphrase
+{
+
+ public static void main
+ ( String[] Args )
+ {
+ String Msg =
+ "cfPassphrase v0.0.000\n"
+ + "\n"
+ + "Project Info: http://sorcerersisle.com/projects:cfpassphrase.html\n"
+ + "Install Docs: https://github.com/boughtonp/cfpassphrase/wiki/Installation\n"
+ ;
+
+
+ if (isJavaw() )
+ JOptionPane.showMessageDialog(null,Msg);
+ else
+ System.out.println(Msg);
+ }
+
+
+ private static boolean isJavaw()
+ {
+ try
+ {
+ System.in.available();
+ return false;
+ }
+ catch (IOException e)
+ {
+ return true;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/coldfusion/Passphrase.cfc b/src/sorcerersisle/cfpassphrase/coldfusion/Passphrase.cfc
new file mode 100644
index 0000000..d0dbbec
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/coldfusion/Passphrase.cfc
@@ -0,0 +1,77 @@
+<cfcomponent output=false >
+
+
+ <cffunction name="Hash" returntype="String" output=false access="public">
+ <cfargument name="Passphrase" type="String" required />
+ <cfargument name="Algorithm" type="String" optional />
+ <cfargument name="AlgorithmParams" type="Struct" optional />
+
+ <cfset var JavaObj = createObject( 'java' , "sorcerersisle.cfpassphrase.coldfusion.PassphraseHash" ) />
+
+ <cfif StructKeyExists(Arguments,'AlgorithmParams')>
+ <cfif NOT StructKeyExists(Arguments,'Algorithm')>
+ <cfthrow
+ type = "cfPassphrase.ColdFusion.Cfc.MissingArgument.Algorithm"
+ message = "You must specify the [Algorithm] argument when [AlgorithmParams] is specified."
+ />
+ </cfif>
+ <cfreturn JavaObj.call
+ ( Arguments.Passphrase
+ , Arguments.Algorithm
+ , Arguments.AlgorithmParams
+ )/>
+ <cfelseif StructKeyExists(Arguments,'Algorithm')>
+ <cfreturn JavaObj.call
+ ( Arguments.Passphrase
+ , Arguments.Algorithm
+ )/>
+ <cfelse>
+ <cfreturn JavaObj.call
+ ( Arguments.Passphrase
+ )/>
+ </cfif>
+ </cffunction>
+
+
+ <cffunction name="Check" returntype="String" output=false access="public">
+ <cfargument name="Passphrase" type="String" required />
+ <cfargument name="Hash" type="String" required />
+ <cfargument name="Algorithm" type="String" optional />
+
+ <cfset var JavaObj = createObject( 'java' , "sorcerersisle.cfpassphrase.coldfusion.PassphraseCheck" ) />
+
+ <cfif StructKeyExists(Arguments,'Algorithm')>
+ <cfreturn JavaObj.call
+ ( Arguments.Passphrase
+ , Arguments.Hash
+ , Arguments.Algorithm
+ )/>
+ <cfelse>
+ <cfreturn JavaObj.call
+ ( Arguments.Passphrase
+ , Arguments.Hash
+ )/>
+ </cfif>
+ </cffunction>
+
+
+ <cffunction name="Info" returntype="Struct" output=false access="public">
+ <cfargument name="Hash" type="String" required />
+ <cfargument name="Algorithm" type="String" optional />
+
+ <cfset var JavaObj = createObject( 'java' , "sorcerersisle.cfpassphrase.coldfusion.PassphraseInfo" ) />
+
+ <cfif StructKeyExists(Arguments,'Algorithm')>
+ <cfreturn JavaObj.call
+ ( Arguments.Hash
+ , Arguments.Algorithm
+ )/>
+ <cfelse>
+ <cfreturn JavaObj.call
+ ( Arguments.Hash
+ )/>
+ </cfif>
+ </cffunction>
+
+
+</cfcomponent>
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/coldfusion/Passphrase.cfm b/src/sorcerersisle/cfpassphrase/coldfusion/Passphrase.cfm
new file mode 100644
index 0000000..d8cff33
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/coldfusion/Passphrase.cfm
@@ -0,0 +1,106 @@
+<cfif NOT StructKeyExists(Attributes,'Action')>
+ <cfthrow
+ type = "cfPassphrase.ColdFusion.Tag.MissingAttribute.Action"
+ message = "You must specify the [Action] attribute. Accepted values are 'hash', 'check', or 'info'."
+ />
+</cfif>
+<cfif NOT StructKeyExists(Attributes,'Variable')>
+ <cfthrow
+ type = "cfPassphrase.ColdFusion.Tag.MissingAttribute.Variable"
+ message = "You must specify the [Variable] attribute."
+ />
+</cfif>
+<cfif NOT StructKeyExists(Attributes,'Passphrase')>
+ <cfthrow
+ type = "cfPassphrase.ColdFusion.Tag.MissingAttribute.Passphrase"
+ message = "You must specify the [Passphrase] attribute."
+ />
+</cfif>
+
+<cfswitch expression=#Attributes.Action# >
+
+ <cfcase value="hash">
+ <cfset JavaObj = createObject( 'java' , "sorcerersisle.cfpassphrase.coldfusion.PassphraseHash" ) />
+
+ <cfif StructKeyExists(Attributes,'AlgorithmParams')>
+ <cfif NOT StructKeyExists(Attributes,'Algorithm')>
+ <cfthrow
+ type = "cfPassphrase.ColdFusion.Tag.MissingAttribute.Algorithm"
+ message = "You must specify the [Algorithm] attribute when [AlgorithmParams] is specified."
+ />
+ </cfif>
+ <cfset Caller[Attributes.Variable] = JavaObj.call
+ ( Attributes.Passphrase
+ , Attributes.Algorithm
+ , Attributes.AlgorithmParams
+ )/>
+ <cfelseif StructKeyExists(Attributes,'Algorithm')>
+ <cfset Caller[Attributes.Variable] = JavaObj.call
+ ( Attributes.Passphrase
+ , Attributes.Algorithm
+ )/>
+ <cfelse>
+ <cfset Caller[Attributes.Variable] = JavaObj.call
+ ( Attributes.Passphrase
+ )/>
+ </cfif>
+ </cfcase>
+
+ <cfcase value="check">
+ <cfif NOT StructKeyExists(Attributes,'Hash')>
+ <cfthrow
+ type = "cfPassphrase.ColdFusion.Tag.MissingAttribute.Hash"
+ message = "You must specify the [Hash] attribute."
+ />
+ </cfif>
+
+ <cfset JavaObj = createObject( 'java' , "sorcerersisle.cfpassphrase.coldfusion.PassphraseCheck" ) />
+
+ <cfif StructKeyExists(Attributes,'Algorithm')>
+ <cfset Caller[Attributes.Variable] = JavaObj.call
+ ( Attributes.Passphrase
+ , Attributes.Hash
+ , Attributes.Algorithm
+ )/>
+ <cfelse>
+ <cfset Caller[Attributes.Variable] = JavaObj.call
+ ( Attributes.Passphrase
+ , Attributes.Hash
+ )/>
+ </cfif>
+
+ </cfcase>
+
+ <cfcase value="info">
+ <cfif NOT StructKeyExists(Attributes,'Hash')>
+ <cfthrow
+ type = "cfPassphrase.ColdFusion.Tag.MissingAttribute.Hash"
+ message = "You must specify the [Hash] attribute."
+ />
+ </cfif>
+
+ <cfset JavaObj = createObject( 'java' , "sorcerersisle.cfpassphrase.coldfusion.PassphraseInfo" ) />
+
+ <cfif StructKeyExists(Attributes,'Algorithm')>
+ <cfset Caller[Attributes.Variable] = JavaObj.call
+ ( Attributes.Hash
+ , Attributes.Algorithm
+ )/>
+ <cfelse>
+ <cfset Caller[Attributes.Variable] = JavaObj.call
+ ( Attributes.Hash
+ )/>
+ </cfif>
+
+ </cfcase>
+
+ <cfdefaultcase>
+ <cfthrow
+ type = "cfPassphrase.ColdFusion.Tag.InvalidAttribute.Action"
+ message = "Invalid value for [Action] attribute. Accepted values are 'hash', 'check', or 'info'."
+ />
+ </cfdefaultcase>
+
+</cfswitch>
+
+<cfexit method="exitTag" />
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/coldfusion/PassphraseCheck.java b/src/sorcerersisle/cfpassphrase/coldfusion/PassphraseCheck.java
new file mode 100644
index 0000000..255fbab
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/coldfusion/PassphraseCheck.java
@@ -0,0 +1,26 @@
+package sorcerersisle.cfpassphrase.coldfusion;
+
+import sorcerersisle.cfpassphrase.*;
+
+
+public final class PassphraseCheck
+{
+
+
+ public static Boolean call
+ ( String Passphrase , String Hash )
+ throws Exception
+ { return call(Passphrase,Hash,null); }
+
+
+ public static Boolean call
+ ( String Passphrase
+ , String Hash
+ , String Algorithm
+ )
+ throws Exception
+ {
+ return Impl.check(Passphrase,Hash,Algorithm);
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/coldfusion/PassphraseHash.java b/src/sorcerersisle/cfpassphrase/coldfusion/PassphraseHash.java
new file mode 100644
index 0000000..29b7fda
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/coldfusion/PassphraseHash.java
@@ -0,0 +1,39 @@
+package sorcerersisle.cfpassphrase.coldfusion;
+
+import sorcerersisle.cfpassphrase.*;
+import coldfusion.runtime.Struct;
+import java.util.Map;
+
+
+public final class PassphraseHash
+{
+
+
+ public static String call
+ ( String Passphrase )
+ throws Exception
+ { return call(Passphrase,null,null); }
+
+ public static String call
+ ( String Passphrase , String Algorithm )
+ throws Exception
+ { return call(Passphrase,Algorithm,null); }
+
+
+ @SuppressWarnings("unchecked")
+ public static String call
+ ( String Passphrase
+ , String Algorithm
+ , Struct AlgorithmParams
+ )
+ throws Exception
+ {
+ return Impl.hash
+ ( Passphrase
+ , Algorithm
+ , (Map<String,Object>) AlgorithmParams
+ );
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/coldfusion/PassphraseInfo.java b/src/sorcerersisle/cfpassphrase/coldfusion/PassphraseInfo.java
new file mode 100644
index 0000000..19e9272
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/coldfusion/PassphraseInfo.java
@@ -0,0 +1,30 @@
+package sorcerersisle.cfpassphrase.coldfusion;
+
+import sorcerersisle.cfpassphrase.*;
+import coldfusion.runtime.Struct;
+
+
+public final class PassphraseInfo
+{
+
+
+ public static Struct call
+ ( String Passphrase )
+ throws Throwable
+ { return call(Passphrase,null); }
+
+
+ public static Struct call
+ ( String Hash
+ , String Algorithm
+ )
+ throws Throwable
+ {
+ Struct Result = new Struct();
+
+ Result.putAll(Impl.info(Hash,Algorithm));
+
+ return Result;
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/openbd/PassphraseCheck.java b/src/sorcerersisle/cfpassphrase/openbd/PassphraseCheck.java
new file mode 100644
index 0000000..c9c0310
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/openbd/PassphraseCheck.java
@@ -0,0 +1,46 @@
+package sorcerersisle.cfpassphrase.openbd;
+
+import sorcerersisle.cfpassphrase.*;
+import com.naryx.tagfusion.expression.function.functionBase;
+import com.naryx.tagfusion.cfm.engine.cfArgStructData;
+import com.naryx.tagfusion.cfm.engine.cfBooleanData;
+import com.naryx.tagfusion.cfm.engine.cfSession;
+import com.naryx.tagfusion.cfm.engine.cfmRunTimeException;
+
+@SuppressWarnings("serial")
+public final class PassphraseCheck
+ extends functionBase
+{
+
+ public PassphraseCheck()
+ {
+ min = 2;
+ max = 3;
+ setNamedParams( new String[] { "Passphrase" , "Hash" , "Algorithm" } );
+ }
+
+
+ public cfBooleanData execute
+ ( cfSession _session
+ , cfArgStructData ArgStruct
+ )
+ throws cfmRunTimeException
+ {
+ try
+ {
+ String Passphrase = getNamedStringParam( ArgStruct , "Passphrase" , null );
+ String Hash = getNamedStringParam( ArgStruct , "Hash" , null );
+ String Algorithm = getNamedStringParam( ArgStruct , "Algorithm" , null );
+
+ return cfBooleanData.getcfBooleanData
+ ( Impl.check
+ ( Passphrase , Hash , Algorithm )
+ );
+ }
+ catch(Exception Ex)
+ {
+ throw new cfmRunTimeException(_session,Ex);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/openbd/PassphraseHash.java b/src/sorcerersisle/cfpassphrase/openbd/PassphraseHash.java
new file mode 100644
index 0000000..a4e6388
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/openbd/PassphraseHash.java
@@ -0,0 +1,52 @@
+package sorcerersisle.cfpassphrase.openbd;
+
+import sorcerersisle.cfpassphrase.*;
+import com.naryx.tagfusion.expression.function.functionBase;
+import com.naryx.tagfusion.cfm.engine.cfSession;
+import com.naryx.tagfusion.cfm.engine.cfArgStructData;
+import com.naryx.tagfusion.cfm.engine.cfStringData;
+import com.naryx.tagfusion.cfm.engine.cfStructData;
+import com.naryx.tagfusion.cfm.engine.cfmRunTimeException;
+
+@SuppressWarnings("serial")
+public final class PassphraseHash
+ extends functionBase
+{
+
+ public PassphraseHash()
+ {
+ min = 1;
+ max = 3;
+ setNamedParams( new String[] { "Passphrase" , "Algorithm" , "AlgorithmParams" } );
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public cfStringData execute
+ ( cfSession _session
+ , cfArgStructData ArgStruct
+ )
+ throws cfmRunTimeException
+ {
+ try
+ {
+ String Passphrase = getNamedStringParam( ArgStruct , "Passphrase" , null );
+ String Algorithm = getNamedStringParam( ArgStruct , "Algorithm" , null );
+ cfStructData AlgorithmParams = (cfStructData) getNamedParam( ArgStruct , "AlgorithmParams" , null );
+
+ return new cfStringData
+ ( Impl.hash
+ ( Passphrase
+ , Algorithm
+ , AlgorithmParams
+ )
+ );
+
+ }
+ catch(Exception Ex)
+ {
+ throw new cfmRunTimeException(_session,Ex);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/openbd/PassphraseInfo.java b/src/sorcerersisle/cfpassphrase/openbd/PassphraseInfo.java
new file mode 100644
index 0000000..756c7a5
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/openbd/PassphraseInfo.java
@@ -0,0 +1,47 @@
+package sorcerersisle.cfpassphrase.openbd;
+
+import sorcerersisle.cfpassphrase.*;
+import com.naryx.tagfusion.expression.function.functionBase;
+import com.naryx.tagfusion.cfm.engine.cfArgStructData;
+import com.naryx.tagfusion.cfm.engine.cfData;
+import com.naryx.tagfusion.cfm.engine.cfSession;
+import com.naryx.tagfusion.cfm.engine.cfStructData;
+import com.naryx.tagfusion.cfm.engine.cfmRunTimeException;
+
+
+@SuppressWarnings("serial")
+public final class PassphraseInfo
+ extends functionBase
+{
+
+ public PassphraseInfo()
+ {
+ min = 1;
+ max = 2;
+ setNamedParams( new String[] { "Hash" , "Algorithm" } );
+ }
+
+
+ public cfData execute
+ ( cfSession _session
+ , cfArgStructData ArgStruct
+ )
+ throws cfmRunTimeException
+ {
+ try
+ {
+ String Hash = getNamedStringParam( ArgStruct , "Hash" , null );
+ String Algorithm = getNamedStringParam( ArgStruct , "Algorithm" , null );
+
+ cfStructData Result = new cfStructData();
+ Result.putAll( Impl.info(Hash,Algorithm) );
+
+ return Result;
+ }
+ catch(Exception Ex)
+ {
+ throw new cfmRunTimeException(_session,Ex);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/openbd/PassphraseTag.java b/src/sorcerersisle/cfpassphrase/openbd/PassphraseTag.java
new file mode 100644
index 0000000..4fc4715
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/openbd/PassphraseTag.java
@@ -0,0 +1,81 @@
+package sorcerersisle.cfpassphrase.openbd;
+
+import com.naryx.tagfusion.cfm.tag.cfTag;
+import com.naryx.tagfusion.cfm.tag.cfTagReturnType;
+import com.naryx.tagfusion.cfm.engine.cfArgStructData;
+import com.naryx.tagfusion.cfm.engine.cfSession;
+import com.naryx.tagfusion.cfm.engine.cfData;
+import com.naryx.tagfusion.cfm.engine.cfStructData;
+import com.naryx.tagfusion.cfm.engine.cfmBadFileException;
+import com.naryx.tagfusion.cfm.engine.cfmRunTimeException;
+
+@SuppressWarnings("serial")
+public final class PassphraseTag
+ extends cfTag
+{
+
+
+ protected void defaultParameters
+ ( String _tag )
+ throws cfmBadFileException
+ {
+ parseTagHeader( _tag );
+
+ if ( ! containsAttribute("action") )
+ throw newBadFileException( "You must specify the [Action] attribute. Accepted values are 'hash', 'check', 'info'." , "" );
+
+ if ( ! containsAttribute("variable") )
+ throw newBadFileException( "You must specify the [Variable] attribute." , "" );
+
+ if ( ! containsAttribute("passphrase") )
+ throw newBadFileException( "You must specify the [Passphrase] attribute." , "" );
+ }
+
+
+ public cfTagReturnType render
+ ( cfSession _session )
+ throws cfmRunTimeException
+ {
+ String Action = getDynamic(_session,"action").getString();
+ String Variable = getDynamic(_session, "variable").getString();
+ cfArgStructData Args = new cfArgStructData();
+ cfData Result;
+
+ if (Action.equalsIgnoreCase("hash"))
+ {
+ Args.setData("passphrase", getDynamic(_session, "passphrase").getString());
+ if (containsAttribute("algorithm")) Args.setData("algorithm", getDynamic(_session, "algorithm").getString());
+ if (containsAttribute("algorithmparams")) Args.setData("algorithmparams", (cfStructData)getDynamic(_session, "algorithmparams"));
+
+ Result = new PassphraseHash().execute(_session,Args);
+ }
+ else if (Action.equalsIgnoreCase("check"))
+ {
+ Args.setData("passphrase" , getDynamic(_session, "passphrase").getString());
+ Args.setData("hash" , getDynamic(_session, "hash").getString());
+ if (containsAttribute("algorithm")) Args.setData("algorithm", getDynamic(_session, "algorithm").getString());
+
+ Result = new PassphraseCheck().execute(_session,Args);
+ }
+ else if (Action.equalsIgnoreCase("info"))
+ {
+ Args.setData("hash" , getDynamic(_session, "hash").getString());
+ if (containsAttribute("algorithm")) Args.setData("algorithm", getDynamic(_session, "algorithm").getString());
+
+ Result = new PassphraseCheck().execute(_session,Args);
+ }
+ else
+ {
+ throw new cfmRunTimeException
+ ( _session
+ , new Exception("Invalid value ["+Action+"] for [Action] attribute. Accepted values are 'hash', 'check', 'info'.")
+ );
+ }
+
+ _session.setData( Variable , Result );
+
+ return cfTagReturnType.NORMAL;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/openbd/cfPassphrasePlugin.java b/src/sorcerersisle/cfpassphrase/openbd/cfPassphrasePlugin.java
new file mode 100644
index 0000000..6e3efde
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/openbd/cfPassphrasePlugin.java
@@ -0,0 +1,42 @@
+package sorcerersisle.cfpassphrase.openbd;
+
+import com.bluedragon.plugin.Plugin;
+import com.bluedragon.plugin.PluginManagerInterface;
+import com.naryx.tagfusion.xmlConfig.xmlCFML;
+
+public final class cfPassphrasePlugin implements Plugin
+{
+
+ public cfPassphrasePlugin()
+ {
+
+ }
+
+ public String getPluginName()
+ {
+ return "cfPassphrase";
+ }
+
+ public String getPluginVersion()
+ {
+ return "0.0.000";
+ }
+
+ public String getPluginDescription()
+ {
+ return "Provides functions PassphraseHash, PassphraseCheck and PassphraseInfo to OpenBD.";
+ }
+
+ public void pluginStart( PluginManagerInterface Manager, xmlCFML SystemParameters )
+ {
+ Manager.registerFunction("PassphraseHash" ,"sorcerersisle.cfpassphrase.openbd.PassphraseHash");
+ Manager.registerFunction("PassphraseCheck","sorcerersisle.cfpassphrase.openbd.PassphraseCheck");
+ Manager.registerFunction("PassphraseInfo","sorcerersisle.cfpassphrase.openbd.PassphraseInfo");
+ Manager.registerTag("cfpassphrase","sorcerersisle.cfpassphrase.openbd.PassphraseTag");
+ }
+
+ public void pluginStop( PluginManagerInterface Manager )
+ {
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/railo/PassphraseCheck.java b/src/sorcerersisle/cfpassphrase/railo/PassphraseCheck.java
new file mode 100644
index 0000000..f020407
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/railo/PassphraseCheck.java
@@ -0,0 +1,40 @@
+package sorcerersisle.cfpassphrase.railo;
+
+import sorcerersisle.cfpassphrase.*;
+import railo.runtime.ext.function.Function;
+import railo.runtime.PageContext;
+import railo.runtime.exp.PageException;
+import railo.loader.engine.CFMLEngineFactory;
+
+
+@SuppressWarnings("serial")
+public final class PassphraseCheck
+ implements Function
+{
+
+
+ public static Boolean call
+ ( PageContext pc , String Passphrase , String Hash )
+ throws PageException
+ { return call(pc,Passphrase,Hash,null); }
+
+
+ public static Boolean call
+ ( PageContext pc
+ , String Passphrase
+ , String Hash
+ , String Algorithm
+ )
+ throws PageException
+ {
+ try
+ {
+ return Impl.check( Passphrase , Hash , Algorithm );
+ }
+ catch(Exception Ex)
+ {
+ throw CFMLEngineFactory.getInstance().getCastUtil().toPageException( Ex );
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/railo/PassphraseHash.java b/src/sorcerersisle/cfpassphrase/railo/PassphraseHash.java
new file mode 100644
index 0000000..3c5c1e6
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/railo/PassphraseHash.java
@@ -0,0 +1,56 @@
+package sorcerersisle.cfpassphrase.railo;
+
+import sorcerersisle.cfpassphrase.*;
+import railo.runtime.ext.function.Function;
+import railo.runtime.PageContext;
+import railo.runtime.exp.PageException;
+import railo.loader.engine.CFMLEngineFactory;
+import railo.runtime.type.Struct;
+import railo.runtime.util.Cast;
+
+
+@SuppressWarnings("serial")
+public final class PassphraseHash
+ implements Function
+{
+
+
+ public static String call
+ ( PageContext pc , String Passphrase )
+ throws PageException
+ { return call(pc,Passphrase,null,null); }
+
+ public static String call
+ ( PageContext pc , String Passphrase , String Algorithm )
+ throws PageException
+ { return call(pc,Passphrase,Algorithm,null); }
+
+
+ @SuppressWarnings("unchecked")
+ public static String call
+ ( PageContext pc
+ , String Passphrase
+ , String Algorithm
+ , Struct AlgorithmParams
+ )
+ throws PageException
+ {
+ Cast Caster = CFMLEngineFactory.getInstance().getCastUtil();
+
+ try
+ {
+ return Impl.hash
+ ( Passphrase
+ , Algorithm
+ , Caster.toMap(AlgorithmParams,null)
+ );
+ }
+ catch(Exception Ex)
+ {
+ throw Caster.toPageException( Ex );
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/railo/PassphraseInfo.java b/src/sorcerersisle/cfpassphrase/railo/PassphraseInfo.java
new file mode 100644
index 0000000..b956d53
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/railo/PassphraseInfo.java
@@ -0,0 +1,43 @@
+package sorcerersisle.cfpassphrase.railo;
+
+import sorcerersisle.cfpassphrase.*;
+import railo.runtime.ext.function.Function;
+import railo.runtime.PageContext;
+import railo.runtime.exp.PageException;
+import railo.runtime.type.Struct;
+import railo.runtime.util.Cast;
+import railo.loader.engine.CFMLEngineFactory;
+
+
+@SuppressWarnings("serial")
+public final class PassphraseInfo
+ implements Function
+{
+
+
+ public static Struct call
+ ( PageContext pc , String Passphrase )
+ throws PageException
+ { return call(pc,Passphrase,null); }
+
+
+ public static Struct call
+ ( PageContext pc
+ , String Hash
+ , String Algorithm
+ )
+ throws PageException
+ {
+ Cast Caster = CFMLEngineFactory.getInstance().getCastUtil();
+
+ try
+ {
+ return Caster.toStruct( Impl.info(Hash,Algorithm) );
+ }
+ catch(Exception Ex)
+ {
+ throw Caster.toPageException( Ex );
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/railo/PassphraseTag.java b/src/sorcerersisle/cfpassphrase/railo/PassphraseTag.java
new file mode 100644
index 0000000..e37afb1
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/railo/PassphraseTag.java
@@ -0,0 +1,92 @@
+package sorcerersisle.cfpassphrase.railo;
+
+import railo.runtime.ext.tag.TagSupport;
+import railo.runtime.ext.tag.DynamicAttributes;
+import railo.runtime.type.Collection.Key;
+import railo.runtime.type.Struct;
+import railo.runtime.exp.PageException;
+import railo.loader.engine.CFMLEngineFactory;
+
+@SuppressWarnings("deprecation")
+public final class PassphraseTag
+ extends TagSupport
+ implements DynamicAttributes
+{
+
+
+ private Struct Attributes = CFMLEngineFactory.getInstance().getCreationUtil().createStruct();
+
+
+ public int doStartTag()
+ throws PageException
+ {
+ String Action = (String)Attributes.get("action",null);
+ String Variable = (String)Attributes.get("variable",null);
+ String Passphrase = (String)Attributes.get("passphrase",null);
+ String Algorithm = (String)Attributes.get("algorithm",null);
+ Object Result;
+
+ if (Action.equalsIgnoreCase("hash"))
+ {
+ Struct AlgorithmParams = Attributes.containsKey("algorithmparams") ? (Struct)Attributes.get("algorithmparams") : null;
+
+ Result = PassphraseHash.call
+ ( pageContext
+ , Passphrase
+ , Algorithm
+ , AlgorithmParams
+ );
+ }
+ else if (Action.equalsIgnoreCase("check"))
+ {
+ String Hash = (String)Attributes.get("hash",null);
+
+ Result = PassphraseCheck.call
+ ( pageContext
+ , Passphrase
+ , Hash
+ , Algorithm
+ );
+ }
+ else if (Action.equalsIgnoreCase("info"))
+ {
+ String Hash = (String)Attributes.get("hash",null);
+
+ Result = PassphraseCheck.call
+ ( pageContext
+ , Hash
+ , Algorithm
+ );
+ }
+ else
+ {
+ throw CFMLEngineFactory.getInstance().getCastUtil().toPageException
+ ( new Exception("Invalid value for [Action] attribute. Accepted values are 'hash','check', or [info].")
+ );
+ }
+
+ pageContext.setVariable( Variable , Result );
+
+
+ return SKIP_BODY;
+ }
+
+
+ public void setDynamicAttribute(String uri, String localName, Object value)
+ {
+ Attributes.setEL(localName,value);
+ }
+
+ public void setDynamicAttribute(String uri, Key localName, Object value)
+ {
+ Attributes.setEL(localName,value);
+ }
+
+
+ public void release()
+ {
+ super.release();
+ Attributes.clear();
+ }
+
+}
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/railo/cfPassphrase.fld b/src/sorcerersisle/cfpassphrase/railo/cfPassphrase.fld
new file mode 100644
index 0000000..81f29e6
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/railo/cfPassphrase.fld
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE func-lib PUBLIC "-//Railo//DTD CFML Function Library 1.0//EN" "dtd/web-cfmfunctionlibrary_1_0.dtd">
+<func-lib>
+ <flib-version>1.00</flib-version>
+
+ <short-name>cfpassphrase-functions</short-name>
+ <uri>http://sorcerersisle.com/projects:cfpassphrase.html</uri>
+ <display-name>cfPassphrase Functions</display-name>
+ <description>Provides functions PassphraseHash and PassphraseCheck to Railo.</description>
+
+ <function>
+ <name>PassphraseHash</name>
+ <class>sorcerersisle.cfpassphrase.railo.PassphraseHash</class>
+ <description>PassphraseHash returns a hash using the specified KDF algorithm.</description>
+ <argument><name>Passphrase</name> <type>String</type> <required>yes</required> <description>The passphrase to hash.</description> </argument>
+ <argument><name>Algorithm</name> <type>String</type> <required>no</required> <description>The algorithm to use. ()Default is bcrypt</description> </argument>
+ <argument><name>AlgorithmParams</name> <type>Struct</type> <required>no</required> <description>Any parameters to pass into the algorithm.</description></argument>
+ <return><type>String</type></return>
+ </function>
+
+ <function>
+ <name>PassphraseCheck</name>
+ <class>sorcerersisle.cfpassphrase.railo.PassphraseCheck</class>
+ <description>PassphraseCheck returns true/false depending on whether the passphrase matches the provided hash, according to the algorithm provided.</description>
+ <argument><name>Passphrase</name> <type>String</type> <required>yes</required> <description>The passphrase to check.</description> </argument>
+ <argument><name>Hash</name> <type>String</type> <required>yes</required> <description>The existing passphrase hash.</description> </argument>
+ <argument><name>Algorithm</name> <type>String</type> <required>no</required> <description>The algorithm to use. (Default depends on hash signature.)</description></argument>
+ <return><type>Boolean</type></return>
+ </function>
+
+ <function>
+ <name>PassphraseInfo</name>
+ <class>sorcerersisle.cfpassphrase.railo.PassphraseInfo</class>
+ <description>PassphraseInfo Identifies the algorithm and parameters for the specified hash.</description>
+ <argument><name>Hash</name> <type>String</type> <required>yes</required> <description>The hash to return info about.</description> </argument>
+ <argument><name>Algorithm</name> <type>String</type> <required>no</required> <description>The algorithm to use. (Default depends on hash signature.)</description></argument>
+ <return><type>Struct</type></return>
+ </function>
+
+</func-lib>
\ No newline at end of file
diff --git a/src/sorcerersisle/cfpassphrase/railo/cfPassphrase.tld b/src/sorcerersisle/cfpassphrase/railo/cfPassphrase.tld
new file mode 100644
index 0000000..e075d1e
--- /dev/null
+++ b/src/sorcerersisle/cfpassphrase/railo/cfPassphrase.tld
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE taglib PUBLIC "-//Railo//DTD CFML Tag Library 1.0//EN" "dtd/web-cfmtaglibrary_1_0.dtd">
+<taglib>
+ <tlib-version>1.00</tlib-version>
+
+ <short-name>cfpassphrase-tag</short-name>
+ <uri>http://sorcerersisle.com/projects:cfpassphrase.html</uri>
+ <display-name>cfPassphrase Tag</display-name>
+ <description>Provides tag cfpassphrase to Railo.</description>
+
+ <name-space>cf</name-space>
+ <name-space-separator/>
+
+ <tag>
+ <name>passphrase</name>
+ <tag-class>sorcerersisle.cfpassphrase.railo.PassphraseTag</tag-class>
+ <body-content>empty</body-content>
+ <body-rtexprvalue>false</body-rtexprvalue>
+ <description>Checks or calculates a hash using the specified KDF algorithm.</description>
+ <attribute-type>dynamic</attribute-type>
+ <attribute-min>3</attribute-min>
+ <attribute-max>6</attribute-max>
+ <attribute>
+ <name>Action</name>
+ <type>string</type>
+ <required>true</required>
+ <description>Specify [hash], [check], or [info] to determine what action tag takes.</description>
+ </attribute>
+ <attribute>
+ <name>Variable</name>
+ <type>string</type>
+ <required>true</required>
+ <description>Name of variable to contain result of action.</description>
+ </attribute>
+ <attribute>
+ <name>Passphrase</name>
+ <type>string</type>
+ <required>false</required>
+ <description>The passphrase to be hashed or checked. (action=hash,action=check)</description>
+ </attribute>
+ <attribute>
+ <name>Hash</name>
+ <type>string</type>
+ <required>false</required>
+ <description>The existing hash to be checked against. (action=check,action=info)</description>
+ </attribute>
+ <attribute>
+ <name>Algorithm</name>
+ <type>string</type>
+ <required>false</required>
+ <description>Algorithm to be used.</description>
+ </attribute>
+ <attribute>
+ <name>AlgorithmParams</name>
+ <type>struct</type>
+ <required>false</required>
+ <description>Optional parameters to be used by algorithm. (action=hash)</description>
+ </attribute>
+ </tag>
+
+</taglib>
\ No newline at end of file