• Godot HelpProgramming
  • how to convert a string from a Pool Byte Array.hex encode() to a readable poolBytearray.

I'm trying to encrypt some data to send via JavaScript.eval() method and so I need a readable string so I can encrypt and send my data and receive it and get decrypted, I'm using this encryption script https://github.com/beamer159/AES-in-GDScript however the return of this method is a poolByteArray and I need to convert it into a string and convert it again when receiving javaScript I can in poolByteArray that is readable for the decryption method![]

in the print it shows one of the attempts I made, thanks for your attention and any help that may come.

Why are you using hex_encode()? If you want to make a string from utf8 byte data you should use get_string_from_utf8()

hex encode was my last attempt, I tried it with get string from utf8 and also with get_string_from_ascii , both didn't work but if you have an example I'll be very grateful.

@cybereality said: What exactly wasn't working with UTF8?

basically it returns this error I'm not sure if I'm using the correct method I haven't found many examples of how to use it correctly, and in the case of get_string_from_ascii() it returns a string, however when I transform the string to poolByteArray it becomes unreadable.

You can do everything with ASCII, seems to work for me:

extends Node2D

onready var aes = get_node("AES")
var copy = "The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well."

func _ready():
	randomize()
	var key = aes.rand_bytes(32)
	var cipher_text = aes.encrypt(copy, key)
	print(cipher_text.get_string_from_ascii())
	var plain_text = aes.decrypt(cipher_text, key)
	print(plain_text.get_string_from_ascii())
 P[i5HYCps/^n	m=wQ)EEVJwn\,OK8=v G}A:E@(~[+T{%;(M52y(A}x
The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well.

Actually, wait, I see what the problem is. Give me a second.

Yeah, so the issue is that the AES script expects certain size of the input file. You can convert a string to a pool like this:

var encrypted = aes.encrypt(copy, key)
var cipher_text = encrypted.get_string_from_ascii()
print(cipher_text)
var cipher_array = cipher_text.to_utf8()
print(cipher_array)

However, because the AES doesn't like being converted to UTF8 (I had to use ASCII here) then the conversion is messed up and it won't decrypt. There is also something off with the padding, as the AES script expects 16 byte and when you convert manually that is not guaranteed. The strange part is that the AES script does appear to allow sending strings as input (not pools) but you need to ensure that the plain text is multiple of 16 bytes.

@cybereality said: Yeah, so the issue is that the AES script expects certain size of the input file. You can convert a string to a pool like this:

var encrypted = aes.encrypt(copy, key)
var cipher_text = encrypted.get_string_from_ascii()
print(cipher_text)
var cipher_array = cipher_text.to_utf8()
print(cipher_array)

However, because the AES doesn't like being converted to UTF8 (I had to use ASCII here) then the conversion is messed up and it won't decrypt. There is also something off with the padding, as the AES script expects 16 byte and when you convert manually that is not guaranteed. The strange part is that the AES script does appear to allow sending strings as input (not pools) but you need to ensure that the plain text is multiple of 16 bytes.

thanks for answering one more time but i still have a doubt i tried using cipher_array to decrypt and it didn't work what should i do so that poolbytearray when transformed by cipher_text.to_utf8() is readable by aes.decrypt()

Actually, I found that Godot 3.4 has built-in support for AES now. However, I still ran into the same problem with the UTF8. But I found a work around to convert to UTF8 to BASE64 and it seems to work. This example shows two encryption decryption methods. You only need to choose one method.

extends Node2D

onready var aes = AESContext.new()
var data = "The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well."

func _ready():
	var key = "My secret key!!!" 
	# Key must be either 16 or 32 bytes.
	# Data size must be multiple of 16 bytes, apply padding if needed.
	data = Marshalls.utf8_to_base64(data)
	while data.length() % 16 != 0:
		data += " "
	# Encrypt ECB
	aes.start(AESContext.MODE_ECB_ENCRYPT, key.to_utf8())
	var encrypted = aes.update(data.to_utf8())
	aes.finish()
	
	var cipher_text = encrypted.get_string_from_ascii()
	print("encrypted = ", cipher_text)
	
	# Decrypt ECB
	aes.start(AESContext.MODE_ECB_DECRYPT, key.to_utf8())
	var decrypted = aes.update(cipher_text.to_ascii())
	aes.finish()
	# Check ECB
	assert(decrypted == data.to_utf8())
	
	print("decrypted = ", Marshalls.base64_to_utf8(decrypted.get_string_from_utf8()))

	var iv = "My secret iv!!!!" # IV must be of exactly 16 bytes.
	# Encrypt CBC
	aes.start(AESContext.MODE_CBC_ENCRYPT, key.to_utf8(), iv.to_utf8())
	encrypted = aes.update(data.to_utf8())
	aes.finish()
	
	cipher_text = encrypted.get_string_from_ascii()
	print("encrypted = ", cipher_text)
	
	# Decrypt CBC
	aes.start(AESContext.MODE_CBC_DECRYPT, key.to_utf8(), iv.to_utf8())
	decrypted = aes.update(cipher_text.to_ascii())
	aes.finish()
	# Check CBC
	assert(decrypted == data.to_utf8())
	
	print("decrypted = ", Marshalls.base64_to_utf8(decrypted.get_string_from_utf8()))

thank you very much for all the help, i ended up with some difficulties with the generated string because i couldn't send it through the javaScript.eval() method, but thanks for the help i'll end up using it in another case that i need here too

Maybe converting to Base64 before sending to Javascript would help?

a month later

@cybereality said: Maybe converting to Base64 before sending to Javascript would help?

I know it's been a while since this post was made, but to put an end to it, actually after the whole process I just had to apply a base64 as you said, I intend to make it available in a few days as soon as I have some time. it on gitHub (probably at this link https://github.com/gilmarkandrade/test_encrypt_dict) to help those who have the same difficulty I had. thanks again for the help.

a year later