Solved

encryption issues

Posted on 2012-03-13
14
283 Views
Last Modified: 2012-04-01
Hello,
I'm working with a 3rd party vendor trying to send them an encrypted URL string with encode to preserve any spaces ect..  They are requiring a DESEDE encryption in ECB mode with PKCS5 padding using Base64 and the string should not be encoded again after the Base64 encoding.  

They have provided with me a username, password, and key they are expecting.  The code should be straight forward.  When put the code in, I get the following error:  

The key specified is not a valid key for this encryption: Wrong key algorithm, expected DESede.

Here is the code:

<cfset myKey = toBase64(BinaryDecode("xxxxxx[24bit key]xxxxxxx", "Base64"))>
<cfset myDate = dateformat(dateconvert( "local2Utc", now()), "YYYYMMDDHHMMSS")>
<cfset uid = "MyUserId">
<cfset pw = "MyPassword">
<cfset stmt = URLEncodedFormat("User_Id=#variables.uid#&User_Password=#Variables.pw#&User_TimeStamp=#variables.myDate#")>
<cfset encryptedUrl = encrypt(stmt, myKey, "DESEDE/ECB/PKCS5Padding", "Base64")>

I've taken out the actual username and password in this sample.  I've tried setting the the myKey to xxxxxx[24bit key]xxxxxxx (which is the key they are expecting), hashing the key, and taking out the ECB/PKCS5Padding.  

Any help would be greatly appreciated.  I'm not sure if I've overlooked anything, or exactly what I'm missing.  I'm not sure why CF keeps asking for the generateSecretKey method.  As soon as I do that, everything works great.   We are running CF 8.  Thank you in advance for your help.
0
Comment
Question by:DADITWebGroup
14 Comments
 
LVL 51

Expert Comment

by:ahoffmann
ID: 37718699
I'm no CF expert, but I assume that your encrypt() expects the key in binary format while you pass it base64 encoded
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 37719848
Sorry this is a PHP example, but it shows the principles of what needs to be done.
<?php // RAY_encrypt_decrypt.php
error_reporting(E_ALL);

// MAN PAGE: http://us.php.net/manual/en/ref.mcrypt.php

class Encryption
{
    protected $key;
    protected $eot;
    protected $ivs;
    protected $iv;

    public function __construct()
    {
        // SET KEY, DELIMITER, INITIALIZATION VECTOR - MUST BE KNOWN TO BOTH PARTS OF THE ALGORITHM
        $this->key = 'quay';
        $this->eot = '___EOT';
        $this->ivs = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
        $this->iv  = mcrypt_create_iv($this->ivs);
    }

    public function encrypt($text)
    {
        // APPEND END OF TEXT DELIMITER
        $text .= $this->eot;

        // ENCRYPT THE DATA
        $data = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv);

        // MAKE IT base64() STRING SAFE FOR STORAGE AND TRANSMISSION
        return base64_encode($data);
    }

    public function decrypt($text)
    {
        // DECODE THE DATA INTO THE BINARY ENCRYPTED STRING
        $text = base64_decode($text);

        // DECRYPT THE STRING
        $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv);

        // REMOVE END OF TEXT DELIMITER
        $data = explode($this->eot, $data);
        return $data[0];
    }
}

// INSTANTIATE THE CLASS
$c = new Encryption();

// INITIALIZE VARS FOR LATER USE IN THE HTML FORM
$encoded = '';
$decoded = '';

// IF ANYTHING WAS POSTED
if (!empty($_POST["clearstring"]))
{
    $encoded = $c->encrypt($_POST["clearstring"]);
    echo "<br/>{$_POST["clearstring"]} YIELDS ";
    var_dump($encoded);
}

if (!empty($_POST["cryptstring"]))
{
    $decoded = $c->decrypt($_POST["cryptstring"]);
    echo "<br/>{$_POST["cryptstring"]} YIELDS ";
    var_dump($decoded);
}

// END OF PHP - PUT UP THE FORM
?>
<form method="post">
<input name="clearstring" value="<?php echo $decoded; ?>" />
<input type="submit" value="ENCRYPT" />
<br/>
<input name="cryptstring" value="<?php echo $encoded; ?>" />
<input type="submit" value="DECRYPT" />
</form>

Open in new window

Everything inside the Encryption class is assumed to be unsigned binary data.  You only use base64 encoding to make the data into a string that is safe for transport over HTTP.   In my development I found that it was necessary to add an end-of-string delimiter to the original input strings.  The encode/decode process had a way of adding some shmutz to the end of the original string.
0
 
LVL 1

Author Comment

by:DADITWebGroup
ID: 37719878
Correct.  Their exact instructions are:  "Encrypt the Query String using DES3 and encode it using Base64 (Note that the string should NOT be URL-encoded again after the Base64 encoding.)  Then append the encrypted Query String to the URL."
0
 
LVL 52

Expert Comment

