4

Using CF8 and MySQL 5.1, I am trying to encrypt() a password upon creation and then decrypt() at login. I can get the decrypt() to work fine on a test page but when I put it in a cfincluded page with cflogin I get the error "An error occurred while trying to encrypt or decrypt your input string: com.rsa.jsafe.crypto.dr: Could not perform unpadding: invalid pad byte.. ". It is the same code and DB from my test page to my app.

application.cfc:

<cfif NOT IsDefined("Request.PasswordKey")>
<cfset request.PasswordKey = generateSecretKey("AES")>
<cfset request.algorithm = "AES">
<cfset request.encoding = "hex">
</cfif>

test page which works fine:

FORM DATA:  <br/>
form password:<cfoutput>#form.passwd#</cfoutput><br/>
<cfset encrypted = Encrypt(form.passwd,Request.PasswordKey,Request.algorithm,Request.encoding)>
Encrypted: <cfoutput>#encrypted#</cfoutput><br/>
Decrypted: <cfoutput>#Decrypt(variables.encrypted,Request.PasswordKey,Request.algorithm,Request.encoding)#</cfoutput><br/>
<br/>
QUERY DATA<br/>
<cfinvoke component="components.userQ" method="login" returnvariable="qLogin">
<cfinvokeargument name="formData" value="#form#">
</cfinvoke>
<cfoutput>qLogin password: #qlogin.encPasswd#</cfoutput><br/>
<cfoutput>Decrypted encPasswd from qLogin: #Decrypt(qlogin.encPasswd,Request.PasswordKey,Request.algorithm,Request.encoding)#</cfoutput>

Decrypt() in app page that is erroring:

<cfset unEnPasswd = #Decrypt(qlogin.encPasswd,Request.PasswordKey,Request.algorithm,Request.encoding)#>

I can get the default CFMX_COMPAT encrypt() and decrypt() to work fine in my app with the same code, just changing the key, algorithm, and encoding variables.
BTW, I am also storing the encrypted strings as varchar() in the DB so it doesn't mess up the padding (so I read). I tried BLOB but get a bytearray error.

Any help or thoughts are greatly appreciated.

Mike Causer
  • 8,196
  • 2
  • 43
  • 63
JS.
  • 227
  • 4
  • 14

2 Answers2

4

You're creating a new secret key on every request,

Really your code should be more like:

<cffunction name="onApplicationStart" returnType="boolean" output="false">
  <cfset application.PasswordKey = generateSecretKey("AES")>
</cffunction>

<cffunction name="onRequestStart" returnType="boolean" output="false">
  <cfset request.PasswordKey = application.PasswordKey />
  <cfset request.algorithm = "AES" />
  <cfset request.encoding = "hex" />
</cffunction>

Though really you want to have the password key hardcoded in a config file otherwise if you restart your server you won't be able to access any of your passwords ever again...

Aidan Kane
  • 3,856
  • 2
  • 25
  • 28
  • The main thing to check really is that when you cfdump the key and encrypted strings on the two different pages they are all the same. So the encrypted string before storing in the db should be the same as the one pulled from the db later. And the key you use each time needs to be the same. – Aidan Kane Aug 22 '10 at 18:54
  • Apologies - your answer is starting to make sense and I believe that I am using different keys. So dumb question for you; using generateSecretKey() for AES, how do I ensure that I am using the same key across restarts etc...? – JS. Aug 22 '10 at 19:39
  • Personally I actually generate a single unique key for the application. That key is then hardcoded in the application (stored in a config file - just a cfm that holds a whole lot of constants). It means that you have to have a copy of the key somewhere on the server - but there's not much you can do about that. – Aidan Kane Aug 23 '10 at 08:28
  • Thanks again for your help. I created a variable from generateSecretKey, cfoutput it to see what the value was, and then used that for the key and am referencing the variable from a config file in my application.cfc. – JS. Aug 24 '10 at 01:16
0

Disable jsafe. Add -Dcoldfusion.disablejsafe=true to your jvm config.

David Collie
  • 612
  • 3
  • 7