Blowfish compatibility with other blowfish implementations

I need to encrypt some text in an AWS Lambda instance in part of a web response, and then decrypt it in JUCE. Has anyone done this before? I figured BlowFish would be a good way to go. I’m using the crypto module, but there are a few different blowfish implementations available: bf, bf-cbc, bf-cfb, bf-ecb, bf-ofb.

The OpenSSL documentation has a bit more info on these:

As you can see from the "enc" help text, OpenSSL supports 4 cipher variations of Blowfish algorithm with 6 aliases:

"bf" - Alias for "bf-cbc"
"blowfish" - Alias for "bf-cbc"
"bf-cbc" - Blowfish in CBC mode
"bf-cfb" - Blowfish in CFB mode
"bf-ecb" - Blowfish in ECB mode
"bf-ofb" - Blowfish in OFB mode

I also found more reference here: https://adayinthelifeof.nl/2010/12/08/encryption-operating-modes-ecb-vs-cbc/

I can’t seem to find in the JUCE documentation what operating mode the BlowFish class uses. Before I do a lot of tedious trial and error (or interpreting the source code), has anyone tried this before?

I’m sorry I don’t have much to add, cpenny, but I would like to know this as well. Seems like a simple question for the JUCE team to answer.

I just went without encryption for now — as it turns out it was unnecessary for my specific application.

This could be a great JUCE demo — I’m sure people will be using JUCE apps alongside web apps more and more. I would love to see an “official” working implementation of encryption in Node.js and decryption in JUCE.

+1 Would be good to know which mode is used, and even better, an example with openssl encryption and JUCE decryption.

I want to use openssl_encrypt on our server too, so knowing which cipher mode the BlowFish algorithm uses is quite essential. @jules should know :wink:

I couldn’t tell you for sure, it’s years since I wrote it, but I assume it’s the most common one: CBC

Looking at the code I’d say the mode is ECB. There is no feedback of the previous cipher into the next block encryption.

I’m actually quite sure it’s not the most common one. Or some of the other settings differ with common defaults. If I remember correctly I tried both ECB and CBC and neither worked.

In the end I ended up using cryptopp instead of juce’s crypto module, and I’ve heard from more parties they struggled with getting BlowFish to work. Sounds like perhaps it warrants another review?

We decided to not use the JUCE implementation. Even if we could get it to work, ECB is too insecure to be useful.

See: TwoFish and ThreeFish

Cheers,

Rail

reFX wrote:
We decided to not use the JUCE implementation. Even if we could get it to work, ECB is too insecure to be useful.

I know this is an old thread.
But I am curious: how is the JUCE Blowfish too insecure? I was planning on using it myself…
I am a newbie on encryption. Sorry, if this question is too obvious :slight_smile:

For a quick visual example:

Thanks, I see. Interesting.
Is this picture the “real” thing? Or just a visualisation?

That’s a real example of what it looks like to use Blowfish with only EBC algorithm. If you used the same input image, you would get the same output.

It’s really quite unusable. It’s very unsafe. You will find plenty of better encryption/decryption algorithms online then using JUCEs Blowfish implementation.

Here is a header-file only implementation of both (EBC and CBC). You should use the CBC methods:

https://defuse.ca/blowfish.htm

Sorry to reanimate this. The Blowfish implementation in JUCE does not play nicely with OpenSSL / Cryptopp because it reads the data in host endian mode. This probably also means that you cannot encode with JUCE on BigEndian and decode on LittleEndian. Apparently other implementations have had the same issue before (see https://stackoverflow.com/questions/11422497/whats-the-difference-between-blowfish-and-blowfish-compat).

I was able to make it match cryptopp and openssl using the following patch.

diff --git a/modules/juce_cryptography/encryption/juce_BlowFish.cpp b/modules/juce_cryptography/encryption/juce_BlowFish.cpp
index fb4fa22e5..c585392b5 100644
--- a/modules/juce_cryptography/encryption/juce_BlowFish.cpp
+++ b/modules/juce_cryptography/encryption/juce_BlowFish.cpp
@@ -330,7 +330,13 @@ bool BlowFish::apply (void* data, size_t size, void (BlowFish::*op) (uint32&, ui
    auto* ptr = reinterpret_cast<AlignedAccessHelper*> (data);

    for (size_t i = 0; i < n; ++i)
-        (this->*op) (ptr[i].data[0], ptr[i].data[1]);
+    {
+        uint32 a = ByteOrder::swapIfLittleEndian(ptr[i].data[0]);
+        uint32 b = ByteOrder::swapIfLittleEndian(ptr[i].data[1]);
+        (this->*op) (a, b);
+        ptr[i].data[0] = ByteOrder::swapIfLittleEndian(a);
+        ptr[i].data[1] = ByteOrder::swapIfLittleEndian(b);
+    }

    return true;
}
1 Like

Wow, I am glad you shared this @harrycodex. Since the juce team doesn’t respond to pull requests, I hope this gets some attention from them on the forum and gets merged ASAP!

Merging a change like this is difficult, because it would be backwards incompatible with things encrypted with previous versions. I’m not sure how I would choose to fix that, constructor option or different class name maybe.

1 Like

That would mean that is not even blowfish anymore. It should be renamed to something else and a real blowfish algo should be implemented.

1 Like

To be fair the function that just takes 2 uint32_ts is the blowfish algorithm as far as I can tell. It’s not totally clear to me where the specification that those uin32_ts should be read from the buffer as big endian comes from, but I’m sure it is somewhere.

There are several that are open-source. I don’t know if they’re single-header implementations, though. And I think the only official ones are the openssl and the bcrypt implementations.

I personally think that stuff encrypted with the old juce::BlowFish implementation would need to be re-encrypted with the new version, if the new version is actually correct.