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! +*/