Skip to content

Commit 9b8f681

Browse files
the alphabet cipher (#11)
1 parent 02a278f commit 9b8f681

File tree

9 files changed

+186
-0
lines changed

9 files changed

+186
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,7 @@ console.log(ceaser.encrypt("hello world"))
2424
- Atbash Cipher
2525
- Playfair Cipher
2626
- Vigenere Cipher
27+
- The Alphabet Cipher
28+
- & more coming soon ...
2729

2830
#### Thanks for visiting (>'-'<)

dist/Cipher.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import { Caesar } from "./ciphers/Caesar.js"
22
import { Atbash } from "./ciphers/Atbash.js"
33
import { Playfair } from "./ciphers/Playfair.js"
44
import { Vigenere } from "./ciphers/Vigenere.js"
5+
import { Alphabet } from "./ciphers/Alphabet.js"
56
export declare abstract class Cipher {
67
static Caesar: typeof Caesar
78
static Atbash: typeof Atbash
89
static Playfair: typeof Playfair
910
static Vigenere: typeof Vigenere
11+
static Alphabet: typeof Alphabet
1012
abstract encrypt(text: string): string
1113
abstract decrypt(text: string): string
1214
}

dist/ciphers/Alphabet.d.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Cipher } from "../Cipher.js"
2+
export declare class Alphabet extends Cipher {
3+
private keyword
4+
private static alphabet
5+
constructor(keyword: string)
6+
/**
7+
* Encrypts a message using the Alphabet Cipher.
8+
* @param message - The plaintext message to encrypt.
9+
* @returns The encrypted ciphertext.
10+
*/
11+
encrypt(message: string): string
12+
/**
13+
* Decrypts a message using the Alphabet Cipher.
14+
* @param ciphertext - The encrypted message to decrypt.
15+
* @returns The original plaintext message.
16+
*/
17+
decrypt(ciphertext: string): string
18+
/**
19+
* Generates the Vigenère table for encoding and decoding.
20+
*/
21+
private static getVigenereTable
22+
}

dist/ciphers/Alphabet.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { Cipher } from "../Cipher.js"
2+
export class Alphabet extends Cipher {
3+
constructor(keyword) {
4+
super()
5+
this.keyword = keyword.toLowerCase()
6+
}
7+
/**
8+
* Encrypts a message using the Alphabet Cipher.
9+
* @param message - The plaintext message to encrypt.
10+
* @returns The encrypted ciphertext.
11+
*/
12+
encrypt(message) {
13+
message = message.toLowerCase()
14+
const table = Alphabet.getVigenereTable()
15+
let result = ""
16+
for (let i = 0; i < message.length; i++) {
17+
const msgChar = message[i]
18+
const keyChar = this.keyword[i % this.keyword.length]
19+
if (!Alphabet.alphabet.includes(msgChar)) {
20+
result += msgChar // Preserve non-alphabet characters
21+
continue
22+
}
23+
const row = Alphabet.alphabet.indexOf(keyChar)
24+
const col = Alphabet.alphabet.indexOf(msgChar)
25+
result += table[row][col]
26+
}
27+
return result
28+
}
29+
/**
30+
* Decrypts a message using the Alphabet Cipher.
31+
* @param ciphertext - The encrypted message to decrypt.
32+
* @returns The original plaintext message.
33+
*/
34+
decrypt(ciphertext) {
35+
ciphertext = ciphertext.toLowerCase()
36+
const table = Alphabet.getVigenereTable()
37+
let result = ""
38+
for (let i = 0; i < ciphertext.length; i++) {
39+
const cipherChar = ciphertext[i]
40+
const keyChar = this.keyword[i % this.keyword.length]
41+
if (!Alphabet.alphabet.includes(cipherChar)) {
42+
result += cipherChar // Preserve non-alphabet characters
43+
continue
44+
}
45+
const row = Alphabet.alphabet.indexOf(keyChar)
46+
const col = table[row].indexOf(cipherChar)
47+
result += Alphabet.alphabet[col]
48+
}
49+
return result
50+
}
51+
/**
52+
* Generates the Vigenère table for encoding and decoding.
53+
*/
54+
static getVigenereTable() {
55+
const table = []
56+
for (let i = 0; i < 26; i++) {
57+
table[i] = Alphabet.alphabet
58+
.slice(i)
59+
.split("")
60+
.concat(Alphabet.alphabet.slice(0, i).split(""))
61+
}
62+
return table
63+
}
64+
}
65+
Alphabet.alphabet = "abcdefghijklmnopqrstuvwxyz"

