php openssl compatible
can this lib be used in conjunction with phps openssl_encrypt() ?
heres example code i tried but didn't work. php.net
switched to aes-256_ecb so IV woudn't be an issue but still didn't work, does the block size need to be padded?
Hi @csxdotcc 👋
I'm unfamiliar with PHP but have gotten the following results.
ECB mode
I used an interactive shell to go through encryption/decryption using AES-128 in ECB mode:
php > $plaintext = "message to be encrypted";
php > $cipher = "aes-128-ecb";
php > $key = openssl_random_pseudo_bytes(openssl_cipher_key_length($cipher));
php > $ciphertext = openssl_encrypt($plaintext, $cipher, $key);
php > print_r($ciphertext);
mRkSDTbqkdLT9Rf2aS6hAIJ1kXXTQ3I0LzX9J14jIP8=
php > $decrypted_ciphertext = openssl_decrypt($ciphertext, $cipher, $key);
php > print_r($decrypted_ciphertext);
message to be encrypted
I got the 16 bytes that make up the key with
php > print_r(implode(", ", unpack("C*", $key)));
254, 14, 140, 121, 110, 130, 46, 134, 30, 88, 114, 215, 217, 119, 56, 164
which I then used on the MicroPython side:
>>> import binascii, mpyaes
>>> key = bytearray([254, 14, 140, 121, 110, 130, 46, 134, 30, 88, 114, 215, 217, 119, 56, 164])
>>> plaintext = "message to be encrypted".encode("utf8")
>>> aes = mpyaes.new(key, mpyaes.MODE_ECB)
>>> aes
<AES 128-bit ECB>
>>> ciphertext = aes.encrypt(plaintext)
>>> ciphertext
bytearray(b"\x99\x19\x12\r6\xea\x91\xd2\xd3\xf5\x17\xf6i.\xa1\x00\x82u\x91u\xd3Cr4/5\xfd'^# \xff")
>>> binascii.b2a_base64(ciphertext, newline=False) # NEWLINE BY DEFAULT!
b'mRkSDTbqkdLT9Rf2aS6hAIJ1kXXTQ3I0LzX9J14jIP8='
>>> decrypted_ciphertext = aes.decrypt(ciphertext)
>>> decrypted_ciphertext
bytearray(b'message to be encrypted')
PHP's openssl_encrypt returns the base64-encoded ciphertext by default, whereas mpyaes returns the raw bytes. If you choose to make use of binascii on the MicroPython side to handle base64 conversions, take care of binascii.b2a_base64, which appends a newline to the base64 string by default. Otherwise you can obtain the raw bytes by passing the OPENSSL_RAW_DATA option when encrypting (and decrypting!), e.g.
php > $ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA);
php > print_r($ciphertext);
6?????i.??u?u?Cr4/5?'^# ?
php > print_r(implode(", ", unpack("C*", $ciphertext)));
153, 25, 18, 13, 54, 234, 145, 210, 211, 245, 23, 246, 105, 46, 161, 0, 130, 117, 145, 117, 211, 67, 114, 52, 47, 53, 253, 39, 94, 35, 32, 255
and on the MicroPython side
>>> list(ciphertext)
[153, 25, 18, 13, 54, 234, 145, 210, 211, 245, 23, 246, 105, 46, 161, 0, 130, 117, 145, 117, 211, 67, 114, 52, 47, 53, 253, 39, 94, 35, 32, 255]
CBC mode
I looked at AES-128 in CBC mode to see how IVs fair. On the PHP side:
php > $cipher = "aes-128-cbc";
php > $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
php > $ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
php > print_r(implode(", ", unpack("C*", $ciphertext)));
30, 107, 132, 168, 161, 158, 77, 152, 168, 73, 39, 156, 38, 3, 180, 192, 216, 99, 197, 44, 116, 125, 156, 4, 252, 216, 140, 65, 212, 5, 241, 16
php > $decrypted_ciphertext = openssl_decrypt($ciphertext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
php > echo $decrypted_ciphertext;
message to be encrypted
The 16 bytes making up the IV:
php > print_r(implode(", ", unpack("C*", $iv)));
14, 29, 232, 142, 145, 57, 46, 97, 15, 248, 74, 117, 226, 38, 207, 230
The MicroPython side:
>>> iv = bytearray([14, 29, 232, 142, 145, 57, 46, 97, 15, 248, 74, 117, 226, 38, 207, 230])
>>> aes = mpyaes.new(key, mpyaes.MODE_CBC, IV=iv)
>>> aes
<AES 128-bit CBC>
>>> ciphertext = aes.encrypt(plaintext)
>>> list(ciphertext)
[30, 107, 132, 168, 161, 158, 77, 152, 168, 73, 39, 156, 38, 3, 180, 192, 216, 99, 197, 44, 116, 125, 156, 4, 252, 216, 140, 65, 212, 5, 241, 16]
>>> decrypted_ciphertext = aes.decrypt(ciphertext)
>>> decrypted_ciphertext
bytearray(b'message to be encrypted')
Without exhausting AES cipher parameter combinations, to my understanding mpyaes seems compatible with PHP's OpenSSL extension. What was it you tried that didn't work?