bcrypt project

I’d like to port bcrypt, found here, to Xojo, but I’m afraid my C is just not up to the task, so I thought I’d throw a few specific questions out there to help move it along. I’ll make the final product available when finished.

If there is enough interest, I’ll even throw the project up onto GitHub.

The first question comes from this code:

static void
encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
{
	u_int8_t *bp = buffer;
	u_int8_t *p = data;
	u_int8_t c1, c2;
	while (p < data + len) {
		c1 = *p++;
		*bp++ = Base64Code[(c1 >> 2)];
		c1 = (c1 & 0x03) << 4;
		if (p >= data + len) {
			*bp++ = Base64Code[c1];
			break;
		}
		c2 = *p++;
		c1 |= (c2 >> 4) & 0x0f;
		*bp++ = Base64Code[c1];
		c1 = (c2 & 0x0f) << 2;
		if (p >= data + len) {
			*bp++ = Base64Code[c1];
			break;
		}
		c2 = *p++;
		c1 |= (c2 >> 6) & 0x03;
		*bp++ = Base64Code[c1];
		*bp++ = Base64Code[c2 & 0x3f];
	}
	*bp = '\\0';
}

What is an u_int8_t? I get that it’s an UInt8, but what’s the “_t” about? The answer to this will help me understand the parameters and how they are being used.

And does this code ultimately do the same as Xojo’s EncodeBase64?

I’m no expert but I’m fairly sure the _t is simply a naming convention to show that it’s been typedef’d. Fairly common to see in C.

Evidence:
http://lxr.free-electrons.com/source/include/uapi/linux/coda.h#L123
http://stackoverflow.com/questions/1391447/what-does-the-postfix-t-stand-for-in-c

Got it. So the C code:

static void
encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)

Would translate to Xojo as:

Function encode_base64 (ByRef buffer As UInt8, ByRef data As UInt8, thelen As UInt16)

Yes?

encode_base64(buffer As MemoryBlock, data As MemoryBlock)

thelen -> data.size

Except it looks like this function is expecting a single value, and will use it to do calculations, so u_int8_t *buffer is a pointer to a single byte, isn’t it?

I feel like I’m missing something in how C treats these variables.

why would you want to port a base64 encode function to Xojo where already one exists?

I’m using this as an example to learn. The answers here will help me understand other parts of the code.

And you missed the last line of my original question.

[quote=60968:@Kem Tekinay]Except it looks like this function is expecting a single value, and will use it to do calculations, so u_int8_t *buffer is a pointer to a single byte, isn’t it?
[/quote]
more like the starting address of a sequence of bytes

the reason I say this is

u_int8_t *bp = buffer; u_int8_t *p = data;
and subsequently all the ptr math

c1 = *p++; *bp++ = Base64Code[(c1 >> 2)];
etc
which steps through the byes pointed at by those two ptrs

Hi Kem,

u_int8_t *buffer
means “a pointer to” and not “a pointer to a single value” so it is something “like” a memory block but you don’t know how big it is the memory area.
u_int16_t len reports how big it is the memory area (up to 65536 bytes in this case)

C language syntax…

Thank you both, that’s clearer, and a reminder of why I so love that Xojo doesn’t make me do pointer math. :slight_smile:

Oops…

up to 65535 bytes… (while (p < data + len))

Sorry I’m late to the party.

Could bcrypt be written as part of the crypto class like BER, DER, MD5, etc? I am asking for feasibility here not asking Kem to do it.

I think having bcrypt, blowfish, twofish, etc added to the Xojo crypto class would be a win for Xojo. The more crypto options the better.

Kem good luck with the port to xojo.

Thanks. At this point, I’m still renewing my relationship with C. Like an almost-ex, I am being reminded why I didn’t want to get involved in the first place…

Hahahahahahaha

C is my Ex. The crazy starker Ex that pops up when you least expect or want it to. And it is an Ex for a reason.

Good news is you are writing Xojo and just having to read/understand c. Which at times can’t be easy.

It’s the pointer math I’m finding hard to decipher. *p++ (or something) means something different than p++. Very annoying.

[quote=60963:@Kem Tekinay]Got it. So the C code:

static void
encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)

