我正在使用ColdFusion 9和MySQL 5.1。我正在尝试对齐ColdFusion加密/解密函数和mySQL AES_ENCRYPT / AES_DECRYPT,以便我可以根据情况互换使用它们。没有太多运气。
首先,我使用ColdFusion创建了一个AES字符串:
<cfset theKey = generateSecretKey("AES") />
<cfoutput>#theKey#</cfoutput>
示例键:4OFWUiuqFEkGrSRFm8sLlg ==
我使用此密钥加密MySQL。注意,encrypt_test是一个现有的表,fld是一个varchar列。
INSERT INTO encrypt_test
SET fld = aes_encrypt('the text to encrypt', '4OFWUiuqFEkGrSRFm8sLlg==')
接下来我尝试用ColdFusion解密:
<cfset theKey = "4OFWUiuqFEkGrSRFm8sLlg=="
<cfset theAlgorithm = "AES" />
然后运行cfquery来获取数据(表中只有1条记录),
<cfquery name="testDecrypt">
SELECT fld FROM encrypt_test
</cfquery`
最后解密
<cfoutput>#Decrypt(testDecrypt.fld, theKey, theAlgorithm)#</cfoutput>
这会产生Null
。我怀疑它是填充问题或其他一些不匹配问题,任何人都知道我做错了什么,或者如何使这个工作?
答案 0 :(得分:1)
我知道这个帖子已经过时了,但答案出现了on a recent thread。所以我发布它给后人。作为explained in this blog entry,差异的原因是:
.. MySQL算法只是或者是给定密码的字节 如果密码超过16个字符,则与前一个字节相对 当密码短于16个字符时,只留下0。
因此,在将密钥值传递到encrypt/decrypt
之前,您需要对密钥值执行相同的操作。
答案 1 :(得分:0)
为什么不使用ColdFusion的加密功能而不是MySQL?
事实上,这将是测试问题可能位置的一种方法:尝试输出数据库中的加密值和CF的加密函数将产生的值,并查看它们是否相同。
或者只是在查询中使用aes_decrypt函数,而不是使用ColdFusion的解密。
嗯,来自docs:
由于AES是块级算法,因此填充用于编码不均匀长度的字符串,因此可以使用以下公式计算结果字符串长度:
16 *(trunc(string_length / 16)+ 1)
如果AES_DECRYPT()检测到无效数据或填充不正确,则返回NULL。
因此,假设CFML没有执行该填充,您必须自己或类似地找出相反的结果。
答案 2 :(得分:0)
我会坚持使用CF的功能。这样,您可以添加各种安全流程层,包括迭代和多个键等内容,轻松构建自定义解决方案。它增加的开销量也不大。
答案 3 :(得分:0)
我知道这是一个很老的帖子,但这是你应该做的:
在存入数据库之前:
<cfset crypt_fld = #encrypt('the text to encrypt', thekey, 'AES')#>
然后:
INSERT INTO encrypt_test
SET fld = crypt_fld
它对我有用
答案 4 :(得分:0)
使用jBCrypt :: bCrypt是最强大的加密...在Mark Mandel的神奇JavaLoader的帮助下 在ColdFusion中实现jBCrypt很快......
就密码字段而言,您正在使用的数据库类型无关紧要......如果您正在处理语言环境支持,则字段可能是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 ...更多代码...