AES sample

bluedude

Well-Known Member
Licensed User
Longtime User
I want to do AES encryption (there is no support for https it seems) for transmitting data safely from my backend web services to the android client.

I'm using an AES encryption class on the backend and I want to use AES too on the client.

Has anyone done something with the new encryption library how to use it?
 

sioconcept

Active Member
Licensed User
Longtime User
Sorry. My previous code was wrong.
The key length must be of a specific size.
One way you can do it is to first calculate a MD5 hash of the string:
B4X:
Sub Activity_Create(FirstTime As Boolean)
Dim kg As KeyGenerator
kg.Initialize("AES")
Dim md As MessageDigest
Dim p As String
p = "mypassword"
kg.KeyFromBytes(md.GetMessageDigest(p.GetBytes("UTF8"), "MD5"))
Dim c As Cipher
c.Initialize("AES")
Dim data() As Byte
data = c.Encrypt("some data".GetBytes("UTF8"), kg.Key, False)
data = c.Decrypt(data, kg.Key, False)
Msgbox(BytesToString(data, 0, data.Length, "UTF8"), "")
End Sub


Ok ok, i send data with HttpUtils and base64 encoding, all it's ok but i don't know how i can discover the decryted word in PHP. Help me please !

I've try in PHP : ($decrypt in php = data in string from B4A)

PHP:
   $decoded = base64_decode($decrypt);
   $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
   $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $mc_key, trim($decoded), MCRYPT_MODE_ECB, $iv));

what's the problem ??? :BangHead:
 
Upvote 0

sioconcept

Active Member
Licensed User
Longtime User
AES Encode from B4A / Decode to PHP

Eureka ! So, nobody help me... I'm forever alone :)
This code can encode under B4A and decode with PHP in AES RIJNDAEL_128 / MODE CBC.

Note : mcrypt must be installed & activate in your apache server.

B4X:
Sub CryptAES(PassWord As String, Data As String)

   Dim su As StringUtils
   Dim kg As KeyGenerator
   Dim C As Cipher
   Dim md As MessageDigest
   Dim encrypted() As Byte
   
   kg.Initialize("AES")
   kg.KeyFromBytes(md.GetMessageDigest(PassWord.GetBytes("UTF8"), "MD5"))
   
   C.Initialize("AES")
   encrypted = C.Encrypt(Data.GetBytes("UTF8"), kg.Key, False)

   Return su.EncodeBase64(encrypted)
   
End Sub

And the second part in PHP to decode it

PHP:
function DecryptAES($key, $data) {
   if(16 !== strlen($key)) $key = hash('MD5', $key, true);
   $padding = 16 - (strlen($data) % 16);
   $data .= str_repeat(chr($padding), $padding);
   return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
}

use in B4A :
B4X:
Log(CryptAES("password", "B4A for Fun !"))
return : FbxYokKgqSe2bazqjboM8Q==

and PHP :
PHP:
echo DecryptAES('password', base64_decode('FbxYokKgqSe2bazqjboM8Q=='));
return : B4A for Fun !
 
Upvote 0

aalekizoglou

Member
Licensed User
Longtime User
Sioconcept

I am trying to use the code you posted in PHP. Line

echo DecryptAES('password', base64_decode('FbxYokKgqSe2bazqjboM8Q=='))

does not return "B4A for Fun !" but rather ">„γ_’•΅¤nƒή΅Oχ}φ¥pτUO\x14δ\t‰Ϋλ-\xFΧ\x5"

I've copied exactly your code

B4X:
function DecryptAES($key, $data) { 
    if(16 !== strlen($key)) $key = hash('MD5', $key, true); 
    $padding = 16 - (strlen($data) % 16); 
    $data .= str_repeat(chr($padding), $padding); 
    return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16)); 
}

Am I missing something?
 
Upvote 0

aalekizoglou

Member
Licensed User
Longtime User
Well,

I found those PHP functions that work. I post aes256Encrypt / aes256Decrypt as well in case someone needs them.

B4X:
function aes128Encrypt($key, $data) {
  if(16 !== strlen($key)) $key = hash('MD5', $key, true);
  $padding = 16 - (strlen($data) % 16);
  $data .= str_repeat(chr($padding), $padding);
  return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
}

function aes128Decrypt($key, $data) {
  if(16 !== strlen($key)) $key = hash('MD5', $key, true);
  $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
  $padding = ord($data[strlen($data) - 1]); 
  return substr($data, 0, -$padding); 
}

function aes256Encrypt($key, $data) {
  if(32 !== strlen($key)) $key = hash('SHA256', $key, true);
  $padding = 16 - (strlen($data) % 16);
  $data .= str_repeat(chr($padding), $padding);
  return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
}

function aes256Decrypt($key, $data) {
  if(32 !== strlen($key)) $key = hash('SHA256', $key, true);
  $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
  $padding = ord($data[strlen($data) - 1]); 
  return substr($data, 0, -$padding); 
}
 
Upvote 0

