M_Crypto (formerly Blowfish and Bcrypt project)

So now there’s this:

https://github.com/ktekinay/Blowfish

I’ve implemented Blowfish and Bcrypt here and added some tests. Feel free to play around with it and make suggestions. The C libraries I worked from are included as Xcode projects.

Note that Bcrypt is slow. Not as slow as it was when I first converted it (around 4 seconds down to under 1 second), but much slower than it should be. Other implementations like C or PHP take far less time to do the same thing (under 100 ms), so any suggestions here would be appreciated, but I think it’s just the overhead of the repeated method calls.

congrats on the module.

Good work!

I’ve made some changes since I posted this to make block chaining with CBC easier and more intuitive. It will now retain the last vector until isFinalBlock is True. The example code was updated too. So, for example, if you were encrypting a file:

dim blf as new Blowfish_MTC
blf.SetVector( "12345678" ) // Not needed, but if you really want to

bs = BinaryStream.Open( f, true )
while not bs.EOF
  dim curPos as UInt64 = bs.Position
  dim block as MemoryBlock = bs.Read( 1024 ) // Has to be a multiple of 8
  blf.EncryptCBC( block, bs.EOF ) // Encrypts in place, resizes block if needed
  bs.Position = curPos
  bs.Write block // Overwrites the data with the encrypted version
wend

To decrypt:

dim blf as new Blowfish_MTC
blf.SetVector( "12345678" ) // Not needed, but if you really want to

dim newLength as UInt64
bs = BinaryStream.Open( f, true )
while not bs.EOF
  dim curPos as UInt64 = bs.Position
  dim block as MemoryBlock = bs.Read( 1024 ) // Has to be a multiple of 8
  blf.DecryptCBC( block, bs.EOF ) // Decrypts in place, resizes block if needed
  bs.Position = curPos
  bs.Write block // Overwrites the data with the encrypted version
  newLength = newLength + block.Size
wend
bs.Length = newLength // In case the last block was padded

This https://dl.dropbox.com/u/42287079/Blowfish%20Example.zip is the implementation I use. Do I need to update?

Or more importantly does there need to be somewhere to store this stuff so we don’t reinvent the wheel?

I don’t know, but I like mine better. :slight_smile:

That code has a bug, though. Specifically, if you encrypt data that is a perfect multiple of 8 bytes, and the last byte value X is > 0 and < 8, the decryption code will improperly strip the last X bytes from the decrypted text, corrupting it. My code won’t do that.

I came up with a padding scheme that is based on other recommendations, but avoids that potential bug. I add X-1 nulls followed by X to get the final block up to a multiple of 8. BUT, if only 1 byte is needed, I add 9 bytes instead. When decrypting, I check the last byte X and, if it’s >= 2 and <= 9, I make sure it’s really X-1 nulls followed by X. Only then do I strip it.

What’s more, when encrypting, if the last block is already a perfect multiple of 8, I make sure the last few bytes wouldn’t be mistaken for padding. For example, if your data ends in &h00 02, the decryption code would think that’s padding and strip it, so my code adds &h00 00 00 00 00 00 00 08 to the final block.

Well crap, that leads to another bug when chain decrypting and padding is 9 bytes. If the final 8 come in by themselves, there is no way to know that the null in the next-to-last block wasn’t supposed to be there. I have to think on this some more…

OK, that’s fixed. Now it will hold the last null of an intermediate block in reserve and add it to the next block so it can properly test the pad.

Also added a special case while encrypting the final block. If it’s a multiple of 8 and the last 8 are all nulls followed by a 9, an additional pad will be added.

Just asking but which is the most secure encryption method: AES of Blowfish ?

BTW the blowfish class of MBS is super fast - way faster than your code. Maybe you should ask Christian why it is working blistering fast with his plugins.

It’s working blistering fast because his plugins are written in C, not Xojo. The C code I based it on (included as an Xcode project) is blistering fast too.

AES is considered more secure. AES is the Rijndael algorithm, developed by 2 Belgian scientists at the University of Leuven and is chosen as the Advanced Encryption Standard a couple of years ago.

In theory it is not crackable as the amount of possible keys is gigantic. That is why it can withstand brute force attacks.

Based on my quick research, AES is preferred, but neither has been broken. Theoretically, Blowfish (which has been replaced by TwoFish) isn’t as secure because it uses 64-bit blocks vs. 128-bit blocks, but I believe that’s still just theory.

Looks like I’ll have to get started on an AES implementation…

Here is a VB source I kept for years: https://www.dropbox.com/s/vgx404katj94y1r/CRijndael.VB

That must be a good thing. :slight_smile:

I don’t know. I thought it sounded like the start of a joke :wink:

Yes indeed. But a joke from a Dutch point of view then.

I have an all-Xojo AES implementation that I never quite got around to finalizing, documenting or releasing for some reason. (I think I got sidetracked on the documentation by falling down the rabbit hole of rewriting my source code documentation generator. That and deciphering the US export rules for open source encryption code)

The encryption code itself was a sidetrack from working on my SNMP code for the v3 implementation.

When working on side projects for fun, I tend to get distracted quite… Squirrel!

Forum for Xojo Programming Language and IDE. Copyright © 2021 Xojo, Inc.