Skip to main content
New Participant
September 23, 2009
Answered

Blowfish Encrypt() output differs from Blowfish encryption in PHP and other languages

  • September 23, 2009
  • 2 replies
  • 10052 views

I need to post the result of a blowfish hex encryption to an external API. 

The result of encrypt(myText, key, "BLOWFISH", "HEX") gives me a value that I can decrypt just fine in coldfusion, but apparently not the same value as you would get if you ran the same encryption (blowfish, hex) using PHP or Java. 

Essentially I'm trying to make the result of
encrypt(myText, key, "BLOWFISH", "HEX")
match what you get using this tool:
http://webnet77.com/cgi-bin/helpers/blowfish.pl
this tool seems to output the result that would be generated by php and what the API expects.

I'm not sure why the result differs or what options I would need to change to make Coldfusion generate the correct value.


I've tried padding the myText variable with null characters to fill it so the length is a multiple of 8 (have to use URLDecode("%00") instead of char(0) as the null character, since char(0) doesn't actually increase the length of the string).  But that doesn't seem to have much of any effect.


If someone can make the result of coldfusion's blowfish encryption match what you get using that tool above I would really appreciate it.

This topic has been closed for replies.
Correct answer -__cfSearching__-

Still no clue why Coldfusion's Blowfish encryption is different, but here's the code for using java in case anyone else runs into the same issue:

Just to follow-up, it turns out the CF key needs to be in base64 format (and have a valid key length) to get the same result from CF+Java. (I hate it when it is something that simple .. ;-)

<-cfset myText = "whatever">
<cfset plainKey = "something" />
<cfset keyInBase64 = BinaryEncode(CharsetDecode(plainKey, "utf8"), "base64")>
<cfset cfEncrypted = encrypt(myText, keyInBase64, "Blowfish/ECB/NoPadding", "HEX")>


<cfset Cipher = createObject("java", "javax.crypto.Cipher")>
<cfset encryptor = Cipher.getInstance("Blowfish/ECB/NoPadding")>
<cfset keySpec = createObject("java", "javax.crypto.spec.SecretKeySpec").init(plainKey.getBytes(), "Blowfish")>
<cfset encryptor.init(Cipher.ENCRYPT_MODE, keySpec)>
<cfset encryptedTextFromJava = encryptor.doFinal(myText.getBytes())>
<cfset javaEncrypted = BinaryEncode(encryptedTextFromJava, "HEX")>

<cfoutput>
cfEncrypted = #cfEncrypted#<br>
javaEncrypted = #javaEncrypted#<br>
</cfoutput>

2 replies

BKBK
Community Expert
September 26, 2009

Essentially I'm trying to make the result of encrypt(myText, key, "BLOWFISH", "HEX") match what you get using this tool:
http://webnet77.com/cgi-bin/helpers/blowfish.pl
this tool seems to output the result that would be generated by php

Not Perl?

I'm not sure why the result differs or what options I would need to change to make Coldfusion generate the correct value.

The author of that tool has to let you know his or her Initialization Vector. Different Blowfish IVs will produce different results even when the key is  the same.

khusroksAuthor
New Participant
September 26, 2009

There was no IV for the encryption.

Anyway - I ended up solving it by instantiating a java object - and the java encryption gave the result that was expected.

Still no clue why Coldfusion's Blowfish encryption is different, but here's the code for using java in case anyone else runs into the same issue:

<cfset myText = "something">
<cfset myKey="somethingelse">
<!--- get a cipher instance --->
<cfset Cipher = createObject("java", "javax.crypto.Cipher")>
<cfset encryptor = Cipher.getInstance("Blowfish/ECB/NoPadding")>
<!--- must convert the key string into a KeySpec object first --->
<cfset keySpec = createObject("java", "javax.crypto.spec.SecretKeySpec").init(myKey.getBytes(), "Blowfish")>
<!--- initialize the cipher for encrypting --->
<cfset encryptor.init(Cipher.ENCRYPT_MODE, keySpec)>
<!--- do the encrypt --->
<cfset encryptedTextFromJava = encryptor.doFinal(myText.getBytes())>
<!--- finally convert it to hex --->
<cfset encryptedText = BinaryEncode(encryptedTextFromJava, "HEX")>
<cfoutput>
        encryptedText = #encryptedText#
