@irfanshadikrishad/cipher 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,27 +2,62 @@
2
2
 
3
3
  A versatile and secure cryptographic library for implementing various cipher algorithms in Node.js applications.
4
4
 
5
- #### Installation
5
+ #### 🚀 Installation
6
+
7
+ Install the package via npm:
8
+
9
+ npm:
6
10
 
7
11
  ```bash
8
- npm i @irfanshadikrishad/cipher
12
+ npm install @irfanshadikrishad/cipher
9
13
  ```
10
14
 
11
- #### Usage
15
+ yarn:
16
+
17
+ ```bash
18
+ yarn add @irfanshadikrishad/cipher
19
+ ```
20
+
21
+ bun:
22
+
23
+ ```bash
24
+ bun add @irfanshadikrishad/cipher
25
+ ```
12
26
 
13
- ```js
27
+ #### 📖 Usage
28
+
29
+ Import the library and use a cipher algorithm:
30
+
31
+ ```ts
14
32
  import { Cipher } from "@irfanshadikrishad/cipher"
15
33
 
16
- const ceaser = new Cipher.Ceaser(6)
34
+ // Create a Caesar Cipher instance with a shift of 6
35
+ const caesar = new Cipher.Caesar(6)
17
36
 
18
- console.log(ceaser.encrypt("hello world"))
37
+ console.log(caesar.encrypt("hello world")) // Output: "nkrru cuxrj"
19
38
  ```
20
39
 
21
- #### Available Ciphers
40
+ #### 🔐 Supported Ciphers
41
+
42
+ This library provides implementations of various classical and modern ciphers:
43
+
44
+ | Cipher | Type | Key required? | Strength | Used In/Notes |
45
+ | --------------------------------------------------- | -------------- | ------------- | -------- | ------------------------------------------ |
46
+ | [Caesar Cipher](/docs/en/ciphers/CAESAR.md) | Substitution | No | Low | Ancient Rome, Simple Obsfuscation |
47
+ | [Atbash Cipher](/docs/en/ciphers/ATBASH.md) | Substitution | No | Low | Hebrew Cipher, Basic Encryption |
48
+ | [Playfair Cipher](/docs/en/ciphers/PLAYFAIR.md) | Diagraph-based | Yes | Medium | Used in WWI & WWII |
49
+ | [Vigenère Cipher](/docs/en/ciphers/VIGENERE.md) | Polyalphabetic | Yes | Medium | Used in Historical Documents |
50
+ | [The Alphabet Cipher](/docs/en/ciphers/ALPHABET.md) | Polyalphabetic | Yes | Medium | Inspired by Vigenere, Cryptography Puzzles |
51
+ | [Salsa20](/docs/en/ciphers/SALSA20.md) | Stream Cipher | Yes | High | Modern Cryptography, Secure Communications |
52
+
53
+ More ciphers coming soon...
54
+
55
+ #### 🍀 Contribution
56
+
57
+ To contribute on the codebase, follow [contribution guideline](/docs/en/CONTRIBUTING.md).
58
+
59
+ #### ❤️ Support
22
60
 
23
- - Ceaser Cipher
24
- - Atbash Cipher
25
- - Playfair Cipher
26
- - Vigenere Cipher
61
+ If you find this library useful, consider giving it a ⭐ on GitHub!
27
62
 
28
- #### Thanks for visiting (>'-'<)
63
+ Thanks for visiting! (>'-'<)
package/dist/Cipher.d.ts CHANGED
@@ -2,11 +2,41 @@ import { Caesar } from "./ciphers/Caesar.js";
2
2
  import { Atbash } from "./ciphers/Atbash.js";
3
3
  import { Playfair } from "./ciphers/Playfair.js";
4
4
  import { Vigenere } from "./ciphers/Vigenere.js";
5
+ import { Alphabet } from "./ciphers/Alphabet.js";
6
+ import { Salsa20 } from "./ciphers/Salsa20.js";
5
7
  export declare abstract class Cipher {
8
+ /**
9
+ * Caesar cipher is a substitution cipher where each letter in the plaintext is shifted a certain number of places down the alphabet.
10
+ * @param shift Number of places to shift the alphabet
11
+ */
6
12
  static Caesar: typeof Caesar;
13
+ /**
14
+ * Atbash cipher is a substitution cipher where the alphabet is reversed.
15
+ * A -> Z, B -> Y, C -> X, ..., Z -> A
16
+ */
7
17
  static Atbash: typeof Atbash;
18
+ /**
19
+ * Playfair cipher is a digraph substitution cipher that encrypts pairs of letters.
20
+ * @param key 5x5 grid of letters
21
+ */
8
22
  static Playfair: typeof Playfair;
23
+ /**
24
+ * Vigenère cipher is a polyalphabetic substitution cipher that encrypts the plaintext with a keyword.
25
+ * @param key Keyword to encrypt the plaintext
26
+ */
9
27
  static Vigenere: typeof Vigenere;
10
- abstract encrypt(text: string): string;
11
- abstract decrypt(text: string): string;
28
+ /**
29
+ * "The Alphabet Cipher" was a brief study published by Lewis Carroll in 1868, describing how to use the alphabet to send encrypted codes.
30
+ */
31
+ static Alphabet: typeof Alphabet;
32
+ /**
33
+ * Salsa20 is a stream cipher developed by Daniel J. Bernstein.
34
+ * It is widely used in the industry and is considered secure.
35
+ * @param key 256-bit key
36
+ * @param nonce 64-bit nonce
37
+ * @param counter 64-bit counter
38
+ */
39
+ static Salsa20: typeof Salsa20;
40
+ abstract encrypt(text: string): string | Uint8Array;
41
+ abstract decrypt(text: string | Uint8Array): string;
12
42
  }
@@ -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
+ }
@@ -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";
@@ -0,0 +1,16 @@
1
+ import { Cipher } from "../Cipher.js";
2
+ export declare class Salsa20 extends Cipher {
3
+ private key;
4
+ private nonce;
5
+ private counter;
6
+ constructor(key: Uint8Array | string, nonce: Uint8Array | string, counter?: number);
7
+ private static rotateLeft;
8
+ private static quarterRound;
9
+ private generateKeystreamBlock;
10
+ encrypt(plaintext: string): string;
11
+ decrypt(ciphertext: string): string;
12
+ static generateKey(): string;
13
+ static generateNonce(): string;
14
+ static encodeBase64(uint8array: Uint8Array): string;
15
+ static decodeBase64(base64: string): Uint8Array;
16
+ }
@@ -0,0 +1,94 @@
1
+ import { Cipher } from "../Cipher.js";
2
+ import crypto from "crypto";
3
+ import { Buffer } from "buffer";
4
+ export class Salsa20 extends Cipher {
5
+ constructor(key, nonce, counter = 0) {
6
+ super();
7
+ if (typeof key === "string")
8
+ key = Buffer.from(key, "base64");
9
+ if (typeof nonce === "string")
10
+ nonce = Buffer.from(nonce, "base64");
11
+ if (key.length !== 32)
12
+ throw new Error("Key must be 32 bytes (256-bit).");
13
+ if (nonce.length !== 8)
14
+ throw new Error("Nonce must be 8 bytes (64-bit).");
15
+ this.key = new Uint32Array(new Uint8Array(key).buffer);
16
+ this.nonce = new Uint32Array(new Uint8Array(nonce).buffer);
17
+ this.counter = counter;
18
+ }
19
+ static rotateLeft(x, n) {
20
+ return (x << n) | (x >>> (32 - n));
21
+ }
22
+ static quarterRound(state, a, b, c, d) {
23
+ state[b] ^= Salsa20.rotateLeft(state[a] + state[d], 7);
24
+ state[c] ^= Salsa20.rotateLeft(state[b] + state[a], 9);
25
+ state[d] ^= Salsa20.rotateLeft(state[c] + state[b], 13);
26
+ state[a] ^= Salsa20.rotateLeft(state[d] + state[c], 18);
27
+ }
28
+ generateKeystreamBlock() {
29
+ const constants = new Uint32Array([
30
+ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
31
+ ]); // "expand 32-byte k"
32
+ const state = new Uint32Array(16);
33
+ state.set(constants, 0);
34
+ state.set(this.key.slice(0, 4), 4);
35
+ state.set(this.nonce, 8);
36
+ state.set([this.counter, 0], 10);
37
+ state.set(this.key.slice(4, 8), 12);
38
+ const workingState = new Uint32Array(state);
39
+ for (let i = 0; i < 10; i++) {
40
+ Salsa20.quarterRound(workingState, 0, 4, 8, 12);
41
+ Salsa20.quarterRound(workingState, 1, 5, 9, 13);
42
+ Salsa20.quarterRound(workingState, 2, 6, 10, 14);
43
+ Salsa20.quarterRound(workingState, 3, 7, 11, 15);
44
+ Salsa20.quarterRound(workingState, 0, 5, 10, 15);
45
+ Salsa20.quarterRound(workingState, 1, 6, 11, 12);
46
+ Salsa20.quarterRound(workingState, 2, 7, 8, 13);
47
+ Salsa20.quarterRound(workingState, 3, 4, 9, 14);
48
+ }
49
+ for (let i = 0; i < 16; i++) {
50
+ workingState[i] += state[i];
51
+ }
52
+ this.counter++; // Increment counter for next block
53
+ return new Uint8Array(workingState.buffer);
54
+ }
55
+ encrypt(plaintext) {
56
+ const textBytes = new TextEncoder().encode(plaintext);
57
+ const ciphertext = new Uint8Array(textBytes.length);
58
+ for (let i = 0; i < textBytes.length; i += 64) {
59
+ const keystream = this.generateKeystreamBlock();
60
+ const blockLength = Math.min(64, textBytes.length - i);
61
+ for (let j = 0; j < blockLength; j++) {
62
+ ciphertext[i + j] = textBytes[i + j] ^ keystream[j];
63
+ }
64
+ }
65
+ return Salsa20.encodeBase64(ciphertext);
66
+ }
67
+ decrypt(ciphertext) {
68
+ const originalCounter = this.counter;
69
+ this.counter = 0;
70
+ const cipherUnit8Array = Salsa20.decodeBase64(ciphertext);
71
+ const decryptedBytes = new Uint8Array(cipherUnit8Array.length);
72
+ for (let i = 0; i < cipherUnit8Array.length; i += 64) {
73
+ const keystream = this.generateKeystreamBlock();
74
+ const blockLength = Math.min(64, cipherUnit8Array.length - i);
75
+ for (let j = 0; j < blockLength; j++) {
76
+ decryptedBytes[i + j] = cipherUnit8Array[i + j] ^ keystream[j];
77
+ }
78
+ }
79
+ this.counter = originalCounter;
80
+ return new TextDecoder().decode(decryptedBytes);
81
+ }
82
+ static generateKey() {
83
+ return Salsa20.encodeBase64(crypto.getRandomValues(new Uint8Array(32)));
84
+ }
85
+ static generateNonce() {
86
+ return Salsa20.encodeBase64(crypto.getRandomValues(new Uint8Array(8)));
87
+ }
88
+ static encodeBase64(uint8array) {
89
+ return Buffer.from(uint8array).toString("base64");
90
+ }
91
+ static decodeBase64(base64) {
92
+ return new Uint8Array(Buffer.from(base64, "base64"));
93
+ }
94
+ }
package/dist/index.js CHANGED
@@ -3,8 +3,12 @@ import { Caesar } from "./ciphers/Caesar.js";
3
3
  import { Atbash } from "./ciphers/Atbash.js";
4
4
  import { Playfair } from "./ciphers/Playfair.js";
5
5
  import { Vigenere } from "./ciphers/Vigenere.js";
6
+ import { Alphabet } from "./ciphers/Alphabet.js";
7
+ import { Salsa20 } from "./ciphers/Salsa20.js";
6
8
  Cipher.Caesar = Caesar;
7
9
  Cipher.Atbash = Atbash;
8
10
  Cipher.Playfair = Playfair;
9
11
  Cipher.Vigenere = Vigenere;
12
+ Cipher.Alphabet = Alphabet;
13
+ Cipher.Salsa20 = Salsa20;
10
14
  export { Cipher };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@irfanshadikrishad/cipher",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "A versatile and secure cryptographic library for implementing various cipher algorithms in Node.js applications.",
5
5
  "homepage": "https://github.com/irfanshadikrishad/cipher#readme",
6
6
  "bugs": {