dist/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import { Caesar } from "./ciphers/Caesar.js"
33
import { Atbash } from "./ciphers/Atbash.js"
44
import { Playfair } from "./ciphers/Playfair.js"
55
import { Vigenere } from "./ciphers/Vigenere.js"
6+
import { Alphabet } from "./ciphers/Alphabet.js"
67
Cipher.Caesar = Caesar
78
Cipher.Atbash = Atbash
89
Cipher.Playfair = Playfair
910
Cipher.Vigenere = Vigenere
11+
Cipher.Alphabet = Alphabet
1012
export { Cipher }

src/Cipher.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import { Caesar } from "./ciphers/Caesar.js"
22
import { Atbash } from "./ciphers/Atbash.js"
33
import { Playfair } from "./ciphers/Playfair.js"
44
import { Vigenere } from "./ciphers/Vigenere.js"
5+
import { Alphabet } from "./ciphers/Alphabet.js"
56

67
export abstract class Cipher {
78
static Caesar: typeof Caesar
89
static Atbash: typeof Atbash
910
static Playfair: typeof Playfair
1011
static Vigenere: typeof Vigenere
12+
static Alphabet: typeof Alphabet
1113

1214
abstract encrypt(text: string): string
1315
abstract decrypt(text: string): string

src/ciphers/Alphabet.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { Cipher } from "../Cipher.js"
2+
3+
export class Alphabet extends Cipher {
4+
private keyword: string
5+
private static alphabet = "abcdefghijklmnopqrstuvwxyz"
6+
7+
constructor(keyword: string) {
8+
super()
9+
this.keyword = keyword.toLowerCase()
10+
}
11+
12+
/**
13+
* Encrypts a message using the Alphabet Cipher.
14+
* @param message - The plaintext message to encrypt.
15+
* @returns The encrypted ciphertext.
16+
*/
17+
encrypt(message: string): string {
18+
message = message.toLowerCase()
19+
const table = Alphabet.getVigenereTable()
20+
let result = ""
21+
22+
for (let i = 0; i < message.length; i++) {
23+
const msgChar = message[i]
24+
const keyChar = this.keyword[i % this.keyword.length]
25+
26+
if (!Alphabet.alphabet.includes(msgChar)) {
27+
result += msgChar // Preserve non-alphabet characters
28+
continue
29+
}
30+
31+
const row = Alphabet.alphabet.indexOf(keyChar)
32+
const col = Alphabet.alphabet.indexOf(msgChar)
33+
result += table[row][col]
34+
}
35+
36+
return result
37+
}
38+
39+
/**
40+
* Decrypts a message using the Alphabet Cipher.
41+
* @param ciphertext - The encrypted message to decrypt.
42+
* @returns The original plaintext message.
43+
*/
44+
decrypt(ciphertext: string): string {
45+
ciphertext = ciphertext.toLowerCase()
46+
const table = Alphabet.getVigenereTable()
47+
let result = ""
48+
49+
for (let i = 0; i < ciphertext.length; i++) {
50+
const cipherChar = ciphertext[i]
51+
const keyChar = this.keyword[i % this.keyword.length]
52+
53+
if (!Alphabet.alphabet.includes(cipherChar)) {
54+
result += cipherChar // Preserve non-alphabet characters
55+
continue
56+
}
57+
58+
const row = Alphabet.alphabet.indexOf(keyChar)
59+
const col = table[row].indexOf(cipherChar)
60+
result += Alphabet.alphabet[col]
61+
}
62+
63+
return result
64+
}
65+
66+
/**
67+
* Generates the Vigenère table for encoding and decoding.
68+
*/
69+
private static getVigenereTable(): string[][] {
70+
const table: string[][] = []
71+
for (let i = 0; i < 26; i++) {
72+
table[i] = Alphabet.alphabet
73+
.slice(i)
74+
.split("")
75+
.concat(Alphabet.alphabet.slice(0, i).split(""))
76+
}
77+
return table
78+
}
79+
}

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { Caesar } from "./ciphers/Caesar.js"
33
import { Atbash } from "./ciphers/Atbash.js"
44
import { Playfair } from "./ciphers/Playfair.js"
55
import { Vigenere } from "./ciphers/Vigenere.js"
6+
import { Alphabet } from "./ciphers/Alphabet.js"
67

78
Cipher.Caesar = Caesar
89
Cipher.Atbash = Atbash
910
Cipher.Playfair = Playfair
1011
Cipher.Vigenere = Vigenere
12+
Cipher.Alphabet = Alphabet
1113

1214
export { Cipher }

tests/alphabet.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Cipher } from "../src/index"
2+
3+
test(`The Alphabet Cipher`, () => {
4+
const alphabet = new Cipher.Alphabet("keyword")
5+
const plaintext = "hello world"
6+
const enc = alphabet.encrypt(plaintext)
7+
const dec = alphabet.decrypt(enc)
8+
9+
expect(dec).toBe(plaintext)
10+
})

0 commit comments

Comments
 (0)