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..820d0303d6
--- /dev/null
+++ b/Ciphers/test/SubstitutionCipher.test.js
@@ -0,0 +1,44 @@
+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
+    )
+  })
+  it('encrypts using default key if none provided', () => {
+    const encrypted = substitutionCipherEncryption('HELLO WORLD')
+    expect(encrypted).toBe('ITSSG VGKSR')
+  })
+  
+  it('decrypts using default key if none provided', () => {
+    const decrypted = substitutionCipherDecryption('ITSSG VGKSR')
+    expect(decrypted).toBe('HELLO WORLD')
+  })
+  
+  it('throws error for invalid key in decryption', () => {
+    expect(() => substitutionCipherDecryption('HELLO', 'BADKEY')).toThrow(RangeError)
+  })
+  
+})
diff --git a/Maths/MobiusFunction.js b/Maths/MobiusFunction.js
index bd268b8bbd..4239d6ab31 100644
--- a/Maths/MobiusFunction.js
+++ b/Maths/MobiusFunction.js
@@ -28,6 +28,6 @@ export const mobiusFunction = (number) => {
   return primeFactorsArray.length !== new Set(primeFactorsArray).size
     ? 0
     : primeFactorsArray.length % 2 === 0
-    ? 1
-    : -1
+      ? 1
+      : -1
 }