Coldfusion ENCRYPT и MySQL AES_DECRYPT Работаете вместе? - PullRequest
1 голос
/ 06 июля 2011

Я использую ColdFusion 9 и MySQL 5.1. Я пытаюсь совместить функции шифрования / дешифрования ColdFusion и mySQL AES_ENCRYPT / AES_DECRYPT, чтобы я мог использовать их взаимозаменяемо в зависимости от ситуации. Не повезло с этим.

Сначала я создал строку AES с ColdFusion:

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

1 голос
/ 07 июня 2012

Я знаю, что эта тема старая, но ответ пришел в недавней теме .Поэтому я публикую это для потомков.Как объясняется в этой записи блога , причина различий заключается в следующем:

.. алгоритм MySQL просто или представляет собой байты заданной парольной фразы относительно предыдущих байтов, если парольдлиннее 16 символов и просто оставляет их равными 0, если пароль короче 16 символов.

Поэтому вам необходимо выполнить те же манипуляции со значением ключа, прежде чем передавать его в encrypt/decrypt.

0 голосов
/ 16 мая 2013

Использование 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 ... больше кода ...

0 голосов
/ 25 ноября 2012

Я знаю, что это довольно старый пост, но вот что вы должны сделать:

Перед сохранением в БД:

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

Затем:

INSERT INTO encrypt_test 
SET fld = crypt_fld

У меня это сработало

0 голосов
/ 06 июля 2011

Я бы придерживался только использования функций CF. Таким образом, вы можете добавлять всевозможные уровни процессов безопасности, включая такие вещи, как итерации и несколько ключей, чтобы легко создавать собственные решения. Количество накладных расходов, которое оно добавляет, тоже не так много для этого.

0 голосов
/ 06 июля 2011

Почему вы не используете функцию шифрования ColdFusion вместо MySQL?

Фактически это был бы один из способов проверить, в чем может заключаться проблема: попробуйте вывести как зашифрованное значение из вашей базы данных, так и то, что выдаст функция шифрования CF, и посмотрите, идентичны ли они.

В качестве альтернативы просто используйте функцию aes_decrypt в вашем запросе вместо использования расшифровки ColdFusion.

Хммм, из документов :

Поскольку AES является алгоритмом на уровне блоков, для кодирования строк неравной длины используется заполнение, поэтому длина строки результата может быть рассчитана по следующей формуле:

16 * (усечение (длина строки / 16) + 1)

Если AES_DECRYPT () обнаруживает неверные данные или неправильное заполнение, возвращается NULL.

Таким образом, предполагая, что CFML не выполняет это заполнение, вы должны выяснить обратное себе или что-то в этом роде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...