A Basic Symmetrical Cryptography Tool From Scratch in JavaScript

Florian Maxim
8 min readFeb 9, 2020

The Objective

Our objective here is to write a very basic command line tool in Javascript for encrypting and decrypting messages using a (secret) key. We call our tool “secret” since we are dealing with information that we intent to hide and reveal.

If we want to encrypt the message “all the cats are grey” using the secret key “elephant” we simply want to type:

secret --encrypt -“all the cats are grey” -elephant

which should return the following encrypted message (ciphertext):

ewp ioe ptxd egl gexc

This encrypted message can be decrypted with the same keyword via:

secret --decrypt -“ewp ioe ptxd egl gexc” -elephant

which should gain return our decrypted message (plaintext):

all the cats are grey

So, let’s get started!

The Cipher

The method (or algorithm) that is being used for encrypting and decrypting a message is called a cipher. One of the classical categories of ciphers is called substitutional ciphers, which basically describes the method of substituting each letter of a message with another one. The easiest substitution would be to simply rearrange the alphabet used for the plaintext into a different one for the ciphertext .

/* (plaintext alphabet)
/* +-----------------------------------------------------+ */
/* | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | */
/* +-----------------------------------------------------+ */
/* | L G H T Z Y K V C M O F N B P J R X D Q A U W I S E | */
/* +-----------------------------------------------------+ */
/* (ciphertext alphabet) */

Using this ciphertext alphabet would turn our plaintext “all the cats are grey” into the ciphertext “lff qvz hlqd lxz kxzs”.

The Cipher

Instead of using a ciphertext alphabet technique we are using a keyword technique (called Vigenere cipher) that works as follows.

The Encryption

Below our message we keep repeating our keyword “elephant” until it matches the plaintext’s length:

/* (plaintext)
/* +-------------------------------------------+ */
/* | a l l t h e c a t s a r e g r e y | */
/* +-------------------------------------------+ */
/* | e l e p h a n t e l e p h a n t e | */
/* +-------------------------------------------+ */
/* (key word) */

In the next step we look up each letters index in the alphabet (a is 0, z is 25) of both the plain text and the key word.

/* (plaintext)
/* +---------------------------------------------------+ */
/* | a l l t h e c a t s a r e g r e y | */
/* +---------------------------------------------------+ */
/* | 0 11 11 19 7 4 2 0 19 18 0 17 4 6 17 4 24 | */
/* +---------------------------------------------------+ */
(alphabetic index) */
/* (keyword)
/* +---------------------------------------------------+ */
/* | e l e p h a n t e l e p h a n t e | */
/* +---------------------------------------------------+ */
/* | 4 11 4 15 7 0 13 19 4 11 4 15 7 0 13 19 4 | */
/* +---------------------------------------------------+ */
/* (alphabetic index) */

Then we add both indices:

/* (plaintext)
/* +------------------------------------------------------+ */
/* | 0 11 11 19 7 4 2 0 19 18 0 17 4 6 17 4 24 | */
/* +------------------------------------------------------+ */
+ + + + + + + + + + + + + + + + +
/* +------------------------------------------------------+ */
/* | 4 11 4 15 7 0 13 19 4 11 4 15 7 0 13 19 4 | */
/* +------------------------------------------------------+ */
/* (keyword) */
= = = = = = = = = = = = = = = = =
/* +------------------------------------------------------+ */
/* | 4 22 15 34 14 4 15 19 24 29 4 32 11 6 30 23 28 | */
/* +------------------------------------------------------+ */
/* (added indices) */

Finally we map the alphabet letters to the calculated indices.
If the index is greater than the alphabet’s length we simply take the difference (34-26=8), start from the beginning and end up at i (8th letter of the alphabet).

/* +------------------------------------------------------+ */
/* | 4 22 15 8 14 4 15 19 24 29 4 6 11 6 4 23 2 | */
/* +------------------------------------------------------+ *
/* +------------------------------------------------------+ */
/* | e w p i o e p t x d e g l g e x c | */
/* +------------------------------------------------------+ */

So our final ciphertext is: ewp ioe ptxd egl gexc.

Put into code it looks like this:

The Decryption

To decrypt our ciphertext we have to reverse the process. We repeat our keyword below the ciphertext:

/* +------------------------------------------------------+ */
/* | e w p i o e p t x d e g l g e x c | */
/* +------------------------------------------------------+ */
/* | e l e p h a n t e l e p h a n t e | */
/* +------------------------------------------------------+ */

We look up each character’s index:

/* (ciphertext)
/* +-----------------------------------------------------+ */
/* | e w p i o e p t x d e g l g e x c | */
/* +-----------------------------------------------------+ */
/* | 4 22 15 8 14 4 15 19 24 29 4 6 11 6 4 23 2 | */
/* +-----------------------------------------------------+ */
(alphabetic index) */
/* (keyword)
/* +---------------------------------------------------+ */
/* | e l e p h a n t e l e p h a n t e | */
/* +---------------------------------------------------+ */
/* | 4 11 4 15 7 0 13 19 4 11 4 15 7 0 13 19 4 | */
/* +---------------------------------------------------+ */
/* (alphabetic index) */

Then subtract them:

/* (plaintext)
/* +------------------------------------------------------+ */
/* | 4 22 15 8 14 4 15 19 24 29 4 6 11 6 4 23 2 | */
/* +------------------------------------------------------+ */
- - - + + + + + + + + + + + + +
/* +------------------------------------------------------+ */
/* | 4 11 4 15 7 0 13 19 4 11 4 15 7 0 13 19 4 | */
/* +------------------------------------------------------+ */
/* (keyword) */
= = = = = = = = = = = = = = = = =
/* +------------------------------------------------------+ */
/* | 0 11 11 -5 14 4 15 19 24 29 4 32 11 6 30 23 28 | */
/* +------------------------------------------------------+ */
/* (added indices) */

Now we add 26 to each index. If it’s greater than 26 we take the difference.

/* (plaintext)
/* +------------------------------------------------------+ */
/* | 4 22 15 8 14 4 15 19 24 29 4 6 11 6 4 23 2 | */
/* +------------------------------------------------------+ */
- - - - - - - -+ + + + + + + +
/* +------------------------------------------------------+ */
/* | 4 11 4 15 7 0 13 19 4 11 4 15 7 0 13 19 4 | */
/* +------------------------------------------------------+ */
/* -7 (keyword) */
+26
= = = = = = = = = = = = = = = = =
/* +------------------------------------------------------+ */
/* | 0 11 11 19 7 4 15 19 24 29 4 32 11 6 30 23 28 | */
/* +------------------------------------------------------+ */
/* (added indices) */

If the calculated index is negative it means we have to go from the end of the alphabet so we add 26 (-7 + 26 = 19). If we now map these indices to the alphabet…

/* +------------------------------------------------------+ */
/* | 0 11 11 19 7 4 15 19 24 29 4 6 11 6 4 23 2 | */
/* +------------------------------------------------------+ *
/* +------------------------------------------------------+ */
/* | a l l t h e p t x d e g l g e x c | */
/* +------------------------------------------------------+ */

… we get back our plaintext: all the cats are grey.

Put into code it looks like this:

The Command Line Tool

Since our objective was to write a command line tool we quickly need to learn how to build a CLI in Javascript with Node.js using it’s built-in package manager NPM.

First we initiate an empty NPM package via:

npm init

This will generate a package.json that looks similar to this:

{
"name": "golden-secret",
"version": "1.0.0",
"description": "Basic Hide & Reveal",
"main": "index.js",
"bin": {
"secret": "index.js"
},

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Florian Maxim",
"license": "ISC"
}

By adding a bin value with a key object { “secret”: “index.js” } we’re telling NPM that we want the command “secret” to be linked to index.js. So every time we run “secret” it will run whatever is in this file.

Once the index.js file was created we have to give it executable rights:

chmod +x index.js

Then we link the command we defined in the package.json:

npm link

The Parameters

On top of our index.js file we need to put the following line to define the Node.js environment .

#!/usr/bin/env node

(Learn more on that here: https://en.wikipedia.org/wiki/Shebang_(Unix))

So what information do we need? First we need to know if we should encrypt or decrypt a text (this is the MODE of our programm). Secondly we need the TEXT itself (either a plaintext to encrypt or a ciphertext to decrypt.). To make make our encryption or decryption work we always have to pass our KEY as a third parameter.
In Node.js parameters are stored in the process.argv object. Since the first two keys always include ‘node’ and the filename we start with the third argument ([2]).

Everything Put Together

Finally, we include our encrypt and our decrypt functions from above and call them according to the passed MODE argument (Short “E” or “encrypt” encrypts, “d” or decrypt does it the other way around.).

If you now type:

secret -E -"all the cats are grey" -"elephant"

you should get our ciphertext from before:

ewp ioe ptxd egl gexc

And vice versa:

secret -D -"ewp ioe ptxd egl gexc" -"elephant"

will print our original plaintext:

all the cats are grey

If you think all cats are gold leave a comment below as well if you liked or disliked this text in any way. I’m always happy to improve and hear your thoughts!

Code:

The full code can be found here:

https://github.com/florianmaxim/gold-secret

Alternatively it can be installed using NPM:

npm install golden-secret

Resources:

https://www.youtube.com/watch?v=ez0AOYl-i4k

https://en.wikipedia.org/wiki/Cipher
https://en.wikipedia.org/wiki/Substitution_cipher
https://en.wikipedia.org/wiki/Polyalphabetic_cipher

--

--