aalekizoglou

Member
Licensed User
Longtime User
Now I can see another strange behavior, that has to do with the length of the string encrypted. To be more specific when I try to encrypt less than 16 bytes both B4A and PHP give me the same result. If I try to do it for more bytes, I get different results.

Code used in B4A

B4X:
Sub Encrypt(dataToEncrypt As String)

    Dim su As StringUtils
    Dim kg As KeyGenerator
    Dim C As Cipher
    Dim md As MessageDigest
    Dim encrypted() As Byte
    Dim cHashKey as String
   
    cHashKey = "12345"

    kg.Initialize("AES")
    kg.KeyFromBytes(md.GetMessageDigest(cHashKey.GetBytes("UTF8"), "MD5"))
       
    C.Initialize("AES")
    encrypted = C.Encrypt(dataToEncrypt.GetBytes("UTF8"), kg.Key, False)

    Return su.EncodeBase64(encrypted)    
End Sub

Code used in PHP

B4X:
function aes128Encrypt($key, $data) {
  if(16 !== strlen($key)) $key = hash('MD5', $key, true);
  $padding = 16 - (strlen($data) % 16);
  $paddingchar = chr($padding);
  $data .= str_repeat($paddingchar, $padding);
  return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
}


in B4A Log(Encrypt("01234567890123")) : c4aNrMLILmdchEx0uF/0Kw==
in PHP echo aes128Encrypt("12345", "01234567890123") : c4aNrMLILmdchEx0uF/0Kw==

in B4A Log(Encrypt("012345678901234")) : EBmhsAa5/qJY0jyXE88weA==
in PHP echo aes128Encrypt("12345", "012345678901234") : EBmhsAa5/qJY0jyXE88weA==

in B4A Log(Encrypt("0123456789012345")) : Y02tWZNfiKQxT6dkEBPGzVixTKadbOwfkjfWXb5zolU=
in PHP echo aes128Encrypt("12345", "0123456789012345") : Y02tWZNfiKQxT6dkEBPGzfUl1j9IC5gOruhew+bW1vs=

So with 16 bytes encryption you can spot the difference
B4A: Y02tWZNfiKQxT6dkEBPGzVixTKadbOwfkjfWXb5zolU=
PHP: Y02tWZNfiKQxT6dkEBPGzfUl1j9IC5gOruhew+bW1vs=

I don't suppose this has to do with padding because with 1-15 bytes (that should be padded in B4A) the result is the same both in B4A and PHP.

Does anyone have any thought about this?
 
Upvote 0

aalekizoglou

Member
Licensed User
Longtime User
Probably because of Cipher Block Chaining differences.

Meaning??? :sign0085:

Is this something I can correct someway by altering the PHP or B4A function?

Maybe I need to go with another encryption algorithm?
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
kg.Initialize("AES")
This is probably equivalent to "AES/ECB/PKCS5Padding" where ECB means Electronic Code Book mode.

return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
I don't know PHP but that looks like Cipher Block Chaining mode.

Another encryption algorithm will not help. You need to understand the different ways that symmetric algorithms are used.
 
Last edited:
Upvote 0

aalekizoglou

Member
Licensed User
Longtime User
Agraham you are right,

the problem is in PHP. I needed:
mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB, str_repeat("\0", 16))

So for any future usage and for anyone who is interested here is the code I used for B4A and PHP

B4A
B4X:
Sub Encrypt(dataToEncrypt As String) As String
    Dim su As StringUtils
    Dim kg As KeyGenerator
    Dim C As Cipher
    Dim md As MessageDigest
    Dim encrypted() As Byte
   
   If cHashKey.Trim = "" Then Return False

    kg.Initialize("AES")
    kg.KeyFromBytes(md.GetMessageDigest(cHashKey.GetBytes("UTF8"), "MD5"))
       
    C.Initialize("AES/ECB/PKCS5Padding")
    encrypted = C.Encrypt(dataToEncrypt.GetBytes("UTF8"), kg.Key, False)

    Return su.EncodeBase64(encrypted)
End Sub

Sub Decrypt(dataToDecrypt As String) As String
    Dim su As StringUtils
    Dim kg As KeyGenerator
    Dim C As Cipher
    Dim md As MessageDigest
    Dim decrypted() As Byte
   Dim BConv As ByteConverter
   
   If cHashKey.Trim = "" Then Return False

    kg.Initialize("AES")
    kg.KeyFromBytes(md.GetMessageDigest(cHashKey.GetBytes("UTF8"), "MD5"))
       
    C.Initialize("AES/ECB/PKCS5Padding")

   decrypted = su.DecodeBase64(dataToDecrypt)
    decrypted = C.Decrypt(decrypted, kg.Key, False)

    Return BConv.StringFromBytes(decrypted, "UTF8")
End Sub

PHP

