diff --git a/index51.js b/index51.js
new file mode 100644
index 00000000..8b52690c
Binary files /dev/null and b/index51.js differ
diff --git a/rsa-cryptosystem-signature/RSA signing process diagram.png b/rsa-cryptosystem-signature/RSA signing process diagram.png
new file mode 100644
index 00000000..e3b2fb62
Binary files /dev/null and b/rsa-cryptosystem-signature/RSA signing process diagram.png differ
diff --git a/rsa-cryptosystem-signature/index.html b/rsa-cryptosystem-signature/index.html
new file mode 100644
index 00000000..a791ded8
--- /dev/null
+++ b/rsa-cryptosystem-signature/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ RSA Digital Signature System
+
+
+
+
+
diff --git a/rsa-cryptosystem-signature/index.js b/rsa-cryptosystem-signature/index.js
new file mode 100644
index 00000000..920c1f0c
--- /dev/null
+++ b/rsa-cryptosystem-signature/index.js
@@ -0,0 +1,72 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+ sendAndVerify(generatedSignature, message);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ const hashValue = hashTheMessage(message);
+ const decryptedSignature = decryptSignature(digitalSignature);
+ if (hashValue === decryptedSignature) {
+ console.log("Success! Data is intact and signature is verified.");
+ } else {
+ console.log("Failure! There's something wrong with data or signature.");
+ }
+}
+
+sendMsgToBob("Hey Bob, I'm Alice here. Bob, Buy 300 shares of TSLA!");
diff --git a/rsa-cryptosystem-signature/index01.js b/rsa-cryptosystem-signature/index01.js
new file mode 100644
index 00000000..3e6643a4
--- /dev/null
+++ b/rsa-cryptosystem-signature/index01.js
@@ -0,0 +1,10 @@
+/*
+Cryptography is a mathematical art of protecting information from an unauthorized access.
+
+Digital signature is a way to verify the authenticity and integrity of documents and messages.
+
+First we hash our message, which is a method to transform a document into a fixed-size value.
+
+Create an empty function `hashTheMessage()` with `message` as a parameter.
+Functions which hash the data are called hash functions.
+*/
diff --git a/rsa-cryptosystem-signature/index02.js b/rsa-cryptosystem-signature/index02.js
new file mode 100644
index 00000000..6f6d65ce
--- /dev/null
+++ b/rsa-cryptosystem-signature/index02.js
@@ -0,0 +1,9 @@
+function hashTheMessage(message) {
+ /*
+ There are two types of hash functions -- cryptographic and non-cryptographic. Cryptographic hash functions are used for password management and non-cryptographic ones are used for database management.
+
+ The basics are same for both the types. The fixed-size value returned by a hash function is referred to as a hash value or hash.
+
+ Create a variable `hashValue` and set it to 0.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index03.js b/rsa-cryptosystem-signature/index03.js
new file mode 100644
index 00000000..4c7bd346
--- /dev/null
+++ b/rsa-cryptosystem-signature/index03.js
@@ -0,0 +1,10 @@
+function hashTheMessage(message) {
+ let hashValue = 0;
+ /*
+ A slight change in `message` should output a different hash value. This is called an avalanche effect.
+
+ So hash functions ideally use all of the data passed to it for hashing.
+
+ Create a `for` loop to iterate over all the characters of `message`.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index04.js b/rsa-cryptosystem-signature/index04.js
new file mode 100644
index 00000000..27c8c94e
--- /dev/null
+++ b/rsa-cryptosystem-signature/index04.js
@@ -0,0 +1,12 @@
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; i++) {
+ /*
+ Hash functions are one way functions, which means you can’t figure out the `message` if you only know the hash value.
+
+ We will represent our hash value as an integer.
+ Add the ASCII value of characters to `hashValue`.
+ Use `charCodeAt(index)` to find the ASCII value of each character in `message`.
+ */
+ }
+}
diff --git a/rsa-cryptosystem-signature/index05.js b/rsa-cryptosystem-signature/index05.js
new file mode 100644
index 00000000..b05ab025
--- /dev/null
+++ b/rsa-cryptosystem-signature/index05.js
@@ -0,0 +1,10 @@
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; i++) {
+ hashValue += message.charCodeAt(i);
+ }
+ /*
+ Hash functions are deterministic, which means they return the same hash value when the same message is passed.
+ Return `hashValue`.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index06.js b/rsa-cryptosystem-signature/index06.js
new file mode 100644
index 00000000..e9b7be9f
--- /dev/null
+++ b/rsa-cryptosystem-signature/index06.js
@@ -0,0 +1,17 @@
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; i++) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+/*
+In `ROT13` cipher, a modern version of the Caesar Cipher, the value of each letter is shifted by 13 places. So, 13 is called the key in `ROT13`.
+
+13 is a key that is used both for encryption and decryption. Thus, `ROT13` cipher is a type of symmetric key cryptography.
+
+In asymmetric key cryptography, each user has a public and a private key. The public key can be shared with anyone.
+
+Create an empty function `generatePublicKey()`.
+*/
diff --git a/rsa-cryptosystem-signature/index07.js b/rsa-cryptosystem-signature/index07.js
new file mode 100644
index 00000000..56065695
--- /dev/null
+++ b/rsa-cryptosystem-signature/index07.js
@@ -0,0 +1,15 @@
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; i++) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function generatePublicKey() {}
+
+/*
+However the private key must be kept secret.
+
+Create an empty function `generatePrivateKey()`.
+*/
diff --git a/rsa-cryptosystem-signature/index08.js b/rsa-cryptosystem-signature/index08.js
new file mode 100644
index 00000000..ace0ef4e
--- /dev/null
+++ b/rsa-cryptosystem-signature/index08.js
@@ -0,0 +1,19 @@
+/*
+If `publicKey` is used for encryption then only the matching `privateKey` can decrypt it.
+
+Keep in mind that the opposite is also true. Therefore, they are referred to as key pairs.
+
+Create a variable called `publicKey` and set it to 0.
+*/
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
diff --git a/rsa-cryptosystem-signature/index09.js b/rsa-cryptosystem-signature/index09.js
new file mode 100644
index 00000000..536f36d5
--- /dev/null
+++ b/rsa-cryptosystem-signature/index09.js
@@ -0,0 +1,21 @@
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+/*
+Suppose Alice sends an encrypted message to Bob using a symmetric key like the number 13 in `ROT13`. There's no way for Bob to verify that the sender is really Alice because anyone with access to that key can send Bob a message and claim to be Alice.
+
+A digital signature solves this problem. By encrypting the hash value of the message with her private key Alice creates a unique signature.
+
+Create an empty function called `generateSignature()`.
+*/
diff --git a/rsa-cryptosystem-signature/index10.js b/rsa-cryptosystem-signature/index10.js
new file mode 100644
index 00000000..3c3b5cd1
--- /dev/null
+++ b/rsa-cryptosystem-signature/index10.js
@@ -0,0 +1,27 @@
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+/*
+![Diagram of RSA digital signing process](RSA signing process diagram.png)
+
+Alice sends her unique signature along with the message to Bob.
+
+Bob then does two things -- first, he decrypts the signature using Alice's public key. Next, he uses Alice's hash function to generate a hash value of the received message.
+
+If the hash value of the received message and the decrypted signature match, then the data is intact and message is really from Alice.
+
+Create an empty function `decryptSignature()`.
+*/
diff --git a/rsa-cryptosystem-signature/index11.js b/rsa-cryptosystem-signature/index11.js
new file mode 100644
index 00000000..e922d2ed
--- /dev/null
+++ b/rsa-cryptosystem-signature/index11.js
@@ -0,0 +1,25 @@
+let publicKey = 0;
+
+/*
+We'll use the RSA asymmetric cryptographic algorithm to generate key pairs, to encrypt and decrypt data.
+
+RSA is based on the fact that finding prime factors of a large number is difficult.
+
+Create a constant named `firstPrime` and set it to 2.
+*/
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index12.js b/rsa-cryptosystem-signature/index12.js
new file mode 100644
index 00000000..7e62598b
--- /dev/null
+++ b/rsa-cryptosystem-signature/index12.js
@@ -0,0 +1,25 @@
+const firstPrime = 2;
+let publicKey = 0;
+
+/*
+Prime numbers are only divisible by 1 and by the number itself.
+The first few prime numbers are 2, 3, 5, 7, and 11.
+
+Create a constant `secondPrime` and set it to 5.
+*/
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index13.js b/rsa-cryptosystem-signature/index13.js
new file mode 100644
index 00000000..8c8cb17d
--- /dev/null
+++ b/rsa-cryptosystem-signature/index13.js
@@ -0,0 +1,29 @@
+const firstPrime = 2;
+const secondPrime = 5;
+let publicKey = 0;
+
+/*
+Create a constant `N` and set it as `firstPrime * secondPrime`.
+`N` will be used to generate both private and public keys.
+
+Here, `N = 10`. So, it's easy to find the prime factors: 2 and 5.
+But in real world usage `N` is around 600 digits long, which makes prime factorization almost impossible.
+
+Our implementation is insecure, and is just to teach you about the fundamentals of asymmetric cryptography.
+*/
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index14.js b/rsa-cryptosystem-signature/index14.js
new file mode 100644
index 00000000..3ea5f37c
--- /dev/null
+++ b/rsa-cryptosystem-signature/index14.js
@@ -0,0 +1,28 @@
+const firstPrime = 3;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+let publicKey = 0;
+
+/*
+Private key must be between 1 and `Φ(N)` or `1 < privateKey < Φ(N)`.
+
+`Φ(N)` pronounced as phi of N is called Euler's totient function. It outputs number of integers up to `N` that are coprime with `N`.
+
+Create a constant `phiOfN` and set it to 0.
+*/
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index15.js b/rsa-cryptosystem-signature/index15.js
new file mode 100644
index 00000000..2e0bba12
--- /dev/null
+++ b/rsa-cryptosystem-signature/index15.js
@@ -0,0 +1,30 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = 0;
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+/*
+Two integers are coprime if the only positive integer that divides both of them simultaneously is 1.
+
+For example, 10 can be divided evenly by 2 and 5. But 7 can't be divided evenly by 2 and 5.
+10 and 7 both are only divisible by 1. Hence, 10 and 7 are coprime.
+
+Create an empty function named `isCoPrime` with `smallerNum` and `largerNum` as parameters.
+*/
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index16.js b/rsa-cryptosystem-signature/index16.js
new file mode 100644
index 00000000..1a1e9818
--- /dev/null
+++ b/rsa-cryptosystem-signature/index16.js
@@ -0,0 +1,31 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = 0;
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ /*
+ To check if two integers are coprime, we start with 2 and check up to the smaller number.
+
+ For example, to check if 12 and 9 are coprime, start from 2 and check until 9 because any integer greater than 9 won't divide 9 evenly.
+
+ Create a `for` loop to iterate from 2 up to and including `smallerNum`.
+ */
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index17.js b/rsa-cryptosystem-signature/index17.js
new file mode 100644
index 00000000..002c380e
--- /dev/null
+++ b/rsa-cryptosystem-signature/index17.js
@@ -0,0 +1,30 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = 0;
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ /*
+ Use an `if` statement to check whether `smallerNum` and `largerNum` can be divided by `i` evenly.
+ If `i` divide both the numbers evenly then they aren't coprime.
+ */
+ }
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index18.js b/rsa-cryptosystem-signature/index18.js
new file mode 100644
index 00000000..29c6e08b
--- /dev/null
+++ b/rsa-cryptosystem-signature/index18.js
@@ -0,0 +1,34 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = 0;
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ /*
+ Going back to our example numbers 12 and 9, both can be divided by 3 evenly.
+ Thus, they are not coprime.
+
+ Return `false` if `i` divide both `smallerNum` and `largerNum` evenly.
+ */
+ }
+ }
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index19.js b/rsa-cryptosystem-signature/index19.js
new file mode 100644
index 00000000..7fa2d5cd
--- /dev/null
+++ b/rsa-cryptosystem-signature/index19.js
@@ -0,0 +1,32 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = 0;
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ /*
+ Return `true` if both the numbers are not divisible by any integer from 2 to `smallerNum`.
+ */
+}
+
+function generatePrivateKey() {}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index20.js b/rsa-cryptosystem-signature/index20.js
new file mode 100644
index 00000000..28583b7e
--- /dev/null
+++ b/rsa-cryptosystem-signature/index20.js
@@ -0,0 +1,36 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = 0;
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ /*
+ We know that the private key must follow the condition: 1 < privateKey < `Φ(N)`.
+
+ Create a `for` loop to iterate from 2 to `phiOfN - 1`.
+ */
+}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index21.js b/rsa-cryptosystem-signature/index21.js
new file mode 100644
index 00000000..2ab7038e
--- /dev/null
+++ b/rsa-cryptosystem-signature/index21.js
@@ -0,0 +1,44 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+
+/*
+`Φ(N)` or phi of `N` outputs number of integers up to `N` that are coprime with `N`.
+
+In our case, `N = 10`.
+So, let's find `Φ(10)`:
+Coprimes of 10 upto 10 are 1, 3, 7 and 9. There are 4 coprimes of 10 upto 10.
+So, `Φ(10)` = 4.
+
+Set `phiOfN` to 4.
+*/
+
+const phiOfN = 0;
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {}
+}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index22.js b/rsa-cryptosystem-signature/index22.js
new file mode 100644
index 00000000..1090fbfb
--- /dev/null
+++ b/rsa-cryptosystem-signature/index22.js
@@ -0,0 +1,40 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+
+/*
+The coprimes with 7 up to 7 are 1, 2, 3, 4, 5 and 6, or `Φ(7)` = 6.
+In general, `Φ(prime) = prime - 1`.
+
+Set `phiOfN` equal to `firstPrime - 1`.
+*/
+
+const phiOfN = 4;
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {}
+}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index23.js b/rsa-cryptosystem-signature/index23.js
new file mode 100644
index 00000000..aff656d3
--- /dev/null
+++ b/rsa-cryptosystem-signature/index23.js
@@ -0,0 +1,45 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+
+/*
+`Φ` function is multiplicative which means `Φ(A * B) = Φ(A) * Φ(B)`.
+
+We can say, `Φ(firstPrime * secondPrime) = Φ(firstPrime) * Φ(secondPrime)`.
+We know, `N = firstPrime * secondPrime`.
+So, `Φ(N) = Φ(firstPrime) * Φ(secondPrime)`.
+We also know, `Φ(firstPrime) = firstPrime - 1` and `Φ(secondPrime) = secondPrime - 1`.
+Substituting the above values we get `Φ(N) = (firstPrime - 1) * (secondPrime - 1)` 🎉.
+
+Set `phiOfN` to `(firstPrime - 1) * (secondPrime - 1)`.
+*/
+
+const phiOfN = firstPrime - 1;
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {}
+}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index24.js b/rsa-cryptosystem-signature/index24.js
new file mode 100644
index 00000000..94fdc4d2
--- /dev/null
+++ b/rsa-cryptosystem-signature/index24.js
@@ -0,0 +1,42 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ /*
+ Private keys have two constraints.
+ First, it must be greater than 1 and less than `Φ(N)`.
+ Second, it must be coprime with `N` and `Φ(N)`.
+
+ You already took care of the first constraint with the `for` loop.
+
+ Implement a conditional to check coprimality of `privateKey` with `N` and `phiOfN` using `isCoPrime` function.
+ */
+ }
+}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index25.js b/rsa-cryptosystem-signature/index25.js
new file mode 100644
index 00000000..18e46883
--- /dev/null
+++ b/rsa-cryptosystem-signature/index25.js
@@ -0,0 +1,38 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ /*
+ If `privateKey` is coprime with `N` and `phiOfN` then return `privateKey`.
+ */
+ }
+ }
+}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index26.js b/rsa-cryptosystem-signature/index26.js
new file mode 100644
index 00000000..6432976f
--- /dev/null
+++ b/rsa-cryptosystem-signature/index26.js
@@ -0,0 +1,39 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+ /*
+ If the possible values of `privateKey` are not coprime with `N` and `phiOfN`, then log an error message to the console.
+ */
+}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index27.js b/rsa-cryptosystem-signature/index27.js
new file mode 100644
index 00000000..b1b34e4f
--- /dev/null
+++ b/rsa-cryptosystem-signature/index27.js
@@ -0,0 +1,41 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ /*
+ Also, return 0 to indicate failure.
+ */
+}
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index28.js b/rsa-cryptosystem-signature/index28.js
new file mode 100644
index 00000000..1da07472
--- /dev/null
+++ b/rsa-cryptosystem-signature/index28.js
@@ -0,0 +1,45 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+/*
+Public key is mathematically related to a private key.
+
+Provide `privateKey` as a parameter to the `generatePublicKey()` function.
+*/
+
+function generatePublicKey() {}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index29.js b/rsa-cryptosystem-signature/index29.js
new file mode 100644
index 00000000..15139661
--- /dev/null
+++ b/rsa-cryptosystem-signature/index29.js
@@ -0,0 +1,45 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ /*
+ If we have successfully generated the private key then a corresponding public key must also exist.
+
+ Create a `while` loop that iterates when `privateKey` is valid i.e. when `privateKey > 0`.
+ */
+}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index30.js b/rsa-cryptosystem-signature/index30.js
new file mode 100644
index 00000000..b13234d6
--- /dev/null
+++ b/rsa-cryptosystem-signature/index30.js
@@ -0,0 +1,47 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ /*
+ The public key must fulfill the condition `(publicKey * privateKey) mod phiOfN = 1`.
+
+ Use an `if` statement to check for the condition mentioned above.
+ */
+ }
+}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index31.js b/rsa-cryptosystem-signature/index31.js
new file mode 100644
index 00000000..ac3f76b1
--- /dev/null
+++ b/rsa-cryptosystem-signature/index31.js
@@ -0,0 +1,51 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ /*
+ Public keys have two constraints.
+ First, `(publicKey * privateKey) mod phiOfN = 1`, but you already took care of this.
+ Second, it should not be the same as the private key.
+
+ Use the `&&` operator in the `if` statement to check for the second constraint.
+ */
+ if ((publicKey * privateKey) % phiOfN === 1) {
+ }
+ }
+}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index32.js b/rsa-cryptosystem-signature/index32.js
new file mode 100644
index 00000000..767c4e5e
--- /dev/null
+++ b/rsa-cryptosystem-signature/index32.js
@@ -0,0 +1,47 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ }
+ /*
+ Increment `publicKey` so we can test it on every iteration of the loop.
+ */
+ }
+}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index33.js b/rsa-cryptosystem-signature/index33.js
new file mode 100644
index 00000000..0694e48d
--- /dev/null
+++ b/rsa-cryptosystem-signature/index33.js
@@ -0,0 +1,48 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ /*
+ If both the conditions of the `if` statement are true then terminate the function using `return;` as we have found a mathematically related public key.
+ */
+ }
+ ++publicKey;
+ }
+}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index34.js b/rsa-cryptosystem-signature/index34.js
new file mode 100644
index 00000000..94f55fd2
--- /dev/null
+++ b/rsa-cryptosystem-signature/index34.js
@@ -0,0 +1,51 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+ /*
+ If `privateKey = 0`, then a private key couldn't successfully be generated so there can't be a valid public key.
+
+ Log an error message to the console when `privateKey = 0`.
+ */
+}
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index35.js b/rsa-cryptosystem-signature/index35.js
new file mode 100644
index 00000000..503a06d1
--- /dev/null
+++ b/rsa-cryptosystem-signature/index35.js
@@ -0,0 +1,55 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+/*
+Alice then encrypts the hash value of the data with her private key.
+The encrypted value is known as a signature.
+
+To generate a signature, pass `hashValue` and `privateKey` as parameters to the `generateSignature()` function.
+*/
+
+function generateSignature() {}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index36.js b/rsa-cryptosystem-signature/index36.js
new file mode 100644
index 00000000..4b3f43d3
--- /dev/null
+++ b/rsa-cryptosystem-signature/index36.js
@@ -0,0 +1,55 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ /*
+ To encrypt data using RSA, we use the equation: `encryptedData = (Data ^ privateKey) % N`.
+ We need to encrypt `hashValue`, so our `Data` is `hashValue`.
+
+ Return `(hashValue ^ privateKey) % N` using `Math.pow`.
+ */
+}
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index37.js b/rsa-cryptosystem-signature/index37.js
new file mode 100644
index 00000000..71bde16b
--- /dev/null
+++ b/rsa-cryptosystem-signature/index37.js
@@ -0,0 +1,59 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+/*
+Alice will attach her signature to the message and send it to Bob.
+Then Bob needs to decrypt the signature with Alice's public key.
+Since `publicKey` is a global variable, we have access to it everywhere.
+So our decryption function only needs access to the signature to decrypt it.
+
+Pass `digitalSignature` as a parameter to the `decryptSignature()` function.
+*/
+
+function decryptSignature() {}
diff --git a/rsa-cryptosystem-signature/index38.js b/rsa-cryptosystem-signature/index38.js
new file mode 100644
index 00000000..63daf23f
--- /dev/null
+++ b/rsa-cryptosystem-signature/index38.js
@@ -0,0 +1,59 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ /*
+ To decrypt data using RSA we use a equation similar to that of encryption:
+ `Data = (encryptedData ^ publicKey) % N`.
+
+ Here, the `encryptedData` is `digitalSignature`.
+
+ Return `(digitalSignature ^ publicKey) % N` using `Math.pow`.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index39.js b/rsa-cryptosystem-signature/index39.js
new file mode 100644
index 00000000..a7475f35
--- /dev/null
+++ b/rsa-cryptosystem-signature/index39.js
@@ -0,0 +1,58 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+/*
+Now Alice is ready to send her secret message to Bob!
+
+Create an empty function called `sendMsgToBob` with message as a parameter.
+*/
diff --git a/rsa-cryptosystem-signature/index40.js b/rsa-cryptosystem-signature/index40.js
new file mode 100644
index 00000000..55392fa6
--- /dev/null
+++ b/rsa-cryptosystem-signature/index40.js
@@ -0,0 +1,60 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ /*
+ Before Alice send her secret message, she needs to generate the key pair.
+
+ Create a constant called `privateKey` and set it equal to `generatePrivateKey()`.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index41.js b/rsa-cryptosystem-signature/index41.js
new file mode 100644
index 00000000..d205665e
--- /dev/null
+++ b/rsa-cryptosystem-signature/index41.js
@@ -0,0 +1,59 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ /*
+ Generate a public key by calling the `generatePublicKey()` function and pass it `privateKey` as an argument.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index42.js b/rsa-cryptosystem-signature/index42.js
new file mode 100644
index 00000000..86f49e8c
--- /dev/null
+++ b/rsa-cryptosystem-signature/index42.js
@@ -0,0 +1,62 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ /*
+ Call the `hashTheMessage()` function and pass it `message` as an argument.
+
+ Store the returned value as a constant named `hashValue`.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index43.js b/rsa-cryptosystem-signature/index43.js
new file mode 100644
index 00000000..8ae23a7d
--- /dev/null
+++ b/rsa-cryptosystem-signature/index43.js
@@ -0,0 +1,61 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ /*
+ Modify the return statement so that our hash function do not return values greater than or equal to `N` because RSA encryption and decryption work properly only when the hash value is less than `N`.
+ */
+ return hashValue;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+}
diff --git a/rsa-cryptosystem-signature/index44.js b/rsa-cryptosystem-signature/index44.js
new file mode 100644
index 00000000..b4626583
--- /dev/null
+++ b/rsa-cryptosystem-signature/index44.js
@@ -0,0 +1,64 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ /*
+ We now have a key pair and the right hash value.
+
+ Call the `generateSignature()` function and pass it `hashValue` and `privateKey` as arguments.
+ Store the returned value as a constant named `generatedSignature`.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index45.js b/rsa-cryptosystem-signature/index45.js
new file mode 100644
index 00000000..aafc442e
--- /dev/null
+++ b/rsa-cryptosystem-signature/index45.js
@@ -0,0 +1,66 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+}
+
+/*
+Alice encrypted the hash value of her message which generated her signature.
+Now, we can send the message along with signature to Bob.
+
+Create an empty function called `sendAndVerify` and provide the parameters `digitalSignature` and `message`.
+*/
diff --git a/rsa-cryptosystem-signature/index46.js b/rsa-cryptosystem-signature/index46.js
new file mode 100644
index 00000000..4cf9ac49
--- /dev/null
+++ b/rsa-cryptosystem-signature/index46.js
@@ -0,0 +1,68 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ /*
+ Bob receives the data and signature.
+ To verify the signature he first needs to hash the received message with the same hash function Alice used.
+
+ Hash the received message and store the returned value in a constant named `hashValue`.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index47.js b/rsa-cryptosystem-signature/index47.js
new file mode 100644
index 00000000..357f52b8
--- /dev/null
+++ b/rsa-cryptosystem-signature/index47.js
@@ -0,0 +1,71 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ const hashValue = hashTheMessage(message);
+ /*
+ Do you remember that Alice's signature was the encrypted hash value of message?
+
+ So when Bob decrypts the signature using Alice's public key, he should get the original hash value of the message.
+
+ Call the `decryptSignature()` function and pass it `digitalSignature` as an argument.
+ Store the returned value as a constant named `decryptedSignature`.
+*/
+}
diff --git a/rsa-cryptosystem-signature/index48.js b/rsa-cryptosystem-signature/index48.js
new file mode 100644
index 00000000..3f7307ed
--- /dev/null
+++ b/rsa-cryptosystem-signature/index48.js
@@ -0,0 +1,70 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ const hashValue = hashTheMessage(message);
+ const decryptedSignature = decryptSignature(digitalSignature);
+ /*
+ If the hash value of received message and decrypted signature are equal then the message is intact and it is really from Alice.
+
+ Check for the equality of `hashValue` and `decryptedSignature`.
+ If they are equal then log a success message to the console.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index49.js b/rsa-cryptosystem-signature/index49.js
new file mode 100644
index 00000000..99a0a20d
--- /dev/null
+++ b/rsa-cryptosystem-signature/index49.js
@@ -0,0 +1,74 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ const hashValue = hashTheMessage(message);
+ const decryptedSignature = decryptSignature(digitalSignature);
+ if (hashValue === decryptedSignature) {
+ console.log("Success! Data is intact and signature is verified.");
+ }
+ /*
+ There are two cases of failure.
+ First, when the original message is modified by a third party. The modified message will result in a different hash value than the original.
+ Second, when the signature is modified.
+
+ So log a failure message when the `hashValue` and `decryptedSignature` don't match.
+ */
+}
diff --git a/rsa-cryptosystem-signature/index50.js b/rsa-cryptosystem-signature/index50.js
new file mode 100644
index 00000000..6938c937
--- /dev/null
+++ b/rsa-cryptosystem-signature/index50.js
@@ -0,0 +1,72 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+ /*
+ Call `sendAndVerify()` function and provide the `generatedSignature` and `message` as an arguments.
+ */
+}
+
+function sendAndVerify(digitalSignature, message) {
+ const hashValue = hashTheMessage(message);
+ const decryptedSignature = decryptSignature(digitalSignature);
+ if (hashValue === decryptedSignature) {
+ console.log("Success! Data is intact and signature is verified.");
+ } else {
+ console.log("Failure! There's something wrong with data or signature.");
+ }
+}
diff --git a/rsa-cryptosystem-signature/index51.js b/rsa-cryptosystem-signature/index51.js
new file mode 100644
index 00000000..86b06c56
--- /dev/null
+++ b/rsa-cryptosystem-signature/index51.js
@@ -0,0 +1,76 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+ sendAndVerify(generatedSignature, message);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ const hashValue = hashTheMessage(message);
+ const decryptedSignature = decryptSignature(digitalSignature);
+ if (hashValue === decryptedSignature) {
+ console.log("Success! Data is intact and signature is verified.");
+ } else {
+ console.log("Failure! There's something wrong with data or signature.");
+ }
+}
+
+/*
+Call the `sendMsgToBob()` function and pass it a super secret message as a string.
+
+Observe the output of `console.log`.
+*/
diff --git a/rsa-cryptosystem-signature/index52.js b/rsa-cryptosystem-signature/index52.js
new file mode 100644
index 00000000..ce648aa6
--- /dev/null
+++ b/rsa-cryptosystem-signature/index52.js
@@ -0,0 +1,79 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+ sendAndVerify(generatedSignature, message);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ /*
+ If the `message` is modified by a third party, it'll produce a different hash value so we should get a failure message on the console.
+
+ Concatenate `message` with `Z` to modify it and then observe the output of `console.log`.
+ */
+
+ const hashValue = hashTheMessage(message);
+ const decryptedSignature = decryptSignature(digitalSignature);
+ if (hashValue === decryptedSignature) {
+ console.log("Success! Data is intact and signature is verified.");
+ } else {
+ console.log("Failure! There's something wrong with data or signature.");
+ }
+}
+
+/* Don't change code below this line */
+sendMsgToBob("Hey Bob, I'm Alice here. Bob, Buy 300 shares of TSLA!");
diff --git a/rsa-cryptosystem-signature/index53.js b/rsa-cryptosystem-signature/index53.js
new file mode 100644
index 00000000..8f9dbfc4
--- /dev/null
+++ b/rsa-cryptosystem-signature/index53.js
@@ -0,0 +1,79 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ /*
+ We are still getting the success message on console. There's something strange going on.
+
+ To debug what's wrong, print `hashValue` on console.
+ */
+ const generatedSignature = generateSignature(hashValue, privateKey);
+ sendAndVerify(generatedSignature, message);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ message = message + "Z";
+ const hashValue = hashTheMessage(message);
+ const decryptedSignature = decryptSignature(digitalSignature);
+ if (hashValue === decryptedSignature) {
+ console.log("Success! Data is intact and signature is verified.");
+ } else {
+ console.log("Failure! There's something wrong with data or signature.");
+ }
+}
+
+/* Don't change code below this line */
+sendMsgToBob("Hey Bob, I'm Alice here. Bob, Buy 300 shares of TSLA!");
diff --git a/rsa-cryptosystem-signature/index54.js b/rsa-cryptosystem-signature/index54.js
new file mode 100644
index 00000000..9c4f03e8
--- /dev/null
+++ b/rsa-cryptosystem-signature/index54.js
@@ -0,0 +1,82 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ console.log("Original hash value =", hashValue);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+ sendAndVerify(generatedSignature, message);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ message = message + "Z";
+ const hashValue = hashTheMessage(message);
+ /*
+ We are aware that modified message should produce a different hash value.
+
+ To see the new hash value, print `hashValue` on console.
+ Observe the outputs of `console.log`.
+ */
+
+ const decryptedSignature = decryptSignature(digitalSignature);
+ if (hashValue === decryptedSignature) {
+ console.log("Success! Data is intact and signature is verified.");
+ } else {
+ console.log("Failure! There's something wrong with data or signature.");
+ }
+}
+
+/* Don't change code below this line */
+sendMsgToBob("Hey Bob, I'm Alice here. Bob, Buy 300 shares of TSLA!");
diff --git a/rsa-cryptosystem-signature/index55.js b/rsa-cryptosystem-signature/index55.js
new file mode 100644
index 00000000..7053cba4
--- /dev/null
+++ b/rsa-cryptosystem-signature/index55.js
@@ -0,0 +1,86 @@
+const firstPrime = 2;
+const secondPrime = 5;
+const N = firstPrime * secondPrime;
+const phiOfN = (firstPrime - 1) * (secondPrime - 1);
+let publicKey = 0;
+
+function hashTheMessage(message) {
+ let hashValue = 0;
+ for (let i = 0, msgLength = message.length; i < msgLength; ++i) {
+ hashValue += message.charCodeAt(i);
+ }
+ return hashValue % N;
+}
+
+function isCoPrime(smallerNum, largerNum) {
+ for (let i = 2; i <= smallerNum; ++i) {
+ if (smallerNum % i === 0 && largerNum % i === 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function generatePrivateKey() {
+ for (let privateKey = 2; privateKey < phiOfN; ++privateKey) {
+ if (isCoPrime(privateKey, N) && isCoPrime(privateKey, phiOfN)) {
+ return privateKey;
+ }
+ }
+
+ console.log("Private key can't be generated.");
+ return 0;
+}
+
+function generatePublicKey(privateKey) {
+ while (privateKey) {
+ if ((publicKey * privateKey) % phiOfN === 1 && privateKey !== publicKey) {
+ return;
+ }
+ ++publicKey;
+ }
+
+ console.log("Public key can't be generated.");
+}
+
+function generateSignature(hashValue, privateKey) {
+ return Math.pow(hashValue, privateKey) % N;
+}
+
+function decryptSignature(digitalSignature) {
+ return Math.pow(digitalSignature, publicKey) % N;
+}
+
+function sendMsgToBob(message) {
+ const privateKey = generatePrivateKey();
+ generatePublicKey(privateKey);
+ const hashValue = hashTheMessage(message);
+ console.log("Original hash value =", hashValue);
+ const generatedSignature = generateSignature(hashValue, privateKey);
+ sendAndVerify(generatedSignature, message);
+}
+
+function sendAndVerify(digitalSignature, message) {
+ message = message + "Z";
+ const hashValue = hashTheMessage(message);
+ console.log("New hash value =", hashValue);
+ const decryptedSignature = decryptSignature(digitalSignature);
+ if (hashValue === decryptedSignature) {
+ console.log("Success! Data is intact and signature is verified.");
+ } else {
+ console.log("Failure! There's something wrong with data or signature.");
+ }
+}
+
+sendMsgToBob("Hey Bob, I'm Alice here. Bob, Buy 300 shares of TSLA!");
+
+/*
+`console.log` tells us that the original hash value and the new hash value are same!
+When two different messages or data result in the same hash value, we call it a hash collision.
+Good hash functions have negligible chance of collision.
+Our implementation is insecure and it was just to teach you the basics of hash functions.
+
+If you are working on a real app then you don't need to implement a hash function or RSA algorithm yourself. You should always use existing hash functions and cryptographic libraries like OpenSSL created by expert cryptographers.
+
+Happy coding <3 and stay secure!
+*/