forked from freeCodeCamp/CurriculumExpansion
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: RSA cryptosystem signature project (freeCodeCamp#184)
* feat: RSA cryptosystem signature project * fix: Large primes and message text - Fixes issue with large primes - Default message revised to fix minor typos - Revised success and failure messages * feat: Break into test decriptions (Part 1) * fix: Improved and added more test decriptions * fix: Revise and add test descriptions * fix: Revise and add more test descriptions * fix: Update and add more test descriptions * fix: Improve and add more descriptions - Added a diagram to explain the signing process - Revised all the test descriptions - Added some descriptions to illustrate hash collision To Do: Explain the internals of encryption and decryption equations
- Loading branch information
Showing
59 changed files
with
2,572 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<meta http-equiv="X-UA-Compatible" content="ie=edge" /> | ||
<title>RSA Digital Signature System</title> | ||
</head> | ||
<body> | ||
<script src="index.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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!"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. | ||
*/ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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`. | ||
*/ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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`. | ||
*/ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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`. | ||
*/ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()`. | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()`. | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()`. | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()`. | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
Oops, something went wrong.