@mhmdhammoud/meritt-utils 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/.github/workflows/npm-publish.yml +43 -0
- package/.github/workflows/push.yml +29 -0
- package/.husky/pre-commit +62 -0
- package/README.md +12 -4
- package/ReleaseNotes.md +59 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/lib/cypto.d.ts +55 -22
- package/dist/lib/cypto.js +167 -38
- package/dist/lib/formatter.d.ts +43 -0
- package/dist/lib/formatter.js +121 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +3 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/lib/cypto.ts +205 -39
- package/src/lib/formatter.ts +121 -0
- package/src/lib/index.ts +1 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: NPM Publish on Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
jobs:
|
|
7
|
+
build:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v3
|
|
11
|
+
- uses: actions/setup-node@v3
|
|
12
|
+
with:
|
|
13
|
+
node-version: 16
|
|
14
|
+
- run: npm ci
|
|
15
|
+
|
|
16
|
+
publish-npm:
|
|
17
|
+
needs: build
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v3
|
|
21
|
+
- uses: actions/setup-node@v3
|
|
22
|
+
with:
|
|
23
|
+
node-version: 16
|
|
24
|
+
registry-url: https://registry.npmjs.org/
|
|
25
|
+
- run: npm ci
|
|
26
|
+
- run: npm publish
|
|
27
|
+
env:
|
|
28
|
+
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
|
29
|
+
notify:
|
|
30
|
+
needs: [publish-npm]
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- name: Notify by Email
|
|
34
|
+
uses: dawidd6/action-send-mail@v2
|
|
35
|
+
with:
|
|
36
|
+
server_address: ${{ secrets.EMAIL_HOST }}
|
|
37
|
+
server_port: 465
|
|
38
|
+
username: ${{ secrets.EMAIL_USERNAME }}
|
|
39
|
+
password: ${{ secrets.EMAIL_PASSWORD }}
|
|
40
|
+
subject: ${{ github.event.head_commit.message }} ${{ github.job }} job of ${{ github.repository }} has ${{ job.status }}
|
|
41
|
+
body: ${{ github.job }} job in worflow ${{ github.workflow }} of ${{ github.repository }} has ${{ job.status }}
|
|
42
|
+
to: mohammad.hammoud.lb@hotmail.com,steef12009@gmail.com,sawwas.omar@gmail.com
|
|
43
|
+
from: Github Action
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Changes
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [dev]
|
|
5
|
+
jobs:
|
|
6
|
+
type-check:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
steps:
|
|
9
|
+
- uses: actions/checkout@v3
|
|
10
|
+
- uses: actions/setup-node@v3
|
|
11
|
+
with:
|
|
12
|
+
node-version: 16
|
|
13
|
+
- run: npm ci
|
|
14
|
+
- run: npm run types
|
|
15
|
+
notify:
|
|
16
|
+
needs: [type-check]
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- name: Notify by Email
|
|
20
|
+
uses: dawidd6/action-send-mail@v2
|
|
21
|
+
with:
|
|
22
|
+
server_address: ${{ secrets.EMAIL_HOST }}
|
|
23
|
+
server_port: 465
|
|
24
|
+
username: ${{ secrets.EMAIL_USERNAME }}
|
|
25
|
+
password: ${{ secrets.EMAIL_PASSWORD }}
|
|
26
|
+
subject: ${{ github.event.head_commit.message }} ${{ github.job }} job of ${{ github.repository }} has ${{ job.status }}
|
|
27
|
+
body: ${{ github.job }} job in worflow ${{ github.workflow }} of ${{ github.repository }} has ${{ job.status }}
|
|
28
|
+
to: mohammad.hammoud.lb@hotmail.com,steef12009@gmail.com,sawwas.omar@gmail.com
|
|
29
|
+
from: Github Action
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
3
|
+
|
|
4
|
+
red='\033[0;31m'
|
|
5
|
+
green='\033[0;32m'
|
|
6
|
+
yellow='\033[0;33m'
|
|
7
|
+
blue='\033[0;34m'
|
|
8
|
+
magenta='\033[0;35m'
|
|
9
|
+
cyan='\033[0;36m'
|
|
10
|
+
clear='\033[0m'
|
|
11
|
+
echo "
|
|
12
|
+
|
|
13
|
+
__ __ ______ _____ _____ _______ _______ _____ ________ __
|
|
14
|
+
| \/ | ____| __ \|_ _|__ __|__ __| | __ \| ____\ \ / /
|
|
15
|
+
| \ / | |__ | |__) | | | | | | | | | | | |__ \ \ / /
|
|
16
|
+
| |\/| | __| | _ / | | | | | | | | | | __| \ \/ /
|
|
17
|
+
| | | | |____| | \ \ _| |_ | | | | | |__| | |____ \ /
|
|
18
|
+
|_| |_|______|_| \_\_____| |_| |_| |_____/|______| \/
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
"
|
|
22
|
+
echo -e "Let's hope you are not ${red}DUMB${clear}!"
|
|
23
|
+
|
|
24
|
+
echo -ne '\n'
|
|
25
|
+
|
|
26
|
+
echo -e "${yellow}Or Are You ??${clear}!"
|
|
27
|
+
echo -ne '\n'
|
|
28
|
+
echo -e "${yellow}Running pre-commit hook...${clear}"
|
|
29
|
+
echo -ne '\n'
|
|
30
|
+
echo -ne '\n'
|
|
31
|
+
|
|
32
|
+
echo -ne '##################### (25%)\r'
|
|
33
|
+
sleep 0.3
|
|
34
|
+
echo -ne '############################## (35%)\r'
|
|
35
|
+
sleep 0.3
|
|
36
|
+
echo -ne '###################################### (45%)\r'
|
|
37
|
+
sleep 0.3
|
|
38
|
+
echo -ne '############################################################ (77%)\r'
|
|
39
|
+
sleep 0.3
|
|
40
|
+
echo -ne '################################################################## (100%)\r'
|
|
41
|
+
|
|
42
|
+
echo -ne '\n'
|
|
43
|
+
echo -ne '\n'
|
|
44
|
+
echo -ne '\n'
|
|
45
|
+
|
|
46
|
+
echo -e "${yellow}Running types...${clear}"
|
|
47
|
+
echo -ne '\n'
|
|
48
|
+
npm run types
|
|
49
|
+
echo -ne '\n'
|
|
50
|
+
|
|
51
|
+
echo -e "${green}types passed...${clear} ✅"
|
|
52
|
+
echo -ne '\n'
|
|
53
|
+
echo -e "${yellow}Running linting...${clear}"
|
|
54
|
+
|
|
55
|
+
npm run lint
|
|
56
|
+
echo -e "${green}linting passed...${clear} ✅"
|
|
57
|
+
|
|
58
|
+
echo -ne '\n'
|
|
59
|
+
|
|
60
|
+
echo -e "${yellow}Seems like you are a${clear} ${green}CLEVER DEVELOPER${clear} 👌"
|
|
61
|
+
echo -ne '\n'
|
|
62
|
+
echo -e "${green}GOOD TO GO${clear} 🚀🚀🚀"
|
package/README.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
This is a collection of utility functions that are often used in Meritt projects.
|
|
4
4
|
|
|
5
|
+
## Actions
|
|
6
|
+
|
|
7
|
+
[](https://github.com/Mhmdhammoud/meritt-utils/actions/workflows/push.yml) [](https://github.com/Mhmdhammoud/meritt-utils/actions/workflows/npm-publish.yml)
|
|
8
|
+
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
7
11
|
For npm:
|
|
@@ -19,9 +23,13 @@ yarn add @mhmdhammoud/meritt-utils
|
|
|
19
23
|
## Usage
|
|
20
24
|
|
|
21
25
|
```typescript
|
|
22
|
-
|
|
26
|
+
// Import the classes you need
|
|
27
|
+
import {Crypto, Formatter} from '@mhmdhammoud/meritt-utils'
|
|
28
|
+
|
|
29
|
+
// Example of creating a product slug
|
|
30
|
+
const slug = Formatter.slugify('My Product Name') // my-product-name
|
|
31
|
+
|
|
32
|
+
// Example of encrypting and decrypting a string
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
const encryptedMessage = Crypto.encrypt('Hello World', 7)
|
|
26
|
-
const decryptedMessage = Crypto.decrypt(encryptedMessage, 7)
|
|
34
|
+
const encryptedMessage = Crypto.encrypt('Hello World', 7) // [23,235,141,414]
|
|
27
35
|
```
|
package/ReleaseNotes.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Changes
|
|
2
|
+
|
|
3
|
+
## Version 1.0.4
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added generateKeys method that returns public and private keys
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import {Crypto} from '@mhmdhammoud/meritt-utils'
|
|
11
|
+
|
|
12
|
+
// Example of generating a public and a private key
|
|
13
|
+
const response = Crypto.generateKeys()
|
|
14
|
+
console.log(response)
|
|
15
|
+
|
|
16
|
+
{
|
|
17
|
+
publicKey:7,
|
|
18
|
+
privateKey:247,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Fixes and Improvements
|
|
25
|
+
|
|
26
|
+
- Checking for prime numbers discarding even and odd numbers and skips 6 iterations at a time until radical I
|
|
27
|
+
|
|
28
|
+
## Version 1.0.3
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- Added Formatter class for manipulating strings
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import {Formatter} from '@mhmdhammoud/meritt-utils'
|
|
36
|
+
|
|
37
|
+
// Example of creating a product slug
|
|
38
|
+
const slug = Formatter.slugify('My Product Name') // my-product-name
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Fixes and Improvements
|
|
42
|
+
|
|
43
|
+
- Fixed bug in Crypto class where encrypting a string with a key that is not a number would throw an error
|
|
44
|
+
|
|
45
|
+
- Improved Crypto class to allow encrypting and decrypting numbers and objects
|
|
46
|
+
|
|
47
|
+
- Documented Crypto class
|
|
48
|
+
|
|
49
|
+
## Version 1.0.2
|
|
50
|
+
|
|
51
|
+
- Added Crypto class that contains encrypt and decrypt methods for strings, numbers, and objects using a public and private key
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import {Crypto} from '@mhmdhammoud/meritt-utils'
|
|
55
|
+
|
|
56
|
+
// Example of encrypting and decrypting a string
|
|
57
|
+
const encryptedMessage = Crypto.encrypt('Hello World', 7) // [23,235,141,414]
|
|
58
|
+
const decryptedMessage = Crypto.decrypt(encryptedMessage, 247) // Hello World
|
|
59
|
+
```
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Crypto = void 0;
|
|
3
|
+
exports.Formatter = exports.Crypto = void 0;
|
|
4
4
|
var lib_1 = require("./lib");
|
|
5
5
|
Object.defineProperty(exports, "Crypto", { enumerable: true, get: function () { return lib_1.Crypto; } });
|
|
6
|
+
var lib_2 = require("./lib");
|
|
7
|
+
Object.defineProperty(exports, "Formatter", { enumerable: true, get: function () { return lib_2.Formatter; } });
|
package/dist/lib/cypto.d.ts
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Crypto class
|
|
3
|
-
* @class Crypto
|
|
4
|
-
* @example
|
|
5
|
-
* ```typescript
|
|
6
|
-
* import crypto from './lib/crypto'
|
|
7
|
-
* ```
|
|
8
|
-
* */
|
|
9
1
|
declare class Crypto {
|
|
10
2
|
private _primeNumberP;
|
|
11
3
|
private _primeNumberQ;
|
|
4
|
+
private _phiN;
|
|
12
5
|
private _moduloDenominator;
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param number - The number to check if prime
|
|
9
|
+
* @returns The boolean answer of prime checking operation
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* this._isPrime(5)
|
|
13
|
+
* ```
|
|
14
|
+
* */
|
|
15
|
+
private _isPrime;
|
|
13
16
|
/**
|
|
14
17
|
* Set the P prime number for the RSA algorithm
|
|
15
|
-
* @param
|
|
16
|
-
* @
|
|
18
|
+
* @param primeP - The prime number P of type string
|
|
19
|
+
* @returns void
|
|
17
20
|
* @example
|
|
18
21
|
* ```typescript
|
|
19
22
|
* crypto.setPrimeP(17)
|
|
@@ -22,8 +25,8 @@ declare class Crypto {
|
|
|
22
25
|
setPrimeP(primeP: number): void;
|
|
23
26
|
/**
|
|
24
27
|
* Set the Q prime number for the RSA algorithm
|
|
25
|
-
* @param
|
|
26
|
-
* @
|
|
28
|
+
* @param primeQ - The prime number Q of type string
|
|
29
|
+
* @returns void
|
|
27
30
|
* @example
|
|
28
31
|
* ```typescript
|
|
29
32
|
* crypto.setPrimeQ(19)
|
|
@@ -32,31 +35,61 @@ declare class Crypto {
|
|
|
32
35
|
setPrimeQ(primeQ: number): void;
|
|
33
36
|
/**
|
|
34
37
|
*
|
|
35
|
-
* @param
|
|
36
|
-
* @param
|
|
37
|
-
* @
|
|
38
|
+
* @param base - The base number of type number
|
|
39
|
+
* @param exponent - The exponent number of type number
|
|
40
|
+
* @returns The modular exponentiation of the base and the exponent
|
|
38
41
|
* @example
|
|
39
42
|
* ```typescript
|
|
40
43
|
* this.modularExponentiation(2, 3)
|
|
41
44
|
* ```
|
|
42
45
|
* */
|
|
43
46
|
private _modularExponentiation;
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* @param temporaryVarriableOne - The number one
|
|
50
|
+
* @param temporaryVarriableTwo- The number two (phi n)
|
|
51
|
+
* @returns The boolean answer of relatively prime checking operation with phi n
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* this._areRelativelyPrime(5,9)
|
|
55
|
+
* ```
|
|
56
|
+
* */
|
|
57
|
+
private _areRelativelyPrime;
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
* @returns The public and private key number which is a random number generated to match conditions set by RSA algorithm
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* crypto.generateKeys()
|
|
64
|
+
* ```
|
|
65
|
+
* */
|
|
66
|
+
generateKeys: () => Record<'publicKey' | 'privateKey', number>;
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @param publicKey - The public key number
|
|
70
|
+
* @returns The private key number which is the modulus inverse with repect to modulo denominator
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* crypto.generatePrivateKey(5)
|
|
74
|
+
* ```
|
|
75
|
+
* */
|
|
76
|
+
private _generatePrivateKey;
|
|
44
77
|
/**
|
|
45
78
|
* Encrypt the message using the public key
|
|
46
|
-
* @param
|
|
47
|
-
* @param
|
|
48
|
-
* @
|
|
79
|
+
* @param message - The message to encrypt of type string|number|Record
|
|
80
|
+
* @param publicKey - The public key to encrypt the message with of type number
|
|
81
|
+
* @returns The encrypted message of type number[]
|
|
49
82
|
* @example
|
|
50
83
|
* ```typescript
|
|
51
84
|
* crypto.encrypt('Hello World', 7)
|
|
52
85
|
* ```
|
|
53
86
|
* */
|
|
54
|
-
encrypt: (message: string, publicKey: number) => number[];
|
|
87
|
+
encrypt: (message: string | number | Record<any, any>, publicKey: number) => number[];
|
|
55
88
|
/**
|
|
56
89
|
* Decrypt the message using the private key
|
|
57
|
-
* @param
|
|
58
|
-
* @param
|
|
59
|
-
* @
|
|
90
|
+
* @param encryptedMessage - The encryptedMessage to decrypt of type number[]
|
|
91
|
+
* @param privateKey - The private key to decrypt the message with of type number
|
|
92
|
+
* @returns The decrypted message of type string
|
|
60
93
|
* @example
|
|
61
94
|
* ```typescript
|
|
62
95
|
* crypto.decrypt([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100], 23)
|
package/dist/lib/cypto.js
CHANGED
|
@@ -1,30 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* ```
|
|
10
|
-
* */
|
|
3
|
+
/*
|
|
4
|
+
Author : Omar Sawwas
|
|
5
|
+
Date : 2023-06-17
|
|
6
|
+
Description : RSA algorithm
|
|
7
|
+
Version : 1.0
|
|
8
|
+
*/
|
|
11
9
|
class Crypto {
|
|
12
10
|
constructor() {
|
|
13
11
|
// Default variables
|
|
14
12
|
this._primeNumberP = 17;
|
|
15
13
|
this._primeNumberQ = 19;
|
|
14
|
+
this._phiN = (this._primeNumberP - 1) * (this._primeNumberQ - 1);
|
|
16
15
|
this._moduloDenominator = this._primeNumberP * this._primeNumberQ;
|
|
17
16
|
/**
|
|
18
17
|
*
|
|
19
|
-
* @param
|
|
20
|
-
* @
|
|
21
|
-
* @
|
|
18
|
+
* @param number - The number to check if prime
|
|
19
|
+
* @returns The boolean answer of prime checking operation
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* this._isPrime(5)
|
|
23
|
+
* ```
|
|
24
|
+
* */
|
|
25
|
+
this._isPrime = (number) => {
|
|
26
|
+
if (number <= 1) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (number <= 3) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
if (number % 2 === 0 || number % 3 === 0) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
for (let i = 5; i * i <= number; i += 6) {
|
|
36
|
+
if (number % i === 0 || number % (i + 2) === 0) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @param base - The base number of type number
|
|
45
|
+
* @param exponent - The exponent number of type number
|
|
46
|
+
* @returns The modular exponentiation of the base and the exponent
|
|
22
47
|
* @example
|
|
23
48
|
* ```typescript
|
|
24
49
|
* this.modularExponentiation(2, 3)
|
|
25
50
|
* ```
|
|
26
51
|
* */
|
|
27
52
|
this._modularExponentiation = (base, exponent) => {
|
|
53
|
+
if (isNaN(base) || isNaN(exponent)) {
|
|
54
|
+
throw new Error('Provide a valid number');
|
|
55
|
+
}
|
|
28
56
|
if (this._moduloDenominator === 1) {
|
|
29
57
|
return 0;
|
|
30
58
|
}
|
|
@@ -39,35 +67,144 @@ class Crypto {
|
|
|
39
67
|
}
|
|
40
68
|
return result;
|
|
41
69
|
};
|
|
70
|
+
/**
|
|
71
|
+
*
|
|
72
|
+
* @param temporaryVarriableOne - The number one
|
|
73
|
+
* @param temporaryVarriableTwo- The number two (phi n)
|
|
74
|
+
* @returns The boolean answer of relatively prime checking operation with phi n
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* this._areRelativelyPrime(5,9)
|
|
78
|
+
* ```
|
|
79
|
+
* */
|
|
80
|
+
this._areRelativelyPrime = (temporaryVarriableOne, temporaryVarriableTwo) => {
|
|
81
|
+
while (temporaryVarriableTwo !== 0) {
|
|
82
|
+
const temp = temporaryVarriableTwo;
|
|
83
|
+
temporaryVarriableTwo = temporaryVarriableOne % temporaryVarriableTwo;
|
|
84
|
+
temporaryVarriableOne = temp;
|
|
85
|
+
}
|
|
86
|
+
return temporaryVarriableOne === 1;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
* @returns The public and private key number which is a random number generated to match conditions set by RSA algorithm
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* crypto.generateKeys()
|
|
94
|
+
* ```
|
|
95
|
+
* */
|
|
96
|
+
this.generateKeys = () => {
|
|
97
|
+
const temporaryArray = [];
|
|
98
|
+
for (let i = 2; i < this._phiN; i++) {
|
|
99
|
+
if (this._areRelativelyPrime(i, this._phiN)) {
|
|
100
|
+
temporaryArray.push(i);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (temporaryArray.length === 0)
|
|
104
|
+
throw new Error('No public key options found!');
|
|
105
|
+
const randomIndex = Math.floor(Math.random() * temporaryArray.length);
|
|
106
|
+
// return temporaryArray[randomIndex]
|
|
107
|
+
const publicKey = temporaryArray[randomIndex];
|
|
108
|
+
const privateKey = this._generatePrivateKey(publicKey);
|
|
109
|
+
if (privateKey === publicKey) {
|
|
110
|
+
return this.generateKeys();
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
privateKey: publicKey,
|
|
114
|
+
publicKey: privateKey,
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
* @param publicKey - The public key number
|
|
120
|
+
* @returns The private key number which is the modulus inverse with repect to modulo denominator
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* crypto.generatePrivateKey(5)
|
|
124
|
+
* ```
|
|
125
|
+
* */
|
|
126
|
+
this._generatePrivateKey = (publicKey) => {
|
|
127
|
+
if (publicKey <= 1 || isNaN(publicKey)) {
|
|
128
|
+
throw new Error('Public key should be a number greater than 1');
|
|
129
|
+
}
|
|
130
|
+
if (!this._areRelativelyPrime(publicKey, this._phiN)) {
|
|
131
|
+
throw new Error('Public key should be relatively prime with respect to phi N');
|
|
132
|
+
}
|
|
133
|
+
let t1 = 0;
|
|
134
|
+
let t2 = 1;
|
|
135
|
+
let r1 = this._phiN;
|
|
136
|
+
let r2 = publicKey;
|
|
137
|
+
while (r2 !== 0) {
|
|
138
|
+
const quotient = Math.floor(r1 / r2);
|
|
139
|
+
const temp1 = t1;
|
|
140
|
+
const temp2 = r1;
|
|
141
|
+
t1 = t2;
|
|
142
|
+
r1 = r2;
|
|
143
|
+
t2 = temp1 - quotient * t2;
|
|
144
|
+
r2 = temp2 - quotient * r2;
|
|
145
|
+
}
|
|
146
|
+
if (r1 > 1) {
|
|
147
|
+
throw new Error('The number does not have a modular inverse.');
|
|
148
|
+
}
|
|
149
|
+
if (t1 < 0) {
|
|
150
|
+
t1 += this._phiN;
|
|
151
|
+
}
|
|
152
|
+
return t1;
|
|
153
|
+
};
|
|
42
154
|
/**
|
|
43
155
|
* Encrypt the message using the public key
|
|
44
|
-
* @param
|
|
45
|
-
* @param
|
|
46
|
-
* @
|
|
156
|
+
* @param message - The message to encrypt of type string|number|Record
|
|
157
|
+
* @param publicKey - The public key to encrypt the message with of type number
|
|
158
|
+
* @returns The encrypted message of type number[]
|
|
47
159
|
* @example
|
|
48
160
|
* ```typescript
|
|
49
161
|
* crypto.encrypt('Hello World', 7)
|
|
50
162
|
* ```
|
|
51
163
|
* */
|
|
52
164
|
this.encrypt = (message, publicKey) => {
|
|
53
|
-
|
|
165
|
+
if (isNaN(publicKey)) {
|
|
166
|
+
throw new Error('Public key should be a number');
|
|
167
|
+
}
|
|
168
|
+
if (publicKey <= 0) {
|
|
169
|
+
throw new Error('Private key should be a positive number different than 0');
|
|
170
|
+
}
|
|
171
|
+
if (typeof message === 'number') {
|
|
172
|
+
message = message.toString();
|
|
173
|
+
}
|
|
174
|
+
if (typeof message === 'object') {
|
|
175
|
+
message = JSON.stringify(message);
|
|
176
|
+
}
|
|
177
|
+
const encryptedMessage = [];
|
|
54
178
|
for (let i = 0; i < message.length; i++) {
|
|
55
179
|
const a = message.charCodeAt(i);
|
|
56
|
-
|
|
180
|
+
encryptedMessage.push(this._modularExponentiation(a, publicKey));
|
|
57
181
|
}
|
|
58
|
-
return
|
|
182
|
+
return encryptedMessage;
|
|
59
183
|
};
|
|
60
184
|
/**
|
|
61
185
|
* Decrypt the message using the private key
|
|
62
|
-
* @param
|
|
63
|
-
* @param
|
|
64
|
-
* @
|
|
186
|
+
* @param encryptedMessage - The encryptedMessage to decrypt of type number[]
|
|
187
|
+
* @param privateKey - The private key to decrypt the message with of type number
|
|
188
|
+
* @returns The decrypted message of type string
|
|
65
189
|
* @example
|
|
66
190
|
* ```typescript
|
|
67
191
|
* crypto.decrypt([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100], 23)
|
|
68
192
|
* ```
|
|
69
193
|
* */
|
|
70
194
|
this.decrypt = (encryptedMessage, privateKey) => {
|
|
195
|
+
if (isNaN(privateKey)) {
|
|
196
|
+
throw new Error('Public key should be a number');
|
|
197
|
+
}
|
|
198
|
+
if (privateKey <= 0) {
|
|
199
|
+
throw new Error('Private key should be a positive number different than 0');
|
|
200
|
+
}
|
|
201
|
+
if (!Array.isArray(encryptedMessage)) {
|
|
202
|
+
throw new Error('Encrypted message should be an array');
|
|
203
|
+
}
|
|
204
|
+
const allValidNumbers = encryptedMessage.every((number) => !isNaN(number));
|
|
205
|
+
if (!allValidNumbers) {
|
|
206
|
+
throw new Error('Encrypted message should be an array of numbers');
|
|
207
|
+
}
|
|
71
208
|
const decryptedAsciiMessage = [];
|
|
72
209
|
for (let i = 0; i < encryptedMessage.length; i++) {
|
|
73
210
|
const a = encryptedMessage[i];
|
|
@@ -82,44 +219,36 @@ class Crypto {
|
|
|
82
219
|
}
|
|
83
220
|
/**
|
|
84
221
|
* Set the P prime number for the RSA algorithm
|
|
85
|
-
* @param
|
|
86
|
-
* @
|
|
222
|
+
* @param primeP - The prime number P of type string
|
|
223
|
+
* @returns void
|
|
87
224
|
* @example
|
|
88
225
|
* ```typescript
|
|
89
226
|
* crypto.setPrimeP(17)
|
|
90
227
|
* ```
|
|
91
228
|
* */
|
|
92
229
|
setPrimeP(primeP) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (primeP % i === 0) {
|
|
96
|
-
isPrime = false;
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
230
|
+
if (isNaN(primeP) || primeP === 0) {
|
|
231
|
+
throw new Error('Provide a valid number');
|
|
99
232
|
}
|
|
100
|
-
if (!
|
|
233
|
+
if (!this._isPrime(primeP)) {
|
|
101
234
|
throw new Error('The number is not prime');
|
|
102
235
|
}
|
|
103
236
|
this._primeNumberP = primeP;
|
|
104
237
|
}
|
|
105
238
|
/**
|
|
106
239
|
* Set the Q prime number for the RSA algorithm
|
|
107
|
-
* @param
|
|
108
|
-
* @
|
|
240
|
+
* @param primeQ - The prime number Q of type string
|
|
241
|
+
* @returns void
|
|
109
242
|
* @example
|
|
110
243
|
* ```typescript
|
|
111
244
|
* crypto.setPrimeQ(19)
|
|
112
245
|
* ```
|
|
113
246
|
* */
|
|
114
247
|
setPrimeQ(primeQ) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (primeQ % i === 0) {
|
|
118
|
-
isPrime = false;
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
248
|
+
if (isNaN(primeQ) || primeQ === 0) {
|
|
249
|
+
throw new Error('Provide a valid number');
|
|
121
250
|
}
|
|
122
|
-
if (!
|
|
251
|
+
if (!this._isPrime(primeQ)) {
|
|
123
252
|
throw new Error('The number is not prime');
|
|
124
253
|
}
|
|
125
254
|
this._primeNumberQ = primeQ;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
declare class Formatter {
|
|
2
|
+
/**
|
|
3
|
+
* @remarks Normalizes input by removing underscores and hyphens and capitalizing the first letter of the sentence.
|
|
4
|
+
* @param stringToBeChanged - to be formatted without underscores and hyphens
|
|
5
|
+
* @param withWhiteSpacing - Determines if white spacing is needed in the final string or not (default: true)
|
|
6
|
+
* @returns string
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* formatter.toUpperFirst('hello world')
|
|
10
|
+
* // => 'Hello-World'
|
|
11
|
+
* ```
|
|
12
|
+
* */
|
|
13
|
+
toUpperFirst: (_: string | number, withSpacing?: boolean) => string;
|
|
14
|
+
/**
|
|
15
|
+
* @remarks normalizes input to supported path and file name format.
|
|
16
|
+
* Changes camelCase strings to kebab-case, replaces spaces with dash and keeps underscores. *
|
|
17
|
+
* @param str - String needed to be modified
|
|
18
|
+
* @returns formatted string
|
|
19
|
+
*/
|
|
20
|
+
camelToKebab: (str: string) => string;
|
|
21
|
+
/**
|
|
22
|
+
* @remarks obfuscates email address
|
|
23
|
+
* @param email - email address to be obfuscated
|
|
24
|
+
* @returns obfuscated email address
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* formatter.obfuscate('johndoe@email.com') // => jo*****@gmail.com
|
|
28
|
+
* ```
|
|
29
|
+
* */
|
|
30
|
+
obfuscate: (email: string) => string;
|
|
31
|
+
/**
|
|
32
|
+
* @remarks Generates a slug from a given string
|
|
33
|
+
* @param title - string to be converted to slug
|
|
34
|
+
* @returns slug
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* formatter.slugify('Hello World') // => hello-world
|
|
38
|
+
* ```
|
|
39
|
+
* */
|
|
40
|
+
slugify: (title: string) => string;
|
|
41
|
+
}
|
|
42
|
+
declare const formatter: Formatter;
|
|
43
|
+
export default formatter;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/*
|
|
4
|
+
Author : Mhmd Hammoud
|
|
5
|
+
Date : 2023-06-17
|
|
6
|
+
Description : String manipulation
|
|
7
|
+
Version : 1.0
|
|
8
|
+
*/
|
|
9
|
+
class Formatter {
|
|
10
|
+
constructor() {
|
|
11
|
+
/**
|
|
12
|
+
* @remarks Normalizes input by removing underscores and hyphens and capitalizing the first letter of the sentence.
|
|
13
|
+
* @param stringToBeChanged - to be formatted without underscores and hyphens
|
|
14
|
+
* @param withWhiteSpacing - Determines if white spacing is needed in the final string or not (default: true)
|
|
15
|
+
* @returns string
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* formatter.toUpperFirst('hello world')
|
|
19
|
+
* // => 'Hello-World'
|
|
20
|
+
* ```
|
|
21
|
+
* */
|
|
22
|
+
this.toUpperFirst = (_, withSpacing = true) => {
|
|
23
|
+
if (typeof _ !== 'string')
|
|
24
|
+
throw new Error('Provide a valid string');
|
|
25
|
+
if (withSpacing) {
|
|
26
|
+
return _.split(' ')
|
|
27
|
+
.map((val) => val.charAt(0).toUpperCase() + val.slice(1))
|
|
28
|
+
.join(' ')
|
|
29
|
+
.replace(/ /g, '-')
|
|
30
|
+
.replace(/\//g, '-')
|
|
31
|
+
.replace(/\./g, '');
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return _.split(' ')
|
|
35
|
+
.map((val) => val.charAt(0).toUpperCase() + val.slice(1))
|
|
36
|
+
.join(' ')
|
|
37
|
+
.replace(/\//g, '-')
|
|
38
|
+
.replace(/\./g, '');
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* @remarks normalizes input to supported path and file name format.
|
|
43
|
+
* Changes camelCase strings to kebab-case, replaces spaces with dash and keeps underscores. *
|
|
44
|
+
* @param str - String needed to be modified
|
|
45
|
+
* @returns formatted string
|
|
46
|
+
*/
|
|
47
|
+
this.camelToKebab = (str) => {
|
|
48
|
+
const STRING_DASHERIZE_REGEXP = /\s/g;
|
|
49
|
+
const STRING_DECAMELIZE_REGEXP = /([a-z\d])([A-Z])/g;
|
|
50
|
+
return str
|
|
51
|
+
.replace(STRING_DECAMELIZE_REGEXP, '$1-$2')
|
|
52
|
+
.toLowerCase()
|
|
53
|
+
.replace(STRING_DASHERIZE_REGEXP, '-');
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* @remarks obfuscates email address
|
|
57
|
+
* @param email - email address to be obfuscated
|
|
58
|
+
* @returns obfuscated email address
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* formatter.obfuscate('johndoe@email.com') // => jo*****@gmail.com
|
|
62
|
+
* ```
|
|
63
|
+
* */
|
|
64
|
+
this.obfuscate = (email) => {
|
|
65
|
+
if (typeof email !== 'string')
|
|
66
|
+
throw new Error('Provide a valid string');
|
|
67
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
68
|
+
if (!emailRegex.test(email))
|
|
69
|
+
throw new Error('Provide a valid email address');
|
|
70
|
+
const separatorIndex = email.indexOf('@');
|
|
71
|
+
if (separatorIndex < 3) {
|
|
72
|
+
// 'ab@gmail.com' -> '**@gmail.com'
|
|
73
|
+
return (email.slice(0, separatorIndex).replace(/./g, '*') +
|
|
74
|
+
email.slice(separatorIndex));
|
|
75
|
+
}
|
|
76
|
+
// 'test42@gmail.com' -> 'te****@gmail.com'
|
|
77
|
+
return (email.slice(0, 2) +
|
|
78
|
+
email.slice(2, separatorIndex).replace(/./g, '*') +
|
|
79
|
+
email.slice(separatorIndex));
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* @remarks Generates a slug from a given string
|
|
83
|
+
* @param title - string to be converted to slug
|
|
84
|
+
* @returns slug
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* formatter.slugify('Hello World') // => hello-world
|
|
88
|
+
* ```
|
|
89
|
+
* */
|
|
90
|
+
this.slugify = (title) => {
|
|
91
|
+
if (typeof title !== 'string')
|
|
92
|
+
throw new Error('Provide a valid string');
|
|
93
|
+
return title
|
|
94
|
+
.replace(/ /g, '-')
|
|
95
|
+
.replace(/%/g, '-')
|
|
96
|
+
.replace(/#/g, '-')
|
|
97
|
+
.replace(/\?/g, '-')
|
|
98
|
+
.replace(/,/g, '-')
|
|
99
|
+
.replace(/\//g, '-')
|
|
100
|
+
.replace(/\\/g, '-')
|
|
101
|
+
.replace(/\./g, '')
|
|
102
|
+
.replace(/'/g, '')
|
|
103
|
+
.replace(/"/g, '')
|
|
104
|
+
.replace(/\+/g, '-')
|
|
105
|
+
.replace(/\*/g, '-')
|
|
106
|
+
.replace(/\^/g, '-')
|
|
107
|
+
.replace(/@/g, '-')
|
|
108
|
+
.replace(/;/g, '-')
|
|
109
|
+
.replace(/:/g, '-')
|
|
110
|
+
.replace(/!/g, '-')
|
|
111
|
+
.replace(/&/g, '-')
|
|
112
|
+
.replace(/\$/g, '-')
|
|
113
|
+
.replace(/\(/g, '-')
|
|
114
|
+
.replace(/\)/g, '-')
|
|
115
|
+
.trim()
|
|
116
|
+
.toLowerCase();
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const formatter = new Formatter();
|
|
121
|
+
exports.default = formatter;
|
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.js
CHANGED
|
@@ -3,6 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Crypto = void 0;
|
|
6
|
+
exports.Formatter = exports.Crypto = void 0;
|
|
7
7
|
var cypto_1 = require("./cypto");
|
|
8
8
|
Object.defineProperty(exports, "Crypto", { enumerable: true, get: function () { return __importDefault(cypto_1).default; } });
|
|
9
|
+
var formatter_1 = require("./formatter");
|
|
10
|
+
Object.defineProperty(exports, "Formatter", { enumerable: true, get: function () { return __importDefault(formatter_1).default; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mhmdhammoud/meritt-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"private": false,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"types": "tsc --noemit",
|
|
20
20
|
"prepare": "husky install",
|
|
21
21
|
"lint": "eslint src --fix",
|
|
22
|
-
"prepublish": "
|
|
22
|
+
"prepublish": "npm run build"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"dotenv": "^10.0.0"
|
package/src/index.ts
CHANGED
package/src/lib/cypto.ts
CHANGED
|
@@ -1,35 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* ```
|
|
8
|
-
* */
|
|
1
|
+
/*
|
|
2
|
+
Author : Omar Sawwas
|
|
3
|
+
Date : 2023-06-17
|
|
4
|
+
Description : RSA algorithm
|
|
5
|
+
Version : 1.0
|
|
6
|
+
*/
|
|
9
7
|
class Crypto {
|
|
10
8
|
// Default variables
|
|
11
9
|
private _primeNumberP = 17
|
|
12
10
|
private _primeNumberQ = 19
|
|
11
|
+
private _phiN = (this._primeNumberP - 1) * (this._primeNumberQ - 1)
|
|
13
12
|
private _moduloDenominator = this._primeNumberP * this._primeNumberQ
|
|
14
13
|
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @param number - The number to check if prime
|
|
17
|
+
* @returns The boolean answer of prime checking operation
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* this._isPrime(5)
|
|
21
|
+
* ```
|
|
22
|
+
* */
|
|
23
|
+
|
|
24
|
+
private _isPrime = (number: number): boolean => {
|
|
25
|
+
if (number <= 1) {
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (number <= 3) {
|
|
30
|
+
return true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (number % 2 === 0 || number % 3 === 0) {
|
|
34
|
+
return false
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (let i = 5; i * i <= number; i += 6) {
|
|
38
|
+
if (number % i === 0 || number % (i + 2) === 0) {
|
|
39
|
+
return false
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
45
|
+
|
|
15
46
|
/**
|
|
16
47
|
* Set the P prime number for the RSA algorithm
|
|
17
|
-
* @param
|
|
18
|
-
* @
|
|
48
|
+
* @param primeP - The prime number P of type string
|
|
49
|
+
* @returns void
|
|
19
50
|
* @example
|
|
20
51
|
* ```typescript
|
|
21
52
|
* crypto.setPrimeP(17)
|
|
22
53
|
* ```
|
|
23
54
|
* */
|
|
55
|
+
|
|
24
56
|
public setPrimeP(primeP: number) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (primeP % i === 0) {
|
|
28
|
-
isPrime = false
|
|
29
|
-
break
|
|
30
|
-
}
|
|
57
|
+
if (isNaN(primeP) || primeP === 0) {
|
|
58
|
+
throw new Error('Provide a valid number')
|
|
31
59
|
}
|
|
32
|
-
|
|
60
|
+
|
|
61
|
+
if (!this._isPrime(primeP)) {
|
|
33
62
|
throw new Error('The number is not prime')
|
|
34
63
|
}
|
|
35
64
|
this._primeNumberP = primeP
|
|
@@ -37,22 +66,19 @@ class Crypto {
|
|
|
37
66
|
|
|
38
67
|
/**
|
|
39
68
|
* Set the Q prime number for the RSA algorithm
|
|
40
|
-
* @param
|
|
41
|
-
* @
|
|
69
|
+
* @param primeQ - The prime number Q of type string
|
|
70
|
+
* @returns void
|
|
42
71
|
* @example
|
|
43
72
|
* ```typescript
|
|
44
73
|
* crypto.setPrimeQ(19)
|
|
45
74
|
* ```
|
|
46
75
|
* */
|
|
76
|
+
|
|
47
77
|
public setPrimeQ(primeQ: number) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (primeQ % i === 0) {
|
|
51
|
-
isPrime = false
|
|
52
|
-
break
|
|
53
|
-
}
|
|
78
|
+
if (isNaN(primeQ) || primeQ === 0) {
|
|
79
|
+
throw new Error('Provide a valid number')
|
|
54
80
|
}
|
|
55
|
-
if (!
|
|
81
|
+
if (!this._isPrime(primeQ)) {
|
|
56
82
|
throw new Error('The number is not prime')
|
|
57
83
|
}
|
|
58
84
|
this._primeNumberQ = primeQ
|
|
@@ -60,15 +86,19 @@ class Crypto {
|
|
|
60
86
|
|
|
61
87
|
/**
|
|
62
88
|
*
|
|
63
|
-
* @param
|
|
64
|
-
* @param
|
|
65
|
-
* @
|
|
89
|
+
* @param base - The base number of type number
|
|
90
|
+
* @param exponent - The exponent number of type number
|
|
91
|
+
* @returns The modular exponentiation of the base and the exponent
|
|
66
92
|
* @example
|
|
67
93
|
* ```typescript
|
|
68
94
|
* this.modularExponentiation(2, 3)
|
|
69
95
|
* ```
|
|
70
96
|
* */
|
|
97
|
+
|
|
71
98
|
private _modularExponentiation = (base: number, exponent: number) => {
|
|
99
|
+
if (isNaN(base) || isNaN(exponent)) {
|
|
100
|
+
throw new Error('Provide a valid number')
|
|
101
|
+
}
|
|
72
102
|
if (this._moduloDenominator === 1) {
|
|
73
103
|
return 0
|
|
74
104
|
}
|
|
@@ -84,36 +114,172 @@ class Crypto {
|
|
|
84
114
|
return result
|
|
85
115
|
}
|
|
86
116
|
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
* @param temporaryVarriableOne - The number one
|
|
120
|
+
* @param temporaryVarriableTwo- The number two (phi n)
|
|
121
|
+
* @returns The boolean answer of relatively prime checking operation with phi n
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* this._areRelativelyPrime(5,9)
|
|
125
|
+
* ```
|
|
126
|
+
* */
|
|
127
|
+
|
|
128
|
+
private _areRelativelyPrime = (
|
|
129
|
+
temporaryVarriableOne: number,
|
|
130
|
+
temporaryVarriableTwo: number
|
|
131
|
+
) => {
|
|
132
|
+
while (temporaryVarriableTwo !== 0) {
|
|
133
|
+
const temp = temporaryVarriableTwo
|
|
134
|
+
temporaryVarriableTwo = temporaryVarriableOne % temporaryVarriableTwo
|
|
135
|
+
temporaryVarriableOne = temp
|
|
136
|
+
}
|
|
137
|
+
return temporaryVarriableOne === 1
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
*
|
|
142
|
+
* @returns The public and private key number which is a random number generated to match conditions set by RSA algorithm
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* crypto.generateKeys()
|
|
146
|
+
* ```
|
|
147
|
+
* */
|
|
148
|
+
|
|
149
|
+
public generateKeys = (): Record<'publicKey' | 'privateKey', number> => {
|
|
150
|
+
const temporaryArray: number[] = []
|
|
151
|
+
for (let i = 2; i < this._phiN; i++) {
|
|
152
|
+
if (this._areRelativelyPrime(i, this._phiN)) {
|
|
153
|
+
temporaryArray.push(i)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (temporaryArray.length === 0)
|
|
157
|
+
throw new Error('No public key options found!')
|
|
158
|
+
const randomIndex = Math.floor(Math.random() * temporaryArray.length)
|
|
159
|
+
// return temporaryArray[randomIndex]
|
|
160
|
+
const publicKey = temporaryArray[randomIndex]
|
|
161
|
+
const privateKey = this._generatePrivateKey(publicKey)
|
|
162
|
+
if (privateKey === publicKey) {
|
|
163
|
+
return this.generateKeys()
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
privateKey: publicKey,
|
|
167
|
+
publicKey: privateKey,
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
*
|
|
173
|
+
* @param publicKey - The public key number
|
|
174
|
+
* @returns The private key number which is the modulus inverse with repect to modulo denominator
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* crypto.generatePrivateKey(5)
|
|
178
|
+
* ```
|
|
179
|
+
* */
|
|
180
|
+
|
|
181
|
+
private _generatePrivateKey = (publicKey: number): number => {
|
|
182
|
+
if (publicKey <= 1 || isNaN(publicKey)) {
|
|
183
|
+
throw new Error('Public key should be a number greater than 1')
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!this._areRelativelyPrime(publicKey, this._phiN)) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
'Public key should be relatively prime with respect to phi N'
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let t1 = 0
|
|
193
|
+
let t2 = 1
|
|
194
|
+
let r1 = this._phiN
|
|
195
|
+
let r2 = publicKey
|
|
196
|
+
|
|
197
|
+
while (r2 !== 0) {
|
|
198
|
+
const quotient = Math.floor(r1 / r2)
|
|
199
|
+
const temp1 = t1
|
|
200
|
+
const temp2 = r1
|
|
201
|
+
|
|
202
|
+
t1 = t2
|
|
203
|
+
r1 = r2
|
|
204
|
+
|
|
205
|
+
t2 = temp1 - quotient * t2
|
|
206
|
+
r2 = temp2 - quotient * r2
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (r1 > 1) {
|
|
210
|
+
throw new Error('The number does not have a modular inverse.')
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (t1 < 0) {
|
|
214
|
+
t1 += this._phiN
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return t1
|
|
218
|
+
}
|
|
219
|
+
|
|
87
220
|
/**
|
|
88
221
|
* Encrypt the message using the public key
|
|
89
|
-
* @param
|
|
90
|
-
* @param
|
|
91
|
-
* @
|
|
222
|
+
* @param message - The message to encrypt of type string|number|Record
|
|
223
|
+
* @param publicKey - The public key to encrypt the message with of type number
|
|
224
|
+
* @returns The encrypted message of type number[]
|
|
92
225
|
* @example
|
|
93
226
|
* ```typescript
|
|
94
227
|
* crypto.encrypt('Hello World', 7)
|
|
95
228
|
* ```
|
|
96
229
|
* */
|
|
97
|
-
|
|
98
|
-
|
|
230
|
+
|
|
231
|
+
public encrypt = (
|
|
232
|
+
message: string | number | Record<any, any>,
|
|
233
|
+
publicKey: number
|
|
234
|
+
): number[] => {
|
|
235
|
+
if (isNaN(publicKey)) {
|
|
236
|
+
throw new Error('Public key should be a number')
|
|
237
|
+
}
|
|
238
|
+
if (publicKey <= 0) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
'Private key should be a positive number different than 0'
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
if (typeof message === 'number') {
|
|
244
|
+
message = message.toString()
|
|
245
|
+
}
|
|
246
|
+
if (typeof message === 'object') {
|
|
247
|
+
message = JSON.stringify(message)
|
|
248
|
+
}
|
|
249
|
+
const encryptedMessage: number[] = []
|
|
99
250
|
for (let i = 0; i < message.length; i++) {
|
|
100
251
|
const a = message.charCodeAt(i)
|
|
101
|
-
|
|
252
|
+
encryptedMessage.push(this._modularExponentiation(a, publicKey))
|
|
102
253
|
}
|
|
103
|
-
return
|
|
254
|
+
return encryptedMessage
|
|
104
255
|
}
|
|
105
256
|
|
|
106
257
|
/**
|
|
107
258
|
* Decrypt the message using the private key
|
|
108
|
-
* @param
|
|
109
|
-
* @param
|
|
110
|
-
* @
|
|
259
|
+
* @param encryptedMessage - The encryptedMessage to decrypt of type number[]
|
|
260
|
+
* @param privateKey - The private key to decrypt the message with of type number
|
|
261
|
+
* @returns The decrypted message of type string
|
|
111
262
|
* @example
|
|
112
263
|
* ```typescript
|
|
113
264
|
* crypto.decrypt([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100], 23)
|
|
114
265
|
* ```
|
|
115
266
|
* */
|
|
116
267
|
public decrypt = (encryptedMessage: number[], privateKey: number): string => {
|
|
268
|
+
if (isNaN(privateKey)) {
|
|
269
|
+
throw new Error('Public key should be a number')
|
|
270
|
+
}
|
|
271
|
+
if (privateKey <= 0) {
|
|
272
|
+
throw new Error(
|
|
273
|
+
'Private key should be a positive number different than 0'
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
if (!Array.isArray(encryptedMessage)) {
|
|
277
|
+
throw new Error('Encrypted message should be an array')
|
|
278
|
+
}
|
|
279
|
+
const allValidNumbers = encryptedMessage.every((number) => !isNaN(number))
|
|
280
|
+
if (!allValidNumbers) {
|
|
281
|
+
throw new Error('Encrypted message should be an array of numbers')
|
|
282
|
+
}
|
|
117
283
|
const decryptedAsciiMessage: number[] = []
|
|
118
284
|
for (let i = 0; i < encryptedMessage.length; i++) {
|
|
119
285
|
const a = encryptedMessage[i]
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Author : Mhmd Hammoud
|
|
3
|
+
Date : 2023-06-17
|
|
4
|
+
Description : String manipulation
|
|
5
|
+
Version : 1.0
|
|
6
|
+
*/
|
|
7
|
+
class Formatter {
|
|
8
|
+
/**
|
|
9
|
+
* @remarks Normalizes input by removing underscores and hyphens and capitalizing the first letter of the sentence.
|
|
10
|
+
* @param stringToBeChanged - to be formatted without underscores and hyphens
|
|
11
|
+
* @param withWhiteSpacing - Determines if white spacing is needed in the final string or not (default: true)
|
|
12
|
+
* @returns string
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* formatter.toUpperFirst('hello world')
|
|
16
|
+
* // => 'Hello-World'
|
|
17
|
+
* ```
|
|
18
|
+
* */
|
|
19
|
+
toUpperFirst = (_: string | number, withSpacing = true) => {
|
|
20
|
+
if (typeof _ !== 'string') throw new Error('Provide a valid string')
|
|
21
|
+
if (withSpacing) {
|
|
22
|
+
return _.split(' ')
|
|
23
|
+
.map((val: string) => val.charAt(0).toUpperCase() + val.slice(1))
|
|
24
|
+
.join(' ')
|
|
25
|
+
.replace(/ /g, '-')
|
|
26
|
+
.replace(/\//g, '-')
|
|
27
|
+
.replace(/\./g, '')
|
|
28
|
+
} else {
|
|
29
|
+
return _.split(' ')
|
|
30
|
+
.map((val: string) => val.charAt(0).toUpperCase() + val.slice(1))
|
|
31
|
+
.join(' ')
|
|
32
|
+
.replace(/\//g, '-')
|
|
33
|
+
.replace(/\./g, '')
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @remarks normalizes input to supported path and file name format.
|
|
39
|
+
* Changes camelCase strings to kebab-case, replaces spaces with dash and keeps underscores. *
|
|
40
|
+
* @param str - String needed to be modified
|
|
41
|
+
* @returns formatted string
|
|
42
|
+
*/
|
|
43
|
+
camelToKebab = (str: string) => {
|
|
44
|
+
const STRING_DASHERIZE_REGEXP = /\s/g
|
|
45
|
+
const STRING_DECAMELIZE_REGEXP = /([a-z\d])([A-Z])/g
|
|
46
|
+
return str
|
|
47
|
+
.replace(STRING_DECAMELIZE_REGEXP, '$1-$2')
|
|
48
|
+
.toLowerCase()
|
|
49
|
+
.replace(STRING_DASHERIZE_REGEXP, '-')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @remarks obfuscates email address
|
|
54
|
+
* @param email - email address to be obfuscated
|
|
55
|
+
* @returns obfuscated email address
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* formatter.obfuscate('johndoe@email.com') // => jo*****@gmail.com
|
|
59
|
+
* ```
|
|
60
|
+
* */
|
|
61
|
+
obfuscate = (email: string) => {
|
|
62
|
+
if (typeof email !== 'string') throw new Error('Provide a valid string')
|
|
63
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
64
|
+
if (!emailRegex.test(email))
|
|
65
|
+
throw new Error('Provide a valid email address')
|
|
66
|
+
const separatorIndex = email.indexOf('@')
|
|
67
|
+
if (separatorIndex < 3) {
|
|
68
|
+
// 'ab@gmail.com' -> '**@gmail.com'
|
|
69
|
+
return (
|
|
70
|
+
email.slice(0, separatorIndex).replace(/./g, '*') +
|
|
71
|
+
email.slice(separatorIndex)
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
// 'test42@gmail.com' -> 'te****@gmail.com'
|
|
75
|
+
return (
|
|
76
|
+
email.slice(0, 2) +
|
|
77
|
+
email.slice(2, separatorIndex).replace(/./g, '*') +
|
|
78
|
+
email.slice(separatorIndex)
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @remarks Generates a slug from a given string
|
|
84
|
+
* @param title - string to be converted to slug
|
|
85
|
+
* @returns slug
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* formatter.slugify('Hello World') // => hello-world
|
|
89
|
+
* ```
|
|
90
|
+
* */
|
|
91
|
+
slugify = (title: string) => {
|
|
92
|
+
if (typeof title !== 'string') throw new Error('Provide a valid string')
|
|
93
|
+
return title
|
|
94
|
+
.replace(/ /g, '-')
|
|
95
|
+
.replace(/%/g, '-')
|
|
96
|
+
.replace(/#/g, '-')
|
|
97
|
+
.replace(/\?/g, '-')
|
|
98
|
+
.replace(/,/g, '-')
|
|
99
|
+
.replace(/\//g, '-')
|
|
100
|
+
.replace(/\\/g, '-')
|
|
101
|
+
.replace(/\./g, '')
|
|
102
|
+
.replace(/'/g, '')
|
|
103
|
+
.replace(/"/g, '')
|
|
104
|
+
.replace(/\+/g, '-')
|
|
105
|
+
.replace(/\*/g, '-')
|
|
106
|
+
.replace(/\^/g, '-')
|
|
107
|
+
.replace(/@/g, '-')
|
|
108
|
+
.replace(/;/g, '-')
|
|
109
|
+
.replace(/:/g, '-')
|
|
110
|
+
.replace(/!/g, '-')
|
|
111
|
+
.replace(/&/g, '-')
|
|
112
|
+
.replace(/\$/g, '-')
|
|
113
|
+
.replace(/\(/g, '-')
|
|
114
|
+
.replace(/\)/g, '-')
|
|
115
|
+
.trim()
|
|
116
|
+
.toLowerCase()
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const formatter = new Formatter()
|
|
121
|
+
export default formatter
|
package/src/lib/index.ts
CHANGED