<br>
</cfoutput>
BKBK
Community Expert
November 25, 2009

Still no clue why Coldfusion's Blowfish encryption is different, but here's the code for using java in case anyone else runs into the same issue:

Just to follow-up, it turns out the CF key needs to be in base64 format (and have a valid key length) to get the same result from CF+Java. (I hate it when it is something that simple .. ;-)

<-cfset myText = "whatever">
<cfset plainKey = "something" />
<cfset keyInBase64 = BinaryEncode(CharsetDecode(plainKey, "utf8"), "base64")>
<cfset cfEncrypted = encrypt(myText, keyInBase64, "Blowfish/ECB/NoPadding", "HEX")>


<cfset Cipher = createObject("java", "javax.crypto.Cipher")>
<cfset encryptor = Cipher.getInstance("Blowfish/ECB/NoPadding")>
<cfset keySpec = createObject("java", "javax.crypto.spec.SecretKeySpec").init(plainKey.getBytes(), "Blowfish")>
<cfset encryptor.init(Cipher.ENCRYPT_MODE, keySpec)>
<cfset encryptedTextFromJava = encryptor.doFinal(myText.getBytes())>
<cfset javaEncrypted = BinaryEncode(encryptedTextFromJava, "HEX")>

<cfoutput>
cfEncrypted = #cfEncrypted#<br>
javaEncrypted = #javaEncrypted#<br>
</cfoutput>


@ -==cfSearching==-
Some detective work, there, old chap!

Inspiring
September 25, 2009

My instincts tell me that you need to come up with a different approach.

If you're expecting two entirely-unrelated language implementation teams, not only "to come up with compatible implementations" but to continue to do so for (perhaps...?) the next twenty-five years, "it ain't gonna happen."

And you ... or your successor (who is cursing your name posthumously after you had "that very unfortunate with a bread truck") ... might well be stuck with several gigabytes of un-decryptable data.  "Don't go there!"

If two applications need to talk to each other in such a way that no one can understand what they are saying, don't attempt a "roll your own" solution.  Instead, require that an encrypted secure communication-channel must exist between the two parties ... using proven, commercially available technologies such as VPN or SSL.  The information which the two parties send to each other is "in the clear."

Likewise, if you need to store secret data in a database, arrange for the database management system to secure that database on your behalf.  Make sure that your connection to the DBMS is likewise "flowing across a secure network channel."

If you need to store data securely on the hard drive, arrange to use an encrypted disk-volume.

In all of these cases, you have succeeded in removing the obligation for security from your application.  You have passed-the-buck to known-good third parties.  You have also built your app to rely upon technologies that the IS infrastructure people already know how to manage.

khusroksAuthor
New Participant
September 26, 2009

I need to encrypt data using blowfish in order to post to an API.

Currently, the API has libraries for PHP, Java, .NET, Perl and Delphi but no Coldfusion, so I have to write the functions myself.

All these languages encrypt data using algorithm=BLOWFISH, mode=ECB, encoding=HEX and produce exactly the same result, so the API accepts it.  When I try to do it in CF, it produces a different result, so I cannot post to the API.

If PHP, Java, .NET, Perl and Delphi can come up with compatible implementations of Blowfish, why can't Coldfusion? Coldfusion is obviously the outlier, and is doing something different from the "standard" implementation of this encryption method - I'm trying to understand what that difference is, and if I can somehow bring it in line with the rest of the world.

At this point, I've been working on this for a week and the solution seems no closer.  I've even tried using Sean Corfield's cf_php, but that doesn't work because its implementation of the unpack function seems to have a bug.

Inspiring
September 26, 2009

Interesting.

Can you pls post your CF, Java & PHP code which demonstrate this?

Cheers.

--

Adam