user1188254
user1188254

Reputation: 41

Coldfusion Encrypt and Decrypt

I am having issues using the cf9 encrypt and decrypt function. Specifically,the code I use needs to be able to encrypt with AES/ECB/PKCS5Padding 256. I am trying to post data to a third party bank with the following code:

<cfparam name="theKey" default="someStaticKey">
<cfset strName = leaddetail.leadlast&','&leaddetail.leadfirst />
    <cfset stFields = {requesttype = "eftaddonetimecompletetransaction"
            ,clientid = "XXXXXX"
            ,urltoredirect = "#RedirectURl#"
            ,customerid = "#leaddetail.leadid#"
            ,isdebitcardonly = "No"
            ,customername = "#strName#"
            ,customeraddress1 = "#form.billingaddress#"
            ,customercity = "#form.billingcity#"
            ,customerstate = "#form.billingstate#"
            ,customerzip = "#form.billingzip#"
            ,cardbillingaddr1 = "#form.billingaddress#"
            ,cardbillingcity = "#form.billingcity#"
            ,cardbillingstate = "#form.billingstate#"
            ,cardbillingzip = "#form.billingzip#"
            ,accounttype = "CC"
            ,name_on_card = "#form.leadname#"
            ,accountnumber = "#form.ccacctnum#"
            ,expmonth = "#Left(form.ccexpdate,2)#"
            ,expyear = "#Right(form.ccexpdate,2)#"
            ,cvvcode = "#form.ccv2#"
            ,amount = "#NumberFormat(esigninfo.esignpayamt,'9999.99')#"
            ,startdate = "#DateFormat(Now(),'YYYY-MM-DD')#"
            ,transactiontypecode = "WEB"}/>
            <cfset theEncryptedStr = ToBase64(encrypt(serializeJson(stFields),theKey))>
                    <!--- shake hands and login to api --->
    <cfhttp url="https://www.somebank.com/cgi-bin/wsnvptest.vps" method="post" charset="ISO-8859-1" throwonerror="yes" result="httpResponse">
                <!--- login Variables --->
        <cfhttpparam type="Header" name="User-Agent" value="Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.41">
        <cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded" >
        <cfhttpparam type="header" name="Accept" value="application/json" >
                <!--- Login Credentials --->
        <cfhttpparam type="formfield"name="nvpvar"value="''"/>
        <cfhttpparam type="formfield"name="requesttype"value="login"/>
        <cfhttpparam type="formfield"name="userid"value="Dauserid"/>
        <cfhttpparam type="formfield"name="password"value="password"/>
        <cfhttpparam type="formfield"name="requestid"value="#uniquerequestid#"/>
        <cfhttpparam type="formfield"name="PostData" value="#theEncryptedStr#"/>
        <cfif isDefined('CheckSession.sessionID') AND CheckSession.sessionID NEQ ''>
            <cfhttpparam type="formfield"name="sessionid" value="#checkSession.sessionID#"/>
        </cfif>
    </cfhttp>

for some reason I can encrypt but cant decrypt the response. Is there anyone out there that has more experience with this that can put on a path to success?


(Update from rejected edit)

I am using the following script to decrypt my cfhttp response string:

<cfset content = httpResponse.filecontent>
<cfset authdata = structNew()> 
<cfloop index="line" list="#content#"> 
   <cfset dtype = listFirst(line, "=")/> 
   <cfset EncodedString = listRest(line, "=")/> 
   <cfset authdata[dtype] = EncodedString /> 
</cfloop> 

<cfscript> 
   keyInBase64 = "Some64baseKey; 
   // Now decrypt the base64 encoded encryption string 
   decryptedValue = decrypt(EncodedString , keyInBase64 , "AES/ECB/PKCS5Padding" , "base64" ); 
   WriteDump(variables); 
</cfscript> 

The string I am trying to decrypt looks similar to the following:

nvpvar=fKsJGJ-Fe-2zoqUROAeE8N8a87USuQpE7dVd5IvRa67cHsVkPwx9taKLuXKwsCKFC_-NW3j6IOQAvCnRNc4cRNfq2fqyRHBUrFbFDCCmwpk=

Upvotes: 1

Views: 3461

Answers (1)

Leigh
Leigh

Reputation: 28873

encrypt(serializeJson(stFields),theKey)

First, that is NOT AES encryption. You omitted the algorithm parameter, so encrypt() defaults to the legacy CFMX_COMPAT algorithm (weakest). CFMX_COMPAT it is not a "real" encryption algorithm at all, so do not use it - for anything!

Second, with AES you are limited to 128 bit keys out of the box. In order to use 256 bit keys you must first install the (JCE) Unlimited Strength Jurisdiction Policy Files.

Copy them into your /lib/security/ directory. Then restart the CF server to apply the changes.

Note: If you have multiple JVM's installed, be sure to update the correct one. ie The one listed in the CF Administrator).

After restarting, you will be able to encrypt with a 256 bit key. With ECB mode, the syntax is: encrypt(string, key, algorithm, encoding)

  • string - plain text to encrypt
  • key - a 256 bit key, must be base64 encoded
  • algorithm - single string representing the desired: algorithm, mode and padding scheme. Note: "AES" is actually a shorthand for the longer "AES/ECB/PKCS5Padding"
  • encoding - "The binary encoding in which to represent the data as a string"

Putting it all together:

  <cfscript>
  // some sample data to encrypt 
  stFields = { clientid = "AA-BB-CC-123"
                    , customername = "ABC Incorporated" 
                  };

  // some 256 bit key, must be base64 encoded
  // hard coded for demo purposes only
  keyInBase64 = "9NJU2L3FZ8Rr0WKZUFC3lyE/yRrQ7sIZmQRk3kx9MLE=";

  // AES encrypt the value, and base64 encode the result 
  encryptedValue = encrypt(  serializeJson(stFields)
                                     , keyInBase64
                                     , "AES/ECB/PKCS5Padding"
                                     , "base64" 
                           );
  // Now decrypt the base64 encoded encryption string 
  decryptedValue = decrypt(  encryptedValue
                                      , keyInBase64
                                      , "AES/ECB/PKCS5Padding"
                                      , "base64"
                           );

  // display results
  WriteDump( variables );
</cfscript>

Update based on comments:

I notice you are manipulating the raw http response string. Without seeing the API, I would guess that either a) You need to decrypt the whole string first, then extract the parts -OR- b) the code is not extracting the values correctly and that is why you cannot decrypt it. The cfloop treats the response as a comma separated list. Based on the variable names, I am guessing it is actually separated by new lines instead, ie:

 param1=xxxxx      -- new line
 param2=yyyyy      -- new line
 param3=zzzzz      

Those are just guesses though. Check your API. What is the actual format of the returned response? Also, can you please edit your question to include the full error message?

Upvotes: 6

Related Questions