by:_agx_
ID: 37743013
I'm not sure why CF keeps asking for the generateSecretKey

That just means it doesn't see your key as valid for DESEDE. I noticed your key is shorter than what's returned by generateSecretKey.  Since CF only uses the 1st 24 bytes, try padding yours with 8 zeroes:

ie
<cfset myKey = "xxxxxx[24bit key]xxxxxxx"& "00000000">
<cfset encryptedUrl = encrypt(stmt, myKey, "DESEDE/ECB/PKCS5Padding", "Base64")>

<cfset myKey = toBase64(BinaryDecode("xxxxxx[24bit key]xxxxxxx", "Base64"))>

Fyi, that isn't needed if the key is in base64 to begin with.
0
 
LVL 1

Author Comment

by:DADITWebGroup
ID: 37743138
Thank you.  I've tried the padding of the 0's to get me the 32 bytes.  The encryptions goes through the way I expect it too, but when the 3rd party goes to decrypt it, they are unable to decrypt it because of the padding of 0's.  The last <cfset> was the very last thing I tried because I was out of ideas.  

<cfset myKey = toBase64(BinaryDecode("xxxxxx[24bit key]xxxxxxx", "Base64"))>

I've even tried to give not have any padding on the DESEDE, which becomes different issues.  
<cfset encryptedUrl = encrypt(stmt, myKey, "DESEDE/ECB/nopadding", "Base64")>
0
 
LVL 52

Expert Comment

by:_agx_
ID: 37743755
They are unable to decrypt it because of the padding of 0's.


I believe you, but it shouldn't make a difference because the docs say CF only uses the 1st 24 bytes. Do you know what the other side is using -java, c#, php?

For grins, try padding it with the 1st 8 characters of the key instead of 0's. Test it with a very simple input like "abc"
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 1

Author Comment

by:DADITWebGroup
ID: 37774405
I've requested that this question be deleted for the following reason:

Found my own solution and it was mandatory I delete it because it unknowingly contained sensitive data that I did not want referenced later.<br /><br />Thank you
0
 
LVL 52

Expert Comment

by:_agx_
ID: 37773304
What was the actual solution?
0
 
LVL 1

Accepted Solution

by:
DADITWebGroup earned 0 total points
ID: 37774377
From my experience with many webservices and APIs, there never seems to be one specific way to consume and/or use them. It all depends on the expectations of the 3rd parties code. So what works here may be very different than another solution for another API. I have worked on many and I have yet to have two be identical. Hopefully, this helps someone get at least close in the future. . .

SOLUTION:
Coldfusion using a C# 3rd Party API

<cfset myKey = "xxxxxx[24bit key]xxxxxxx"> - (no formatting needed here even though you see it later on inline within the encryption tag. Coldfusion handles it differently inside the encyption tag then when setting the variable here.)

<cfset myDate = dateformat(dateconvert( "local2Utc", now()), "YYYYMMDD")&timeformat(dateconvert( "local2Utc", now()), "HHMMSS")> - (The dateformat function does not allot for the time mask specifications, thus this needed to be separated out and appended to the end with the timeformat function.)

<cfset stmt = "User_Id=[MyUserId]&User_Password=[MyPassword]&User_TimeStamp=#variables.myDate#"> - (Due to some difference in URLEncoding formats between coding languages, the URLEncodingFormat function was sending incorrect formats and really was not needed anyhow, so it was removed from this variable set)

<cfset encryptedUrl = encrypt(stmt, toBase64(myKey), "DESEDE/ECB/PKCS5Padding", "Base64")> - (The Base64 around the key itself must be specified here because of the way Coldfusion is handling the encryption function I suspect, but am not 100% sure on that. I just know that it does not work if set in variable definition instead. One note, you also must use the PKCS5Padding when dealing with C#.)

Thank you for taking the time to put in your suggestions. Unfortunately, they did not work this time out. Have a great day!
0
 
LVL 1

Author Comment

by:DADITWebGroup
ID: 37774406
Close request can be canceled as there was resolution to our issue.
0
 
LVL 52

Expert Comment

by:_agx_
ID: 37774745
The Base64 around the key itself must be specified here because of the way Coldfusion is handling the encryption function I suspect, but am not 100% sure on that. I just know that it does not work if set in variable definition instead.

Weird, I've never experienced that one myself, but .. encryption's sensitive so that's entirely possible. Anyway, glad you found a solution .. and thanks for posting the complete details for the archives.
0
 
LVL 1

Author Closing Comment

by:DADITWebGroup
ID: 37792771
This is the only resolution that worked. (Supervisor had solution)
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
This article provides a case study on how our local youth baseball league deployed a new website, including the platform selection, implementation and benefits to the league.
The purpose of this video is to demonstrate how to integrate Mailchimp with WordPress, by placing a Mailchimp signup form on a WordPress Page or Post. This will be demonstrated using a Windows 8 PC. Mailchimp will be used. Log into your Mailchi…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now