From e979188a6672b62d05b9530ada9323f250722798 Mon Sep 17 00:00:00 2001 From: mmohamedkhaled <144614579+mmohamedkhaled@users.noreply.github.com> Date: Fri, 4 Apr 2025 03:51:19 +0200 Subject: [PATCH] Added Substitution Cipher, and its test --- Ciphers/SubstitutionCipher.js | 59 +++++++++++++++++++++++++ Ciphers/test/SubstitutionCipher.test.js | 31 +++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 Ciphers/SubstitutionCipher.js create mode 100644 Ciphers/test/SubstitutionCipher.test.js diff --git a/Ciphers/SubstitutionCipher.js b/Ciphers/SubstitutionCipher.js new file mode 100644 index 0000000000..2383a99796 --- /dev/null +++ b/Ciphers/SubstitutionCipher.js @@ -0,0 +1,59 @@ +/** + * Substitution Cipher + * + * A monoalphabetic substitution cipher replaces each letter of the plaintext + * with another letter based on a fixed permutation (key) of the alphabet. + * https://en.wikipedia.org/wiki/Substitution_cipher + */ + +const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +const defaultKey = 'QWERTYUIOPASDFGHJKLZXCVBNM' + +/** + * Encrypts a string using a monoalphabetic substitution cipher + * @param {string} text - The text to encrypt + * @param {string} key - The substitution key (must be 26 uppercase letters) + * @returns {string} + */ +export function substitutionCipherEncryption(text, key = defaultKey) { + if (key.length !== 26 || !/^[A-Z]+$/.test(key)) { + throw new RangeError('Key must be 26 uppercase English letters.') + } + + let result = '' + const textUpper = text.toUpperCase() + for (let i = 0; i < textUpper.length; i++) { + const char = textUpper[i] + const index = alphabet.indexOf(char) + if (index !== -1) { + result += key[index] + } else { + result += char + } + } + return result +} +/** + * Decrypts a string encrypted with the substitution cipher + * @param {string} text - The encrypted text + * @param {string} key - The substitution key used during encryption + * @returns {string} + */ +export function substitutionCipherDecryption(text, key = defaultKey) { + if (key.length !== 26 || !/^[A-Z]+$/.test(key)) { + throw new RangeError('Key must be 26 uppercase English letters.') + } + + let result = '' + const textUpper = text.toUpperCase() + for (let i = 0; i < textUpper.length; i++) { + const char = textUpper[i] + const index = key.indexOf(char) + if (index !== -1) { + result += alphabet[index] + } else { + result += char + } + } + return result +} diff --git a/Ciphers/test/SubstitutionCipher.test.js b/Ciphers/test/SubstitutionCipher.test.js new file mode 100644 index 0000000000..871ee40671 --- /dev/null +++ b/Ciphers/test/SubstitutionCipher.test.js @@ -0,0 +1,31 @@ +import { describe, it, expect } from 'vitest' +import { + substitutionCipherEncryption, + substitutionCipherDecryption +} from '../SubstitutionCipher.js' + + +describe('Substitution Cipher', () => { + const key = 'QWERTYUIOPASDFGHJKLZXCVBNM' + + it('correctly encrypts a message', () => { + const encrypted = substitutionCipherEncryption('HELLO WORLD', key) + expect(encrypted).toBe('ITSSG VGKSR') + }) + + it('correctly decrypts a message', () => { + const decrypted = substitutionCipherDecryption('ITSSG VGKSR', key) + expect(decrypted).toBe('HELLO WORLD') + }) + + it('handles non-alphabetic characters', () => { + const encrypted = substitutionCipherEncryption('Test! 123', key) + expect(encrypted).toBe('ZTLZ! 123') + }) + + it('throws error for invalid key', () => { + expect(() => substitutionCipherEncryption('HELLO', 'BADKEY')).toThrow( + RangeError + ) + }) +}) 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