@irfanshadikrishad/cipher 1.0.3 → 1.0.5

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,29 +2,65 @@
2
2
 
3
3
  A versatile and secure cryptographic library for implementing various cipher algorithms in Node.js applications.
4
4
 
5
- #### Installation
5
+ ![NPM Version](https://img.shields.io/npm/v/%40irfanshadikrishad%2Fcipher?style=for-the-badge&labelColor=202020&color=81B29A)
6
+ ![NPM Downloads](https://img.shields.io/npm/dw/%40irfanshadikrishad%2Fcipher?style=for-the-badge&labelColor=202020&color=BE9A60)
7
+ ![NPM Unpacked Size](https://img.shields.io/npm/unpacked-size/%40irfanshadikrishad%2Fcipher?style=for-the-badge&labelColor=202020&color=655699)
8
+
9
+ #### 🚀 Installation
10
+
11
+ Install the package via npm:
6
12
 
7
13
  ```bash
8
- npm i @irfanshadikrishad/cipher
14
+ npm install @irfanshadikrishad/cipher
9
15
  ```
10
16
 
11
- #### Usage
17
+ yarn:
18
+
19
+ ```bash
20
+ yarn add @irfanshadikrishad/cipher
21
+ ```
22
+
23
+ bun:
24
+
25
+ ```bash
26
+ bun add @irfanshadikrishad/cipher
27
+ ```
12
28
 
13
- ```js
29
+ #### 📖 Usage
30
+
31
+ Import the library and use a cipher algorithm:
32
+
33
+ ```ts
14
34
  import { Cipher } from "@irfanshadikrishad/cipher"
15
35
 
16
- const ceaser = new Cipher.Ceaser(6)
36
+ // Create a Caesar Cipher instance with a shift of 6
37
+ const caesar = new Cipher.Caesar(6)
17
38
 
18
- console.log(ceaser.encrypt("hello world"))
39
+ console.log(caesar.encrypt("hello world")) // Output: "nkrru cuxrj"
19
40
  ```
20
41
 
21
- #### Available Ciphers
42
+ #### 🔐 Supported Ciphers
43
+
44
+ This library provides implementations of various classical and modern ciphers:
45
+
46
+ | Cipher | Type | Key required? | Strength | Used In/Notes |
47
+ | --------------------------------------------------- | ---------------------------------------- | ------------- | -------- | ------------------------------------------ |
48
+ | [Caesar Cipher](/docs/en/ciphers/CAESAR.md) | Substitution | No | Low | Ancient Rome, Simple Obsfuscation |
49
+ | [Atbash Cipher](/docs/en/ciphers/ATBASH.md) | Substitution | No | Low | Hebrew Cipher, Basic Encryption |
50
+ | [Playfair Cipher](/docs/en/ciphers/PLAYFAIR.md) | Diagraph-based | Yes | Medium | Used in WWI & WWII |
51
+ | [Vigenère Cipher](/docs/en/ciphers/VIGENERE.md) | Polyalphabetic | Yes | Medium | Used in Historical Documents |
52
+ | [The Alphabet Cipher](/docs/en/ciphers/ALPHABET.md) | Polyalphabetic | Yes | Medium | Inspired by Vigenere, Cryptography Puzzles |
53
+ | [Salsa20](/docs/en/ciphers/SALSA20.md) | Stream Cipher | Yes | High | Modern Cryptography, Secure Communications |
54
+ | [ADFGVX](/docs/en/ciphers/ADFGVX.md) | Polybius Square + Columnar Transposition | Yes | Medium | Used in WWI, Known for 6x6 polybius square |
55
+
56
+ More ciphers coming soon...
57
+
58
+ #### 🍀 Contribution
59
+
60
+ To contribute on the codebase, follow [contribution guideline](/docs/en/CONTRIBUTING.md).
61
+
62
+ #### ❤️ Support
22
63
 
23
- - Ceaser Cipher
24
- - Atbash Cipher
25
- - Playfair Cipher
26
- - Vigenere Cipher
27
- - The Alphabet Cipher
28
- - & more coming soon ...
64
+ If you find this library useful, consider giving it a ⭐ on GitHub!
29
65
 
30
- #### Thanks for visiting (>'-'<)
66
+ Thanks for visiting! (>'-'<)
package/dist/Cipher.d.ts CHANGED
@@ -3,12 +3,47 @@ import { Atbash } from "./ciphers/Atbash.js";
3
3
  import { Playfair } from "./ciphers/Playfair.js";
4
4
  import { Vigenere } from "./ciphers/Vigenere.js";
5
5
  import { Alphabet } from "./ciphers/Alphabet.js";
6
+ import { Salsa20 } from "./ciphers/Salsa20.js";
7
+ import { ADFGVX } from "./ciphers/ADFGVX.js";
6
8
  export declare abstract class Cipher {
9
+ /**
10
+ * Caesar cipher is a substitution cipher where each letter in the plaintext is shifted a certain number of places down the alphabet.
11
+ * @param shift Number of places to shift the alphabet
12
+ */
7
13
  static Caesar: typeof Caesar;
14
+ /**
15
+ * Atbash cipher is a substitution cipher where the alphabet is reversed.
16
+ * A -> Z, B -> Y, C -> X, ..., Z -> A
17
+ */
8
18
  static Atbash: typeof Atbash;
19
+ /**
20
+ * Playfair cipher is a digraph substitution cipher that encrypts pairs of letters.
21
+ * @param key 5x5 grid of letters
22
+ */
9
23
  static Playfair: typeof Playfair;
24
+ /**
25
+ * Vigenère cipher is a polyalphabetic substitution cipher that encrypts the plaintext with a keyword.
26
+ * @param key Keyword to encrypt the plaintext
27
+ */
10
28
  static Vigenere: typeof Vigenere;
29
+ /**
30
+ * "The Alphabet Cipher" was a brief study published by Lewis Carroll in 1868, describing how to use the alphabet to send encrypted codes.
31
+ */
11
32
  static Alphabet: typeof Alphabet;
12
- abstract encrypt(text: string): string;
13
- abstract decrypt(text: string): string;
33
+ /**
34
+ * Salsa20 is a stream cipher developed by Daniel J. Bernstein.
35
+ * It is widely used in the industry and is considered secure.
36
+ * @param key 256-bit key
37
+ * @param nonce 64-bit nonce
38
+ * @param counter 64-bit counter
39
+ */
40
+ static Salsa20: typeof Salsa20;
41
+ /**
42
+ * The ADFGVX cipher was a manually applied field cipher used by the Imperial German Army during World War I.
43
+ * @param key - more than 1 characters long (more length, more secure)
44
+ * @param codeword - 36 characters long
45
+ */
46
+ static ADFGVX: typeof ADFGVX;
47
+ abstract encrypt(text: string): string | Uint8Array;
48
+ abstract decrypt(text: string | Uint8Array): string;
14
49
  }
@@ -0,0 +1,13 @@
1
+ import { Cipher } from "../Cipher.js";
2
+ export declare class ADFGVX extends Cipher {
3
+ private key;
4
+ private codeword;
5
+ private polybiusSquare;
6
+ private reverseSquare;
7
+ private adfgvx;
8
+ constructor(key?: string | null, codeword?: string | null);
9
+ private createPolybiusSquare;
10
+ private columnarTranspose;
11
+ encrypt(text: string): string;
12
+ decrypt(text: string): string;
13
+ }
@@ -0,0 +1,89 @@
1
+ import { Cipher } from "../Cipher.js";
2
+ export class ADFGVX extends Cipher {
3
+ constructor(key, codeword) {
4
+ super();
5
+ this.key = "CIPHER";
6
+ this.codeword = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
7
+ this.polybiusSquare = new Map();
8
+ this.reverseSquare = new Map();
9
+ this.adfgvx = ["A", "D", "F", "G", "V", "X"];
10
+ if (key)
11
+ this.key = key.toUpperCase();
12
+ if (codeword)
13
+ this.codeword = codeword.toUpperCase();
14
+ this.createPolybiusSquare(this.codeword);
15
+ }
16
+ createPolybiusSquare(codeword) {
17
+ const uniqueLetters = [];
18
+ for (const char of codeword.toUpperCase()) {
19
+ if (!uniqueLetters.includes(char)) {
20
+ uniqueLetters.push(char);
21
+ }
22
+ }
23
+ const remainingChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
24
+ .split("")
25
+ .filter((char) => !uniqueLetters.includes(char));
26
+ const alphabet = [...uniqueLetters, ...remainingChars];
27
+ let index = 0;
28
+ for (const row of this.adfgvx) {
29
+ for (const col of this.adfgvx) {
30
+ const letter = alphabet[index];
31
+ const code = row + col;
32
+ this.polybiusSquare.set(letter, code);
33
+ this.reverseSquare.set(code, letter);
34
+ index++;
35
+ }
36
+ }
37
+ }
38
+ columnarTranspose(text, decrypt = false) {
39
+ const keyOrder = [...this.key]
40
+ .map((char, index) => ({ char, index }))
41
+ .sort((a, b) => a.char.localeCompare(b.char))
42
+ .map((item) => item.index);
43
+ const numCols = this.key.length;
44
+ const numRows = Math.ceil(text.length / numCols);
45
+ const grid = Array.from({ length: numRows }, () => new Array(numCols).fill(""));
46
+ if (!decrypt) {
47
+ let charIndex = 0;
48
+ for (let row = 0; row < numRows; row++) {
49
+ for (let col = 0; col < numCols; col++) {
50
+ if (charIndex < text.length) {
51
+ grid[row][col] = text[charIndex++];
52
+ }
53
+ }
54
+ }
55
+ return keyOrder
56
+ .map((col) => grid.map((row) => row[col]).join(""))
57
+ .join("");
58
+ }
59
+ else {
60
+ const sortedKeyOrder = [...keyOrder].sort((a, b) => this.key[a].localeCompare(this.key[b]));
61
+ let charIndex = 0;
62
+ for (const sortedCol of sortedKeyOrder) {
63
+ for (let row = 0; row < numRows; row++) {
64
+ if (charIndex < text.length) {
65
+ grid[row][sortedCol] = text[charIndex++];
66
+ }
67
+ }
68
+ }
69
+ return grid.flat().join("");
70
+ }
71
+ }
72
+ encrypt(text) {
73
+ const plaintext = text.replace(/[^A-Za-z0-9]/g, "").toUpperCase();
74
+ const polybiusText = plaintext
75
+ .split("")
76
+ .map((char) => this.polybiusSquare.get(char) || "")
77
+ .join("");
78
+ return this.columnarTranspose(polybiusText);
79
+ }
80
+ decrypt(text) {
81
+ var _a;
82
+ const encrypted = text.replace(/[^A-Za-z0-9]/g, "").toUpperCase();
83
+ const intermediate = this.columnarTranspose(encrypted, true);
84
+ const polybiusText = ((_a = intermediate.match(/.{1,2}/g)) === null || _a === void 0 ? void 0 : _a.map((char) => {
85
+ return this.reverseSquare.get(char) || "";
86
+ })) || [];
87
+ return polybiusText.join("");
88
+ }
89
+ }
@@ -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
@@ -4,9 +4,13 @@ import { Atbash } from "./ciphers/Atbash.js";
4
4
  import { Playfair } from "./ciphers/Playfair.js";
5
5
  import { Vigenere } from "./ciphers/Vigenere.js";
6
6
  import { Alphabet } from "./ciphers/Alphabet.js";
7
+ import { Salsa20 } from "./ciphers/Salsa20.js";
8
+ import { ADFGVX } from "./ciphers/ADFGVX.js";
7
9
  Cipher.Caesar = Caesar;
8
10
  Cipher.Atbash = Atbash;
9
11
  Cipher.Playfair = Playfair;
10
12
  Cipher.Vigenere = Vigenere;
11
13
  Cipher.Alphabet = Alphabet;
14
+ Cipher.Salsa20 = Salsa20;
15
+ Cipher.ADFGVX = ADFGVX;
12
16
  export { Cipher };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@irfanshadikrishad/cipher",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
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": {