Hashing on IOS and Xojo with the same result...


We are facing a login issue with our IOS App and our Web App.

We hash the usernames and passwords because they are sent using cookies from the login to the main Web App for authentication.
We proceed that way :

1- When the user logs in, we hash both the entered username and password and compare them to the hashed values stored in the database.
2- We create a cookie containing the hashed user name and call the URL of the main app.
3- When the main app opens, it reads the cookie, compares it against the database to identify the user and remove the cookie.

We would like to reproduce this scenario with our IOS App but we are unable to generate the same hashed values in IOS.

Here is some code we are using :

Web App Encrypting

[code]Function EncryptString(value As String) As String
Using Xojo.Core
Using Xojo.Crypto

Dim kSSMB As Xojo.Core.MemoryBlock
kSSMB = Xojo.Core.TextEncoding.UTF8.ConvertTextToData(kSS)

Dim valueMB As Xojo.Core.MemoryBlock
valueMB = Xojo.Core.TextEncoding.UTF8.ConvertTextToData(value.ToText)

Dim hash As Xojo.Core.MemoryBlock
hash = Xojo.Crypto.PBKDF2(kSSMB, valueMB, 100, 32, Xojo.Crypto.HashAlgorithms.SHA512)

Dim hashValue As String
hashValue = EncodeBase64(Xojo.Core.TextEncoding.UTF8.ConvertDataToText(hash, True),0)

Return hashValue

End Sub

IOS Encrypting

[code]Dim hashValue As Text
Dim hash As MemoryBlock

Dim kSSMB As MemoryBlock
kSSMB = Xojo.Core.TextEncoding.UTF8.ConvertTextToData(kSS)

Dim password As Text = value
Dim passwordMB As MemoryBlock
passwordMB = Xojo.Core.TextEncoding.UTF8.ConvertTextToData(password)

hash = Crypto.PBKDF2(saltMB, passwordMB, 100, 32, HashAlgorithms.SHA512)
hashValue = encodeBase64(hash)

Return hashValue[/code]

I guess it has something to do with the encodings and text conversion…

What would be the way to achieve that?


I’m not seeing anything immediately obvious, but is there a reason why you’re not using the identical method on each platform?

Edit: it’s probably the lossy ConvertDataToText in the web version. I bet the iOS version is correct as you’re using a custom encodeBase64 which doesn’t need to convert to string first.

Make sure that “value” is actually UTF8 in the web version before the conversion.

I’d also suggest comparing the memory blocks in the debugger.

Or it could be as simple as you are using two different variables in your hash calculation:

hash = Xojo.Crypto.PBKDF2(kSSMB, valueMB, 100, 32, Xojo.Crypto.HashAlgorithms.SHA512)
hash = Crypto.PBKDF2(saltMB, passwordMB, 100, 32, HashAlgorithms.SHA512)

I don’t see a direct correspondance between kSSMB and saltMB. Actually, I don’t see saltMB defined in your code snippets.


Sorry I copied and pasted too fast and made mistakes but essentially values are the same…

I compared memory blocks byte per byte for each step and It seems that the way of getting the base64 value might be the problem.

In WEB app we do like this. Note that I do have to “allowLossy” to prevent getting an exception.

Dim hashValue As Text hashValue = EncodeBase64(Xojo.Core.TextEncoding.UTF8.ConvertDataToText(hash, True),0).ToText

In IOS to get the EncodeBase64 like that :

[code]'Function EncodeBase64(Extends MB as MemoryBlock) As Text

Declare Function dataWithBytes Lib “UIKit” Selector “dataWithBytes:length:” (class_id As Ptr, bytes As Ptr, length As UInt32) As Ptr
Declare Function base64EncodedStringWithOptions Lib “UIKit” Selector “base64EncodedStringWithOptions:” (class_id As Ptr, options As UInt32) As CFStringRef

// Create NSData pointer to be point of reference.
Dim data As Ptr
data = NSClassFromString(“NSData”)

// Create NSData object using MemoryBlock
Dim dataRef as Ptr = dataWithBytes(data, mb.Data, mb.Size)

// Create Text object to hold Base64 encoded string.
Dim x As Text
x = base64EncodedStringWithOptions(dataRef, 0)

// Return Base64 encoded string
Return x
'End Function[/code]

Anyone can see what’s wrong?


See my previous answer. You’re on the right track.

Converting the hash from the memoryblock to text before base64 encoding is dropping anything that isn’t a UTF8 character.

Also, you might choose hex instead of base64 as the encode/decode routines are pretty simple to write in pure Xojo code. At least until the team gets around to giving us a built-in one. That way you don’t need to use declares.

I’d prefer using HEX but don’t know how in IOS. Could you provide me with some hints?

You simply have to iterate through the Text with Mid, then use Codepoints to get the value of the character, and use http://developer.xojo.com/integer$ToHex

[code]Function DecodeHex(Source As Text) as Xojo.Core.MemoryBlock
Dim Bytes() As UInt8
For I As Integer = 0 To Source.Length - 2 Step 2
Dim Value As UInt8 = UInt8.FromHex(Source.Mid(I, 2))
Return New Xojo.Core.MemoryBlock(Bytes)
End Function

Function EncodeHex(Block As Xojo.Core.MemoryBlock) as Text
Dim Chars() As Text
For I As Integer = 0 To Block.Size - 1
Dim Value As UInt8 = Block.UInt8Value(I)
Return Text.Join(Chars, “”)
End Function

Function EncodeHex(Value As Text, Encoding As Xojo.Core.TextEncoding) as Text
Dim Bytes As Xojo.Core.MemoryBlock = Encoding.ConvertTextToData(Value)
Return EncodeHex(Bytes)
End Function

Function DecodeHex(Source As Text, Encoding As Xojo.Core.TextEncoding) as Text
Dim Bytes As Xojo.Core.MemoryBlock = DecodeHex(Source)
Return Encoding.ConvertDataToText(Bytes)
End Function[/code]

Did not try Michel’s method but Thom’s one worked perfectly!

Thank you very much! Very very appreciated!

Michael’s answer is the same thing, I just had code laying around in an open source project anyway, so no reason not to share.