B4X:
function aes128Encrypt($key, $data) {
  if(16 !== strlen($key)) $key = hash('MD5', $key, true);
  $padding = 16 - (strlen($data) % 16);
  $paddingchar = chr($padding);
  $data .= str_repeat($paddingchar, $padding);
  return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB, str_repeat("\0", 16)));
}
 
function aes128Decrypt($key, $data) {
  if(16 !== strlen($key)) $key = hash('MD5', $key, true);
  $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB, str_repeat("\0", 16));
  $padding = ord($data[strlen($data) - 1]); 
  return substr($data, 0, -$padding); 
}
 
Upvote 0

Swissmade

Well-Known Member
Licensed User
Longtime User
Hi Guys,

Is there also a easy way to do this.
Try to protect my password in a MYSQL database with 512 bits encryption.
With all this story's I can not find what I have to use.
SHA2 AES MD5 :(:(

Any help will make me happy.
Thanks
 
Upvote 0

Swissmade

Well-Known Member
Licensed User
Longtime User
Last edited:
Upvote 0

Daniel-White

Active Member
Licensed User
Longtime User
Howdy.

This code is working PERFECT! thanks for share it. I am only show in this code the Decrypt AES

I would like to capture or handle when the cHashKey="12345" is different, I mean, when I put this code with a wrong cHashKey on purpose. That mean, if some one try to do something wrong (try to guess or use brute force), the APP must show a message. But really I don't know how to capture the error.

when I did the test, the line with this code. decrypted = C.Decrypt(decrypted, kg.Key, False) reproduce an error, obviously because the cHashKey is not the same ,it does not match. I would like to send a message to end user when the cHashkey does not match. and of course avoid the APP stop in that point.
I will very appreciate any light in the end of the tunnel :)



B4X:
Sub Process_Globals
    Type Message (Address As String, Body As String)
     Dim cHashKey As String
       cHashKey = "12345"

End Sub


Sub Activity_Create(FirstTime As Boolean)

YadescifradoAES=DecryptAES(mystringsAES)
    Log("Descifrado en AES= " & YadescifradoAES)
    ToastMessageShow("AES descifrado = "   &  YadescifradoAES,True)  

End Sub




Sub DecryptAES(dataToDecrypt As String) As String
    Dim su As StringUtils
    Dim kg As KeyGenerator
    Dim C As Cipher
    Dim md As MessageDigest
    Dim decrypted() As Byte
   Dim BConv As ByteConverter
 
   If cHashKey.Trim = "" Then Return False

    kg.Initialize("AES")
    kg.KeyFromBytes(md.GetMessageDigest(cHashKey.GetBytes("UTF8"), "MD5"))
    C.Initialize("AES/ECB/PKCS5Padding")
    decrypted = su.DecodeBase64(dataToDecrypt)
    decrypted = C.Decrypt(decrypted, kg.Key, False)
    Return BConv.StringFromBytes(decrypted, "UTF8")
End Sub


The message in Logs in B4A IDE

decrypted = C.Decrypt(decrypted, kg.Key, True)
java.lang.NullPointerException: iv == null
at javax.crypto.spec.IvParameterSpec.<init>(IvParameterSpec.java:45)
at anywheresoftware.b4a.agraham.encryption.CipherWrapper.doFinal(CipherWrapper.java:135)
at anywheresoftware.b4a.agraham.encryption.CipherWrapper.Decrypt(CipherWrapper.java:150)
at my.exampleSmsReply.testmodule._decryptaes(testmodule.java:205)
at my.exampleSmsReply.testmodule._parsesmsintent(testmodule.java:406)
at my.exampleSmsReply.testmodule._service_start(testmodule.java:541)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:187)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
at my.exampleSmsReply.testmodule.handleStart(testmodule.java:93)
at my.exampleSmsReply.testmodule.onStartCommand(testmodule.java:68)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2568)
at android.app.ActivityThread.access$2000(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1341)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4947)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
 
Upvote 0

Daniel-White

Active Member
Licensed User
Longtime User
Informatix, thanks you indeed. I did this and it is working fine, and I can tell to the end user the AES hashkey is wrong.

I leave the code here, to help other in the forums. :)

Thanks youuuuuuuuuuuuuuuuuuu.

Sub DecryptAES(dataToDecrypt As String) As String
Dim su As StringUtils
Dim kg As KeyGenerator
Dim C As Cipher
Dim md As MessageDigest
Dim decrypted() As Byte
Dim BConv As ByteConverter

If cHashKey.Trim = "" Then Return False
Try
kg.Initialize("AES")
kg.KeyFromBytes(md.GetMessageDigest(cHashKey.GetBytes("UTF8"), "MD5"))
C.Initialize("AES/ECB/PKCS5Padding")
decrypted = su.DecodeBase64(dataToDecrypt)
decrypted = C.Decrypt(decrypted, kg.Key, False)
Catch
Log(LastException)
ToastMessageShow ("HASHkey Wrong :) ",True)
Log("HashKey wrong :) ")
End Try


Return BConv.StringFromBytes(decrypted, "UTF8")
End Sub
 
Upvote 0
Top