diff --git a/Ciphers/RSAAlgorithm.js b/Ciphers/RSAAlgorithm.js new file mode 100644 index 0000000000..347e2531a1 --- /dev/null +++ b/Ciphers/RSAAlgorithm.js @@ -0,0 +1,106 @@ +// RSAAlgorithm.js + +/** + * Generates the greatest common divisor of two numbers. + * @param {number} a - First number. + * @param {number} b - Second number. + * @returns {number} - The GCD of a and b. + */ +export function gcd(a, b) { + if (b === 0) { + return a + } + return gcd(b, a % b) +} + +/** + * Calculates modular inverse using Extended Euclidean Algorithm. + * @param {number} e - The number to find inverse for. + * @param {number} phi - The modulus. + * @returns {number} - The modular inverse of e mod phi. + */ +export function modInverse(e, phi) { + let [m0, x0, x1] = [phi, 0, 1] + + if (phi === 1) { + return 0 + } + + while (e > 1) { + let q = Math.floor(e / phi) + ;[e, phi] = [phi, e % phi] + ;[x0, x1] = [x1 - q * x0, x0] + } + + if (x1 < 0) { + x1 += m0 + } + + return x1 +} + +/** + * Performs modular exponentiation. + * @param {number} base - Base number. + * @param {number} exponent - Exponent. + * @param {number} modulus - Modulus. + * @returns {number} - (base^exponent) % modulus. + */ +export function modPow(base, exponent, modulus) { + if (modulus === 1) return 0 + let result = 1 + base = base % modulus + + while (exponent > 0) { + if (exponent % 2 === 1) { + result = (result * base) % modulus + } + exponent = Math.floor(exponent / 2) + base = (base * base) % modulus + } + + return result +} + +/** + * Generates RSA keys. + * @param {number} p - A prime number. + * @param {number} q - A prime number. + * @returns {{publicKey: {e: number, n: number}, privateKey: {d: number, n: number}}} + */ +export function generateKeys(p, q) { + const n = p * q + const phi = (p - 1) * (q - 1) + + let e = 2 + while (e < phi && gcd(e, phi) !== 1) { + e++ + } + + const d = modInverse(e, phi) + + return { + publicKey: { e, n }, + privateKey: { d, n } + } +} + +/** + * Encrypts a message with a public key. + * @param {number} message - The message to encrypt (as a number). + * @param {{e: number, n: number}} publicKey - The public key. + * @returns {number} - The encrypted message. + */ +export function encrypt(message, publicKey) { + return modPow(message, publicKey.e, publicKey.n) +} + +/** + * Decrypts a cipher with a private key. + * @param {number} cipher - The encrypted message (cipher). + * @param {{d: number, n: number}} privateKey - The private key. + * @returns {number} - The decrypted message. + */ +export function decrypt(cipher, privateKey) { + return modPow(cipher, privateKey.d, privateKey.n) +} diff --git a/Ciphers/test/RSAAlgorithm.test.js b/Ciphers/test/RSAAlgorithm.test.js new file mode 100644 index 0000000000..ac1d0e540f --- /dev/null +++ b/Ciphers/test/RSAAlgorithm.test.js @@ -0,0 +1,14 @@ +// RSAAlgorithm.test.js +import { describe, it, expect } from 'vitest' +import { generateKeys, encrypt, decrypt } from '../RSAAlgorithm.js' + +describe('RSA Algorithm', () => { + it('should encrypt and decrypt correctly', () => { + const { publicKey, privateKey } = generateKeys(61, 53) // two primes + const message = 65 + const cipher = encrypt(message, publicKey) + const decrypted = decrypt(cipher, privateKey) + + expect(decrypted).toBe(message) + }) +}) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy