I copied the relevant C code into an Xcode project so I could compare my results. This let me work out the bugs and I could replicate the results, so I’m good to go with encode_base64 and decode_base64. That was a great refresher.
Unfortunately, before I move forward, I find that I must implement Blowfish itself as found in the blf.h header file, and I can’t find the right code. I’ve found implementations of Blowfish, to be sure, and some seem easy to translate to Xojo (especially the ones found here), but I’m not sure if I need the right one.
It looks like a good implementation, even if the code can be modernized a bit. Unfortunately, it uses a different, simpler implementation (by Paul Kocher), not Schneier’s original, and that’s what this bcrypt version is expecting. I might be able to use it anyway, but I don’t understand enough (yet) about what it’s doing to trust that I’d adapt it correctly.
So I get the x is passed as pointer to an UInt32, but what does x[0] and x[1] do? Do they split the value up into two UInt16 values? Because my Xcode tests don’t show that, and I can’t figure out what it’s supposed to mean otherwise.
Oh crap, you’re right, I should have checked other parts of the code where this sub was actually being called. What threw me is, in my test, I gave it a straight UInt32, and it didn’t complain.
It’s C, of course it didn’t. Why should I be surprised?
Yes C will give you unrestricted freedom to do whatever you want and won’t think twice about it. It’s rather dangerous code though because I’d imagine if you did give it a normal uint32 then it would go out of bounds and crash because, as far as I can see, there’s no checking to see if the pointer does indeed point to an array before it attempts to access the elements.
A speed optimisation perhaps? I’m not sure. I can’t imagine that a quick sizeof check would slow things too much.
C doesn’t really have any way to check. All it knows is you passed it a number. It assumes that it’s a memory address, but there’s no way to verify that it’s legit.
You’re correct. For some reason I thought there was a way to do a proper check but it would seem that the best one can do is simply check if it’s pointing to NULL or not.
To clarify (since I’m now waiting for the profiler to do its thing), I’ve translated the relevant parts of the blf.c library, then translated the bcrypt code. I ran a single test on a known key with a known salt and got the identical result as the Xcode test I set up using the original code, and using PHP.
But it’s significantly slower than the C version so I’m working on a bit of optimization now.
Well, it may be too slow to be practical, or maybe there are ways to optimize this that I’m just not thinking about at the moment.
The first bit of code that could use some love is this. Anyone see a faster way?
Private Function F(x As UInt32) As UInt32
dim a, b, c, d As UInt8
dim y As UInt32
d = x and &h00FF
x = Bitwise.ShiftRight( x, 8 )
c = x and &h00FF
x = Bitwise.ShiftRight( x, 8 )
b = x and &h00FF
x = Bitwise.ShiftRight( x, 8 )
a = x and &h00FF
y = S( 0, a ) + S( 1, b )
y = y Xor S( 2, c )
y = y + S( 3, d )
return y
End Function
Here was my solution to that. I’ve managed to cut down processing time from about 4 seconds to a little over two. So far.
Private Function F(x As UInt32) As UInt32
dim a, b, c, d As Integer
dim y As UInt32
static mb as new MemoryBlock( 4 )
static p as Ptr = mb
p.UInt32( 0 ) = x // LittleEndian = True
a = p.Byte( 3 )
b = p.Byte( 2 )
c = p.Byte( 1 )
d = p.Byte( 0 )
y = S( 0, a ) + S( 1, b )
y = y Xor S( 2, c )
y = y + S( 3, d )
return y
End Function