@mhmdhammoud/meritt-utils 1.0.3 → 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.
@@ -26,3 +26,18 @@ jobs:
26
26
  - run: npm publish
27
27
  env:
28
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
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
+ [![Changes](https://github.com/Mhmdhammoud/meritt-utils/actions/workflows/push.yml/badge.svg)](https://github.com/Mhmdhammoud/meritt-utils/actions/workflows/push.yml) [![NPM Publish on Release](https://github.com/Mhmdhammoud/meritt-utils/actions/workflows/npm-publish.yml/badge.svg)](https://github.com/Mhmdhammoud/meritt-utils/actions/workflows/npm-publish.yml)
8
+
5
9
  ## Installation
6
10
 
7
11
  For npm:
package/ReleaseNotes.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changes
2
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
+
3
28
  ## Version 1.0.3
4
29
 
5
30
  ### Added
@@ -1,7 +1,18 @@
1
1
  declare class Crypto {
2
2
  private _primeNumberP;
3
3
  private _primeNumberQ;
4
+ private _phiN;
4
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;
5
16
  /**
6
17
  * Set the P prime number for the RSA algorithm
7
18
  * @param primeP - The prime number P of type string
@@ -33,6 +44,36 @@ declare class Crypto {
33
44
  * ```
34
45
  * */
35
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;
36
77
  /**
37
78
  * Encrypt the message using the public key
38
79
  * @param message - The message to encrypt of type string|number|Record
package/dist/lib/cypto.js CHANGED
@@ -11,7 +11,34 @@ class Crypto {
11
11
  // Default variables
12
12
  this._primeNumberP = 17;
13
13
  this._primeNumberQ = 19;
14
+ this._phiN = (this._primeNumberP - 1) * (this._primeNumberQ - 1);
14
15
  this._moduloDenominator = this._primeNumberP * this._primeNumberQ;
16
+ /**
17
+ *
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
+ };
15
42
  /**
16
43
  *
17
44
  * @param base - The base number of type number
@@ -40,6 +67,90 @@ class Crypto {
40
67
  }
41
68
  return result;
42
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
+ };
43
154
  /**
44
155
  * Encrypt the message using the public key
45
156
  * @param message - The message to encrypt of type string|number|Record
@@ -54,6 +165,9 @@ class Crypto {
54
165
  if (isNaN(publicKey)) {
55
166
  throw new Error('Public key should be a number');
56
167
  }
168
+ if (publicKey <= 0) {
169
+ throw new Error('Private key should be a positive number different than 0');
170
+ }
57
171
  if (typeof message === 'number') {
58
172
  message = message.toString();
59
173
  }
@@ -79,7 +193,10 @@ class Crypto {
79
193
  * */
80
194
  this.decrypt = (encryptedMessage, privateKey) => {
81
195
  if (isNaN(privateKey)) {
82
- throw new Error('Private key should be a number');
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');
83
200
  }
84
201
  if (!Array.isArray(encryptedMessage)) {
85
202
  throw new Error('Encrypted message should be an array');
@@ -110,17 +227,10 @@ class Crypto {
110
227
  * ```
111
228
  * */
112
229
  setPrimeP(primeP) {
113
- if (isNaN(primeP)) {
230
+ if (isNaN(primeP) || primeP === 0) {
114
231
  throw new Error('Provide a valid number');
115
232
  }
116
- let isPrime = true;
117
- for (let i = 2; i < primeP; i++) {
118
- if (primeP % i === 0) {
119
- isPrime = false;
120
- break;
121
- }
122
- }
123
- if (!isPrime) {
233
+ if (!this._isPrime(primeP)) {
124
234
  throw new Error('The number is not prime');
125
235
  }
126
236
  this._primeNumberP = primeP;
@@ -135,17 +245,10 @@ class Crypto {
135
245
  * ```
136
246
  * */
137
247
  setPrimeQ(primeQ) {
138
- if (isNaN(primeQ)) {
248
+ if (isNaN(primeQ) || primeQ === 0) {
139
249
  throw new Error('Provide a valid number');
140
250
  }
141
- let isPrime = true;
142
- for (let i = 2; i < primeQ; i++) {
143
- if (primeQ % i === 0) {
144
- isPrime = false;
145
- break;
146
- }
147
- }
148
- if (!isPrime) {
251
+ if (!this._isPrime(primeQ)) {
149
252
  throw new Error('The number is not prime');
150
253
  }
151
254
  this._primeNumberQ = primeQ;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mhmdhammoud/meritt-utils",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "private": false,
package/src/lib/cypto.ts CHANGED
@@ -8,8 +8,41 @@ class Crypto {
8
8
  // Default variables
9
9
  private _primeNumberP = 17
10
10
  private _primeNumberQ = 19
11
+ private _phiN = (this._primeNumberP - 1) * (this._primeNumberQ - 1)
11
12
  private _moduloDenominator = this._primeNumberP * this._primeNumberQ
12
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
+
13
46
  /**
14
47
  * Set the P prime number for the RSA algorithm
15
48
  * @param primeP - The prime number P of type string
@@ -19,18 +52,13 @@ class Crypto {
19
52
  * crypto.setPrimeP(17)
20
53
  * ```
21
54
  * */
55
+
22
56
  public setPrimeP(primeP: number) {
23
- if (isNaN(primeP)) {
57
+ if (isNaN(primeP) || primeP === 0) {
24
58
  throw new Error('Provide a valid number')
25
59
  }
26
- let isPrime = true
27
- for (let i = 2; i < primeP; i++) {
28
- if (primeP % i === 0) {
29
- isPrime = false
30
- break
31
- }
32
- }
33
- if (!isPrime) {
60
+
61
+ if (!this._isPrime(primeP)) {
34
62
  throw new Error('The number is not prime')
35
63
  }
36
64
  this._primeNumberP = primeP
@@ -45,18 +73,12 @@ class Crypto {
45
73
  * crypto.setPrimeQ(19)
46
74
  * ```
47
75
  * */
76
+
48
77
  public setPrimeQ(primeQ: number) {
49
- if (isNaN(primeQ)) {
78
+ if (isNaN(primeQ) || primeQ === 0) {
50
79
  throw new Error('Provide a valid number')
51
80
  }
52
- let isPrime = true
53
- for (let i = 2; i < primeQ; i++) {
54
- if (primeQ % i === 0) {
55
- isPrime = false
56
- break
57
- }
58
- }
59
- if (!isPrime) {
81
+ if (!this._isPrime(primeQ)) {
60
82
  throw new Error('The number is not prime')
61
83
  }
62
84
  this._primeNumberQ = primeQ
@@ -72,6 +94,7 @@ class Crypto {
72
94
  * this.modularExponentiation(2, 3)
73
95
  * ```
74
96
  * */
97
+
75
98
  private _modularExponentiation = (base: number, exponent: number) => {
76
99
  if (isNaN(base) || isNaN(exponent)) {
77
100
  throw new Error('Provide a valid number')
@@ -91,6 +114,109 @@ class Crypto {
91
114
  return result
92
115
  }
93
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
+
94
220
  /**
95
221
  * Encrypt the message using the public key
96
222
  * @param message - The message to encrypt of type string|number|Record
@@ -101,6 +227,7 @@ class Crypto {
101
227
  * crypto.encrypt('Hello World', 7)
102
228
  * ```
103
229
  * */
230
+
104
231
  public encrypt = (
105
232
  message: string | number | Record<any, any>,
106
233
  publicKey: number
@@ -108,6 +235,11 @@ class Crypto {
108
235
  if (isNaN(publicKey)) {
109
236
  throw new Error('Public key should be a number')
110
237
  }
238
+ if (publicKey <= 0) {
239
+ throw new Error(
240
+ 'Private key should be a positive number different than 0'
241
+ )
242
+ }
111
243
  if (typeof message === 'number') {
112
244
  message = message.toString()
113
245
  }
@@ -134,7 +266,12 @@ class Crypto {
134
266
  * */
135
267
  public decrypt = (encryptedMessage: number[], privateKey: number): string => {
136
268
  if (isNaN(privateKey)) {
137
- throw new Error('Private key should be a number')
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
+ )
138
275
  }
139
276
  if (!Array.isArray(encryptedMessage)) {
140
277
  throw new Error('Encrypted message should be an array')