Coldfusion ENCRYPT和MySQL AES_DECRYPT一起工作?

时间:2011-07-06 14:26:51

标签: mysql encryption coldfusion

我正在使用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。我怀疑它是填充问题或其他一些不匹配问题,任何人都知道我做错了什么,或者如何使这个工作?

5 个答案:

答案 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 ...更多代码...