Would translate to Xojo as:

Function encode_base64 (ByRef buffer As UInt8, ByRef data As UInt8, thelen As UInt16)

[/quote]

Probably not - I think that the *buffer and *data should be considered “Pointers to an array of values” rather than “Pointers to one single value” so I’d write it as follows:

Function encode_base64 (buffer As MemoryBlock, data As MemoryBlock, thelen As UInt16)

Right. As Maurizio pointed out, theLen could probably be avoided too as it should be the same as data.Size.

The difference between *p++ and p++ is this:

p refers to the pointer itself.
*p points at the pointer’s value.

p++ is to increment the pointer address (moving it to the next part of the array it points to, for example).
*p++ increments the value that the pointer points to.

I wrote this example to hopefully clarify further:

[code]// make an integer array with two elements
int a[2];
a[0] = 0;
a[1] = 0;

// make a pointer
int *p;
// point the pointer to the array’s first element
p = &a[0];

// increase the value of a[0] by 1
*p++;

// print this value
printf("%d
", *p); // 1 is printed

// make p point to a[1]
p++;

// print this value
printf("%d
", *p); // 0 is printed[/code]

With this in mind you can always print the pointer’s address by referring to p. Then when you want to print the pointer’s value you refer to *p.

Thanks Joshua, that was very helpful. Believe it or not, I knew this at one time, but that’s how far removed I’ve become from trying to learn C. :slight_smile:

So, with this in mind, I think I’ve translated this code faithfully. (I realize this is not the optimal way to do it in Xojo given its tools, but my goal here is get the closest translation I can get. I’ll optimize later.)

Again, the C code:

static void
encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
{
	u_int8_t *bp = buffer;
	u_int8_t *p = data;
	u_int8_t c1, c2;
	while (p < data + len) {
		c1 = *p++;
		*bp++ = Base64Code[(c1 >> 2)];
		c1 = (c1 & 0x03) << 4;
		if (p >= data + len) {
			*bp++ = Base64Code[c1];
			break;
		}
		c2 = *p++;
		c1 |= (c2 >> 4) & 0x0f;
		*bp++ = Base64Code[c1];
		c1 = (c2 & 0x0f) << 2;
		if (p >= data + len) {
			*bp++ = Base64Code[c1];
			break;
		}
		c2 = *p++;
		c1 |= (c2 >> 6) & 0x03;
		*bp++ = Base64Code[c1];
		*bp++ = Base64Code[c2 & 0x3f];
	}
	*bp = '\\0';
}

My translation. Does it appear that I’ve gotten this right?

Private Sub encode_base64(buffer As MemoryBlock, data As MemoryBlock)
  dim lastByteIndex as integer = data.Size - 1
  dim bp, p as integer
  
  dim c1, c2 as byte
  while ( p <= lastByteIndex )
    c1 = data.Byte( p )
    p = p + 1
    
    buffer.Byte( bp ) = Base64Code( Bitwise.ShiftRight( c1, 2 ) )
    bp = bp + 1
    
    c1 = Bitwise.ShiftLeft( c1 and &h03, 4 )
    if p > lastByteIndex then
      buffer.Byte( bp ) = Base64Code( c1 )
      exit while
    end if
    
    c2 = data.Byte( p )
    p = p + 1
    
    c1 = c1 or ( Bitwise.ShiftRight( c2, 4 ) and &h0F )
    buffer.Byte( bp ) = Base64Code( c1 )
    bp = bp + 1
    
    c1 = Bitwise.ShiftLeft( c2 and &h0F, 2 )
    if p > lastByteIndex then
      buffer.Byte( bp ) = Base64Code( c1 )
      bp = bp + 1
      exit while
    end if
    
    c2 = data.Byte( p )
    p = p + 1
    
    c1 = c1 or ( Bitwise.ShiftLeft( c2, 6 ) and &h03 )
    buffer.Byte( bp ) = Base64Code( c1 )
    bp = bp + 1
    buffer.Byte( bp ) = Base64Code( c2 and &h3F )
    bp = bp + 1
  wend
  
  buffer.Byte( bp ) = 0  
End Sub

I should note that this code works without error, but the result differs completely from what I get from EncodeBase64.