Coldfusion ENCRYPT 和 MySQL AES_DECRYPT 一起工作吗?

发布于 2024-11-19 00:13:54 字数 1042 浏览 1 评论 0原文

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

I am using ColdFusion 9, and MySQL 5.1. I am trying to align the ColdFusion encrypt/decrypt functions and mySQL AES_ENCRYPT/AES_DECRYPT so I can use them interchangeably depending on the situation. Not having much luck with that.

First I created an AES string with ColdFusion:

    <cfset theKey = generateSecretKey("AES") />
    <cfoutput>#theKey#</cfoutput>

Example key: 4OFWUiuqFEkGrSRFm8sLlg==

I use this key to encrypt with MySQL. Note, encrypt_test is an existing table, and fld is a varchar column.

    INSERT INTO encrypt_test 
    SET fld = aes_encrypt('the text to encrypt', '4OFWUiuqFEkGrSRFm8sLlg==')

Next I try to decrypt with ColdFusion:

    <cfset theKey = "4OFWUiuqFEkGrSRFm8sLlg=="
    <cfset theAlgorithm  = "AES" />

Then run a cfquery to get the data (Only 1 record in the table),

    <cfquery name="testDecrypt">
        SELECT fld FROM encrypt_test
    </cfquery`

And finally decrypt

    <cfoutput>#Decrypt(testDecrypt.fld, theKey, theAlgorithm)#</cfoutput>

This results in a Null. I suspect its a padding issue or some other mismatch, anyone have an idea what I am doing wrong, or how to make this work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

蘸点软妹酱 2024-11-26 00:13:54

我知道这个帖子已经很旧了,但答案出现在最近的帖子上。所以我将其发布给后代。正如本博客中所述条目,差异的原因是:

.. MySQL 算法只是 or 给定密码短语的字节
如果密码长度超过 16 个字符,则针对前面的字节
当密码短于 16 个字符时,将它们保留为 0。

因此,在将键值传递到加密/解密之前,您需要对键值执行相同的操作。

I know this thread is old, but the answer came up on a recent thread. So I am posting it for posterity. As explained in this blog entry, the reason for the difference is:

.. the MySQL algorithm just or’s the bytes of a given passphrase
against the previous bytes if the password is longer than 16 chars and
just leaves them 0 when the password is shorter than 16 chars.

So you need to perform the same manipulations on the key value, before passing it into encrypt/decrypt.

来世叙缘 2024-11-26 00:13:54

我会坚持只使用 CF 的功能。这样,您就可以添加各种安全流程层,包括迭代和多个密钥等内容,从而轻松构建自定义解决方案。它所增加的开销也并不多。

I would stick with just using CF's functions. That way you can add all kinds of layers of security processes, to include things like iterations and multiple keys, to build a custom solution with ease. THe amount of overhead it adds is not much at all for that as well.

⒈起吃苦の倖褔 2024-11-26 00:13:54

为什么不使用 ColdFusion 的加密功能而不是 MySQL 的呢?

事实上,这是测试问题所在的一种方法:尝试输出数据库中的加密值以及 CF 的加密函数将生成的值,看看它们是否相同。

或者,只需在查询中使用 aes_decrypt 函数,而不是使用 ColdFusion 的解密。

嗯,来自文档

由于 AES 是块级算法,因此使用填充来编码不均匀长度的字符串,因此结果字符串长度可以使用以下公式计算:

16 * (trunc(字符串长度 / 16) + 1)

如果 AES_DECRYPT() 检测到无效数据或不正确的填充,则返回 NULL。

因此,假设 CFML 不进行填充,您就必须自己找出相反的方法或其他方法。

Why don't you use ColdFusion's encrypt function instead of MySQL's?

In fact that would be one way to test where the problem might lie : try outputting both the encrypted value from your database and what CF's encrypt function would produce and see if they're identical.

Alternatively just use the aes_decrypt function in your query instead of using ColdFusion's decrypt.

Hmmm, from the docs:

Because AES is a block-level algorithm, padding is used to encode uneven length strings and so the result string length may be calculated using this formula:

16 * (trunc(string_length / 16) + 1)

If AES_DECRYPT() detects invalid data or incorrect padding, it returns NULL.

So assuming CFML doesn't do that padding, you'd have to figure out the reverse of this yourself or something.

高速公鹿 2024-11-26 00:13:54

我知道这是一篇很旧的帖子,但这是你应该做的:

在存储到数据库之前:

<cfset crypt_fld = #encrypt('the text to encrypt', thekey, 'AES')#>

然后:

INSERT INTO encrypt_test 
SET fld = crypt_fld

它对我有用

I know it's quite an old post but here is what you should do:

Before storing into the DB:

<cfset crypt_fld = #encrypt('the text to encrypt', thekey, 'AES')#>

Then:

INSERT INTO encrypt_test 
SET fld = crypt_fld

It worked for me

触ぅ动初心 2024-11-26 00:13:54

使用 jBCrypt :: bCrypt 是可用的最强加密......在 Mark Mandel 的 Fantastic 的帮助下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>

密码哈希.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 ... 更多代码 ...

Use jBCrypt :: bCrypt is the strongest encryption available ... with the assistance of Mark Mandel's Fantastic JavaLoader
implementing jBCrypt is a snap in ColdFusion ...

As far as the password field it really doesn't matter what kind of database you're using ... the field could be varchar(60) or nvarchar(60) if you're dealing with locale support too...

<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>

The 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 ... more code ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文