Vanilla Javascript and PHP encryption / decryption

Walter A Rodriguez
5 min readOct 6, 2019

--

I’ve been looking for any simple option to encrypt and decrypt any string from PHP to Javascript (or the other way around). I’ve found some interesting stuff but not all of them are quite easy to implement if you have frameworks or an already complicated environment.

So I started my own functions. Which I think are available for all, mostly because it is simple Vanilla Javascript and pure PHP. You can even use this code in Angular 8.

Markus Spiske @markusspiske

Task: Create a public algorithm and use a password to create the actual encryption / decryption.

So I found this website. Very nice idea to start with…

So: Use the password to create a new alphabet. Then, get each letter you want to encrypt and use this new alphabet to change the original letter with the new one (in the correspondent position)

credit: trans4mind.com

On one side you know that the alphabet is: abcdefghijklmnopqrstuvwxyz plus numbers 01234567890 and uppercase letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ and any sign you may need, for example: =

That gives us a full laphabet: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=

You also know the password. Let’s say we use: password

So, let’s combine both to get a new alphabet for each letter from the word password. The alphabet for the letter p is: pqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=abcdefghijklmno

Why? Because we start the new alphabet from the letter p up to the end. And then we concat the letters from a to this p.

credit: trans4mind.com

Now that we know the basics, let’s jump into some Javascript code:

const text = ‘Hello World’;
const password = “pass”;

We will encrypt something simple Hello World using the password pass.

function encrypt(password, text) {

// move text to base64 so we avoid special chars
const base64 = btoa( text );

// text string to array
const arr = base64.split('');
// array of password
const arrPass = password.split('');
let lastPassLetter = 0;

// encrypted string
let encrypted = '';

// encrypt
for (let i=0; i < arr.length; i++) {

const letter = arr[ i ];

const passwordLetter = arrPass[ lastPassLetter ];

const temp = getLetterFromAlphabetForLetter(
passwordLetter, letter );

if (temp) {
// concat to the final response encrypted string
encrypted += temp;
} else {
// if any error, return null
return null;
}

/*
This is important: if we're out of letters in our
password, we need to start from the begining.
*/
if (lastPassLetter == (arrPass.length - 1) ) {
lastPassLetter = 0;
} else {
lastPassLetter ++;
}
}

// We finally return the encrypted string
return encrypted;
}

Now, the code for getLetterFromAlphabetForLetter(..) (yep, I know these names I invent are silly and long but it helps me to understand what functions are for)

function getLetterFromAlphabetForLetter(letter, letterToChange) { // this is the alphabet we know, plus numbers and the = sign 
const abc = 'abcdefghijklmnopqrstuvwxyz0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ';

// get the position of the given letter, according to our abc
const posLetter = abc.indexOf( letter );

// if we cannot get it, then we can't continue
if (posLetter == -1) {
console.log('Password letter ' + letter + ' not allowed.');
return null;
}
// according to our abc, get the position of the letter to encrypt
const posLetterToChange = abc.indexOf( letterToChange );

// again, if any error, we cannot continue...
if (posLetterToChange == -1) {
console.log('Password letter ' + letter + ' not allowed.');
return null;
}

// let's build the new abc. this is the important part
const part1 = abc.substring(posLetter, abc.length);
const part2 = abc.substring(0, posLetter);
const newABC = '' + part1 + '' + part2;

// we get the encrypted letter
const letterAccordingToAbc = newABC.split('')[ posLetterToChange ];

// and return to the routine...
return letterAccordingToAbc;
}

Please note that many optimisations can be done to the code above. But I do it like this, just to keep it simple for everyone to understand.

If we run this code with Hello World and password pass, we will get the following result:

encrypted: hGn=qGPyk2QFqGiR

To decrypt this, we just have to do the inverse. We can modify the above code or do some new functions. I will create separated functions so you can see the differences:

function decrypt(password, text) {

// convert the string to decrypt into an array
const arr = text.split('');

// let's also create an array from our password
const arrPass = password.split('');

// keep control about which letter from the password we use
let lastPassLetter = 0;

// this is the final decrypted string
let decrypted = '';

// let's start...
for (let i=0; i < arr.length; i++) {

// next letter from the string to decrypt
const letter = arr[ i ];

// get the next letter from the password
const passwordLetter = arrPass[ lastPassLetter ];
// get the decrypted letter according to the password
const temp = getInvertedLetterFromAlphabetForLetter(
passwordLetter, letter );
if (temp) {
// concat the response
decrypted += temp;
} else {
// if any error, return null
return null;
}

// if our password is too short,
// let's start again from the first letter
if (lastPassLetter == (arrPass.length - 1) ) {
lastPassLetter = 0;
} else {
lastPassLetter ++;
}
} // return the decrypted string and converted
// from base64 to plain text
return atob( decrypted );}

The getInvertedLetterFromAlphabetForLetter(…) is the inverse of what we did before. Let’s take a look:

function getInvertedLetterFromAlphabetForLetter(
letter, letterToChange) {

const abc = 'abcdefghijklmnopqrstuvwxyz0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const posLetter = abc.indexOf( letter );

if (posLetter == -1) {
console.log('Password letter ' + letter + ' not allowed.');
return null;
}
const part1 = abc.substring(posLetter, abc.length);
const part2 = abc.substring(0, posLetter);

const newABC = '' + part1 + '' + part2;

const posLetterToChange = newABC.indexOf( letterToChange );

if (posLetterToChange == -1) {
console.log('Password letter ' + letter + ' not allowed.');
return null;
}

const letterAccordingToAbc = abc.split('')[ posLetterToChange ];

return letterAccordingToAbc;
}

If you invoke this routine with the encrypted string and the correct password, you will get:

encrypted: hGn=qGPyk2QFqGiR
decrypted: Hello World

Try changing the password and you will get an incorrect response.

Yes, if you instead of using pass use passsss, some of the words will be decrypted. But the whole idea is to use random characters and a very long password for this kind of encryptions.

You can access the full code here, in my Github repository.

--

--