Использование jBCrypt :: bCrypt - самое мощное из доступных шифрований ... с помощью Fantastic JavaLoader Марка Манделя * реализация jBCrypt - простое решение в ColdFusion ...
Что касается поля пароля, то на самом деле не имеет значения, какую базу данных вы используете ... поле может быть varchar (60) или nvarchar (60), если вы тоже имеете дело с поддержкой локали ...
<cfcomponent title="bcrypt (strong; recommended)" hint="I encode passwords using a popular secure password hashing algorithm called bcrypt. I am very slow, but that makes me very secure!" extends="PasswordHash"
alias="bcrypt" seq="9001" workFactor="10">
<cfset variables.loadPaths = [expandPath( "/PATHTOLIBDIR/lib/jbcrypt/jbcrypt-0.3m.jar" )]/>
<cffunction name="init" access="public" output="true" returntype="any" hint="constructor">
<cfset super.init( )/>
<!--- Allow java loader to fail silently: we can report the failure via isAvailable() --->
<cftry>
<cfset variables.oBCryptClass = createJavaClass( "org.mindrot.jbcrypt.BCrypt" )/>
<cfcatch></cfcatch>
</cftry>
<cfreturn this/>
</cffunction>
<cffunction name="isAvailable" hint="Is the hashing agorithm available in this environment?" access="public" returntype="boolean">
<cfreturn structKeyExists( variables, "oBCryptClass" )/>
</cffunction>
<cffunction name="matchesHashFormat" hint="Does the string match the format for this hash?" access="public" returntype="boolean">
<cfargument name="input" type="string" hint="String that may be a password hash" required="true"/>
<cfreturn REFind( "^\$2a\$\d+\$[\./A-Za-z0-9]+$", arguments.input )/>
</cffunction>
<cffunction name="encode" hint="Convert a clear password to its encoded value" access="public" returntype="string">
<cfargument name="password" type="string" hint="Input password" required="true"/>
<cfset var salt = variables.oBCryptClass.gensalt( JavaCast( "int", this.workFactor ) )/>
<cfreturn variables.oBCryptClass.hashpw( arguments.password, salt )/>
</cffunction>
<cffunction name="getHashWorkFactor" hint="Retrieve the work factor from a hashed string" access="public" returntype="numeric">
<cfargument name="hashedPassword" type="string" hint="Previously encoded password string" required="true"/>
<cfset var stMatch = ReFind( "^\$2a\$(\d+)\$([\./A-Za-z0-9]+)$", arguments.hashedPassword, 1, "true" )/>
<cfif stMatch.pos[1] eq 0>
<cfreturn 0>
<cfelse>
<cfreturn mid( arguments.hashedPassword, stMatch.pos[2], stMatch.len[2] )>
</cfif>
</cffunction>
<cffunction name="passwordMatch" hint="Compare a plain password against an encoded string" access="public" returntype="boolean">
<cfargument name="password" type="string" hint="Input password" required="true"/>
<cfargument name="hashedPassword" type="string" hint="Previously encoded password string" required="true"/>
<cfargument name="bCheckHashStrength" type="boolean" default="false" hint="If true, the hash strength of the hashed password must also match those generated by encode()"/>
<cfset var bMatch = variables.oBCryptClass.checkpw( arguments.password, arguments.hashedPassword )/>
<cfif bMatch and bCheckHashStrength>
<!--- Hash matched but we also need to match the bCrypt work factor --->
<cfreturn getHashWorkFactor( arguments.hashedPassword ) eq this.workFactor/>
<cfelse>
<cfreturn bMatch/>
</cfif>
</cffunction>
PasswordHash.cfc ...
<cfcomponent hint="I am an abstract component for encoding passwords for storage and comparing passwords against previously encoded strings">
<!--- Array of Java class paths required for this component. Leave empty if no special Java libraries are needed. --->
<cfset variables.loadPaths = []/>
<cffunction name="init" access="public" output="true" returntype="any" hint="constructor">
<cfset var stMetadata = getMetadata( this )/>
<cfset var attr = ""/>
<cfloop condition="not structisempty(stMetadata)">
<!--- Get attributes --->
<cfloop collection="#stMetadata#" item="attr">
<cfif issimplevalue( stMetadata[attr] ) and not listcontains( "bindingname,extends,fullname,functions,hint,name,namespace,output,path,porttypename,serviceportname,style,type,wsdlfile", attr ) and not structkeyexists( this, attr )>
<cfset this[attr] = stMetadata[attr]/>
</cfif>
</cfloop>
<!--- Do the same for ancestors --->
<cfif structkeyexists( stMetadata, "extends" )>
<cfset stMetadata = stMetadata.extends/>
<cfelse>
<cfset stMetadata = structnew( )/>
</cfif>
</cfloop>
<cfset stMetadata = getMetadata( this )/>
<!--- If key isn't specified, use the name of the component --->
<cfif not structkeyexists( this, "alias" )>
<cfset this.alias = listlast( stMetadata.name, "." )/>
</cfif>
<!--- If title isn't specified, use the displayname --->
<cfif not structkeyexists( this, "title" )>
<cfset this.title = this.displayname/>
</cfif>
<!--- If seq isn't specified, use 9999 --->
<cfif not structkeyexists( this, "seq" )>
<cfset this.seq = 9999/>
</cfif>
<cfreturn this/>
</cffunction>
<cffunction name="isAvailable" hint="Is the hashing agorithm available in this environment?" access="public" returntype="boolean">
<cfreturn true/>
</cffunction>
<cffunction name="matchesHashFormat" hint="Does the string match the format for this hash?" access="public" returntype="boolean">
<cfargument name="input" type="string" required="true" hint="String that may be an encoding of a password"/>
<cfthrow message="The #this.alias# password encoding needs to implement the matchesHashFormat function"/>
<cfreturn ""/>
</cffunction>
<cffunction name="encode" hint="Convert a clear password to its encoded value" access="public" returntype="string">
<cfargument name="password" type="string" required="true" hint="Input password"/>
<cfthrow message="The #this.alias# password encoding needs to implement the encode function"/>
<cfreturn ""/>
</cffunction>
<cffunction name="passwordMatch" hint="Compare a plain password against an encoded string" access="public" returntype="boolean">
<cfargument name="password" type="string" required="true" hint="Input password"/>
<cfargument name="hashedPassword" type="string" required="true" hint="Previously encoded password string"/>
<cfargument name="bCheckHashStrength" type="string" default="false" hint="If true, the hash strength of the hashed password must also match those generated by encode()"/>
<cfthrow message="The #this.alias# password encoding needs to implement the passwordMatch function"/>
<cfreturn false/>
</cffunction>
<!--- Private Java library helper functions --->
<cffunction access="private" name="getJavaLoader" returntype="any" output="false">
<!--- Lazy-loading the JavaLoader makes it easier for plugins/projects to add custom crypto libraries --->
<cfif not structKeyExists( variables, "loader" )>
<cfset variables.loader = createObject( "component", "PATH.TO.JavaLoader" ).init( variables.loadPaths )/>
</cfif>
<cfreturn variables.loader/>
</cffunction>
<cffunction access="private" name="createJavaClass" returntype="any" output="false" hint="Return a java class from the crypto libraries">
<cfargument name="className" type="string" required="true"/>
<cfreturn getJavaLoader( ).create( arguments.className )/>
</cffunction>
... yada yada ... больше кода ...