This post was initially published for AppInventor classic, but currently sources are available also for AI2. However, I have not updated the comments and images because the code is roughly the same.
This post explains a simple method to encrypt/decrypt a text using exclusively the functions provided by App Inventor, i.e. without need to call a specialized library. One of the advantages of using only client code is that it does not require an Internet connection to work.
An encryption algorithm is a function that applies a certain transformation (encryption) to an input string in order to obtain an output string which can afterwards be transformed again (decrypted) in order to get back to the original string. Encryption algorithms are usually public, but (in theory) only the encrypter system is able to perform the decryption because the transformation algorithms use a secret key only known by the system.
The reason for building the solution explained in this tutorial is that I could not find one that met my requirements. As explained in this post from Google Groups, we can consider 3 ways to implement encryption in AI:
- Call a server side library using the StartActivity component. The AI Extensions mentioned in the same post seem to be an excellent choice for this purpose
- Program your own algorithm using AI code blocks. One solution for this is the Encryption and Decryption v3 from Abacus apps.
Next question is why not the solution mentioned in the third point. Well, there are three reasons for that. The first one (and to be honest the real reason) is that this solution was not posted when I needed it. The second reason why my solution might still be useful is that it’s so simple that it has immediate response time whereas it seems the mentioned solution can take up to 22 seconds as explained in this post. The final reason is that this site intends to provide some instructive material that helps intermediate readers improve their skills on AI and development in general, and I hope the post can be useful in this sense regardless of whether the results is used.
That being said, if you’re lloking for a more sophisticated solution developed in App Inventor you should refer to the solution mentioned in the third point which will probably have more support and evolution than my humble contribution.
What are we going to build
The method is inspired in standard encryption principles but with several workarounds to overcome the lack of some functions in App Inventor. Actually it is simpler to program than to explain, so maybe you’ll prefer to skip next section and go directly to the code or to the example below. Anyway for those interested I’ll try to explain the theory behind this code.
How it works
We’re going to implement a symmetric encryption algorithm, i.e. one that uses the same key to encrypt and decrypt. A usual means to achieve this is the XOR function because it has the property that XORing a data twice with the same key results in the same data. The XOR function receives two arguments (in our scenario the input string and the secret key) and obtains the output by comparing each bit from the two arguments and generating a 1 for different bits and 0 otherwise. For example, if the input string is “ac” and the key is “12” we would do the following:
So the output string would be “PQ”. Now we’ll apply the same algorithm to obtain the original string:
Unluckily App Inventor does not provide the XOR function (see related issue) nor bitwise manipulation functions that would allow simulating it. So we’ll use a substitute mechanism: create a string containing all the possible characters of the input string, and substitute each character by the opposed in this string, i.e. substitute the first character by the last one, the second by the last but one, etc. An example is simpler to understand: if the allowed characters are “aeiouAEIOU” and the input string is “aA” then the output string will be “Uu”. Notice that if we apply the same transformation to the string “Uu” we obtain again the original “aA” string. This way we have a reversible function like XOR, but with this alone our encryption would be very weak because anyone reading this tutorial (or with some imagination) would be able to decrypt it. That’s where the key comes into play. What we’ll do is “disorder” the allowed characters string by placing at the beginning the characters of the key. For example if the allowed characters are “aeiouAEIOU” and the key is “aEiO” we’ll generate the encrypter string “aEiOeouAIU”
I have no isolated sources for this tutorial because its implementation is embedded into a more general application (a “Login template” that uses encryption to store passwords). So if you need to implement this algorithm you can either type the code looking at the images below or download the whole sources of the login template. By the way, if you’re interested in the template you can have a look at the Login template tutorial.
I won’t show the graphical part of this functionality because it’s mixed with other controls so it would be difficult to show separately the specific components. Moreover, the interface has no secret: if you want to a make a quick test you just need to create a screen with two textboxes (for the input string and the key), a button (to perform the encryption) and a label (to show the results).
So let’s go with the code!
Before seeing the encryption and decryption functions, let’s have a look at the required initializations:
- ALPHANUMERIC_CHARS: A string composed by all the characters that can appear in the input string. You can add or remove characters if you wish to
- CRYPTO_KEY: Your specific key. You SHOULD change its value. You can use only characters contained in the ALPHANUMERIC_CHARS variable. The string can have any length, but it’s advisable for it to have at least 10 characters. You can repeat the same character several times in the key, but only the first one will be taken into account
- sEncrypterKey: contains the key string used by the encrypter and decrypter algorithms
- sVal, sRet_xor: auxiliary variables
- InitCrypto: This function informs the sEncrypterKey variable with the same characters as the ALPHANUMERIC_CHARS variable but disordered (i.e. the characters from CRYPTO_KEY are moved at the beginning). The code consists of a simple loop through the CRYPTO_KEY characters in order to move them at the beginning. Notice the “if” line which is used to ignore any repeated characters
- encrypt , decrypt: Yes, as easy as that! The output string is simply obtained by applying the pseudoXOR function to the input string
- pseudoXOR: The “reversing” function. It’s based on a loop that reads each character from the input string and locates its opposed character within the sEncrypterKey variable.
The algorithm explained in this tutorial is very basic. It would not be very hard for an expert to decipher the key if he was able to capture enough couples of encrypted-decrypted strings. If you want to sophisticate it but don’t wish to recur to the above-mentioned more complex solutions, you can extend the code in many ways. For example we could add a random number of characters at the beginning and at the end of the deciphered string in order to mislead hackers. In this case, for the decryption to work we should also include a couple of counters indicating where is the real string. This is better explained with an example:
|Input string: dog
Allowed characters: abcdefghijklmnopqrstuvwxyz
Previous characters: 1
Ending characters: 5
|1) Disorder the allowed characters string in order to obtain the encrypter string: samplebcdfghijknopqrtuvwxyz
2) Reverse the input string: qbp
3) Add random characters: wqbppoldw
4) Add two counters at the beginning: amwqbppoldw (see next point to understand it)
|1) Obtain the real string. “a” is the second character in the encrypter string and “m” is the third. This means the real string starts at position 2 and has a length of 3, i.e. it’s the string qbp
2) Reverse the string: dog
To implement this variation we should modify the encrypt and decrypt functions in the following way: