So here's a small example. It works in B4J and B4A.
Libraries used:
View attachment 114466
Notes:
- the goal is to send/receive a simple string in the end using the POSTSTRING method
- using strings is very easy but comes unhandy when you need structured data
- here we use maps (could be a list with maps) which are converted to JSON strings and back
- PHP can handle lists/maps very easy. Here these types are just associative arrays (key -> value)
- I've added some subs to convert "all" types to strings
- like any encryption, AES uses bytes to en-/decrypt
- getting bytes from strings is easy, too by using StringName.GetBytes("UTF8")
- AES256 uses a fixes length password of 32 bytes (= 256 bits), AES128 would use 16 (= 128 bits)
- the IV is randomized with every message (= some sort of changing the sort order of the data = same data will look different every time)
- a "salt" is added, too (here: 32 bytes. Can be longer) to randomize it more
- an encrypted message is always a multiple of 16 bytes long (AES = blockcypher). So "hello" will be padded to 16 bytes.
- the message structure is: salt + iv + message
- salt and iv are "public"
- on the PHP side we use OpenSSL
- the methods need a Base64 encoded string (= encrypted bytes) as an input or output
Workflow:
- get the bytes of the string which you want to encrypt (or use a byte array directly if you want to encrypt just bytes)
- hash the password to 32 bytes (see the sub) or use random 32 bytes (which can be converted to a Base64 string to handle it better)
- call the encryption sub
- Salt and IV are added automatically
- Send the data (here a map) to the receiver (here PHP, can be any other platform, too)
- the receiver has to know the SAME password and the position/length of salt and iv
- salt and iv are removed from the message
- the message can now be decrypted
- on some platforms you need to pad the message on your own (e.g. ESP32). Search for my padding example
Pro/paranoia tips:
- add another salt before encryption (e.g. 64 bytes)
- mix the data bytes with the salt (odd/even)
- as both sides need the same password, use RSA to exchange a different aes password for every client/instance/session (SSL does quite the same)
- encrypt it twice with different passwords
PHP (put it in your htdocs folder)
<?php
$aespw=hash('sha256','#$%&12890GHbfewiwegbweoegn',true); //hash string pw to 32 bytes (=256 bits) as bytes (true=binary=bytes)
$jsonstring = file_get_contents("php://input"); //get the string or whatever you send via poststring
$mymap = array(); //define an array (which is the map we send from B4x)
$mymap=json_decode($jsonstring, true); //the JSONencoded map from B4x is decoded to an associative array which is quite the same in php
$Action=$mymap['Action']; //get the value from the map by the key (like a map) so we get the method (ecnrypt or decrypt)
switch ($Action) //Select case... in B4x
{
Case "AES256":
$decrypted=AES256_decrypt($mymap['b4xencrypted'],$aespw);//decrypt the message sent from B4x
$encrypted=AES256_encrypt('This message was encrypted in PHP',$aespw );//encrypt a new message in PHP (to send it back)
//we send back the decrypted message (cleartext) and a new message encrypted via php
//of course we would never send back cleatext (just to proof the decryption)
$res=json_encode(array('AESDecrypt' => 'ok','b4xdecrypted' => $decrypted,'phpencrypted' => $encrypted)); //this is an associative array or a map
exit($res);
break;
default:
print json_encode ("Error: Function not defined (" . $action . ")");
}
function AES256_Encrypt($string, $pw)
{
$encrypt_method = "AES-256-CBC";
$IV=openssl_random_pseudo_bytes(16, $securityok);//generate a radom IV
$Salt=openssl_random_pseudo_bytes(32, $securityok);//generate a random salt
$enc = openssl_encrypt($string, $encrypt_method, $pw, 0,$IV);//encrypt with the given IV
$enc=Base64_encode($Salt.$IV.Base64_decode($enc));//add salt, iv and the message to a Base64 string (OPENSSL encrypt returns a Base64 string so we have to decode it first)
return $enc;
}
function AES256_Decrypt($string, $pw)
{
$dec = false;
$encrypt_method = "AES-256-CBC";
$total=base64_decode($string); //salt + iv + message
$salt=substr($total, 0, 32);//extract the salt
$iv=substr($total, 32, 16);//ectract iv
$string=Base64_Encode(substr($total, 48, strlen($total)-48));//extract the message. Must be Base64 encoded for OpenSSL decrypt
$dec = openssl_decrypt($string, $encrypt_method, $pw, 0,$iv);//decrypt...
return $dec;
}
?>