ncrypt-js 2.1.1 → 2.2.0

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
@@ -1,8 +1,9 @@
1
1
  # NcryptJs
2
2
 
3
- [![Build Status](https://travis-ci.com/ajimae/ncrypt-js.svg?branch=master)](https://travis-ci.com/ajimae/ncrypt-js) [![Coverage Status](https://coveralls.io/repos/github/ajimae/ncrypt-js/badge.svg)](https://coveralls.io/github/ajimae/ncrypt-js) [![NPM](https://img.shields.io/npm/l/ncrypt-js)](https://www.npmjs.com/package/ncrypt-js/v/2.0.0#license)
3
+ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ajimae/ncrypt-js/.github%2Fworkflows%2Fci.yml)
4
+ [![Coverage Status](https://coveralls.io/repos/github/ajimae/ncrypt-js/badge.svg)](https://coveralls.io/github/ajimae/ncrypt-js) ![NPM Downloads](https://img.shields.io/npm/dw/ncrypt-js)
4
5
 
5
- [![GitHub release (latest by date)](https://img.shields.io/github/v/release/ajimae/ncrypt-js)](https://github.com/ajimae/ncrypt-js/releases) [![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/ajimae/ncrypt-js)](https://github/languages/code-size/ajimae/ncrypt-js) [![GitHub issues](https://img.shields.io/github/issues/ajimae/ncrypt-js)](https://github.com/ajimae/ncrypt-js/issues)
6
+ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/ajimae/ncrypt-js)](https://github.com/ajimae/ncrypt-js/releases) [![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/ajimae/ncrypt-js)](https://github/languages/code-size/ajimae/ncrypt-js) [![GitHub issues](https://img.shields.io/github/issues/ajimae/ncrypt-js)](https://github.com/ajimae/ncrypt-js/issues) [![NPM](https://img.shields.io/npm/l/ncrypt-js)](https://www.npmjs.com/package/ncrypt-js/v/2.0.0#license)
6
7
 
7
8
  **_NcryptJs_** is a light weight javascript data encryption and decryption library. This library implements the nodejs default crypto functionality as a mid-channel cipher in addition to a simple and elegant custom data encoding and encryption algorithm.
8
9
 
@@ -16,8 +17,9 @@
16
17
  * [NcryptJs Methods](#ncryptjs-methods)
17
18
  * [Using the `randomString()` methods](#using-randomstring-method)
18
19
  * [Using `encrypt()` and `decrypt()` methods](#using-encrypt-and-decrypt-methods)
19
- * [Stirng Encryption](#string-encryption)
20
+ * [String Encryption](#string-encryption)
20
21
  * [Object Encryption](#object-encryption)
22
+ * [Using password hashing methods](#using-password-hashing-methods)
21
23
  * [Built With](#built-with)
22
24
  * [Contribution](#contribution)
23
25
  * [Version Management](#version-management)
@@ -79,13 +81,16 @@ var { ncrypt } = require("ncrypt-js");
79
81
  | Methods | Description | Parameters | Return |
80
82
  | ------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
81
83
  | [_static_] **randomString()** | Random String. |**size**: _number_ - An optional size of the generated `randomBytes`. <br/>**enc:** _base64/hex_ - Encoding used for encoding the `randomBytes` defaults to _`base64`_ |**encoded**: _string_ - encoded string. |
84
+ | [_static_] **generate()** | Generates a hashed password. |**password**: _string_ - The password to hash. <br/>**options**: _object_ - Optional configuration object (see below). |**hashedPassword**: _string_ - The hashed password string. |
85
+ | [_static_] **verify()** | Verifies a password against a hashed password. | **password**: _string_ - The password to verify. <br/>**hashedPassword**: _string_ - The hashed password to verify against. <br/>**options**: _object_ - Optional configuration object (see below). | **boolean** - Returns `true` if the password matches the hash, `false` otherwise.
86
+ | [_static_] **isHashed()** | Checks if a string is a hashed password. | **password**: _string_ - The string to check. <br/>**options**: _object_ - Optional configuration object (see below). | **boolean** - Returns `true` if the string appears to be a hashed password, `false` otherwise.
82
87
  | **encrypt()** | Encrypts data. |**data**: _object/string/number/boolean_ - The data to be encrypted. <br/>|**ciphered**: _string_ - encrypted data. |
83
88
  | **decrypt()** | Decrypts the encrypted or ciphered data | **encodedData**: string - The encrypted data: _string_ to be decrypted. | **data**: _string/object/number/boolean_ - The decrypted or original data (it might be string or object, depends on the initial input data type).
84
89
 
85
90
 
86
91
  ### Using randomString method
87
92
 
88
- The `randomString()` static method can generate [random bytes](https://nodejs.org/api/crypto.html#cryptorandombytessize-callback) encoded into a `hexadecimal` or `base64` strings. This string can be useful in a variety of use cases e.g to generate database ids, to generate a unique string for a list, a unique serial strings etc.
93
+ The `randomString()` static method can generate [random bytes](https://nodejs.org/api/crypto.html#cryptorandombytessize-callback) encoded into a `hexadecimal` or `base64` strings. This string can be useful in a variety of use cases e.g to generate database ids, to generate a unique string for a list, a unique serial strings, api keys etc.
89
94
 
90
95
  ```ts
91
96
  var { ncrypt } = require('ncrypt-js'); // or import ncrypt from 'ncrypt-js'
@@ -120,7 +125,7 @@ console.log("Encryption process...");
120
125
  console.log("Plain Text : " + data);
121
126
  console.log("Cipher Text : " + encryptedData);
122
127
 
123
- // decrypted super encrypted string here
128
+ // decrypting the encrypted super sensitive data here
124
129
  var decryptedData = decrypt(encryptedData);
125
130
  console.log("... and then decryption...");
126
131
  console.log("Decipher Text : " + decryptedData);
@@ -189,7 +194,7 @@ If you are using any sort of environmental key-value store, e.g `.env` and for a
189
194
  KEY='sshhhh this is a super secret key'
190
195
 
191
196
  # used internally to set the `encoding` - ['base64' | 'binary' | 'hex' | 'ucs-2' | 'ucs2' | 'utf16le']
192
- NCRPT_ENC='hex'
197
+ NCRYPT_ENC='hex'
193
198
 
194
199
  SECRET='this is our hashing secret'
195
200
  ```
@@ -200,7 +205,113 @@ var { ncrypt } = require('ncrypt-js');
200
205
  var { encrypt, decrypt } = new ncrypt(process.env.SECRET);
201
206
  ...
202
207
  ```
203
- _**NOTE:** The secret is required to decrypt the encrypted data, if the secret used to encrypt a specific data is lost, then that data cannot be decripted._
208
+ _**NOTE:** The secret is required to decrypt the encrypted data, if the secret used to encrypt a specific data is lost, then that data cannot be decrypted._
209
+
210
+ _Same goes for encoding, if data was encrypted using `hex` encoding format, decrypting with a `base64` encoding or other encoding format and vise versa will not work_
211
+
212
+ ### Using password hashing methods
213
+
214
+ The `generate()`, `verify()`, and `isHashed()` static methods provide secure password hashing and verification functionality. These methods use HMAC (Hash-based Message Authentication Code) for password hashing.
215
+
216
+ #### Generating a hashed password
217
+
218
+ The `generate()` method creates a secure hash of a password with a randomly generated salt.
219
+
220
+ ```ts
221
+ var { ncrypt } = require('ncrypt-js'); // or import ncrypt from 'ncrypt-js'
222
+
223
+ var password = "mySecurePassword123";
224
+ var hashedPassword = ncrypt.generate(password);
225
+ console.log(hashedPassword); // sha1$abc12345$1$hashedvalue...
226
+
227
+ // signature
228
+ ncrypt.generate(password: string, options?: {
229
+ algorithm?: string; // Hash algorithm (default: 'sha1')
230
+ saltLength?: number; // Salt length in characters (default: 8)
231
+ iterations?: number; // Number of hash iterations (default: 1)
232
+ encoding?: 'hex' | 'base64'; // Encoding format (default: 'hex')
233
+ separator?: string; // Separator character (default: '$')
234
+ });
235
+ ```
236
+
237
+ #### Verifying a password
238
+
239
+ The `verify()` method checks if a plain text password matches a previously hashed password.
240
+
241
+ ```ts
242
+ var { ncrypt } = require('ncrypt-js');
243
+
244
+ var password = "mySecurePassword123";
245
+ var hashedPassword = ncrypt.generate(password);
246
+
247
+ // Later, verify the password
248
+ var isValid = ncrypt.verify(password, hashedPassword);
249
+ console.log(isValid); // true
250
+
251
+ // signature
252
+ ncrypt.verify(password: string, hashedPassword: string, options?: {
253
+ encoding?: 'hex' | 'base64'; // Encoding format (default: 'hex')
254
+ separator?: string; // Separator character (default: '$')
255
+ });
256
+ ```
257
+
258
+ #### Checking if a string is hashed
259
+
260
+ The `isHashed()` method checks if a string appears to be a hashed password by verifying its format.
261
+
262
+ ```ts
263
+ var { ncrypt } = require('ncrypt-js');
264
+
265
+ var hashedPassword = ncrypt.generate("password123");
266
+ var isHashed = ncrypt.isHashed(hashedPassword);
267
+ console.log(isHashed); // true
268
+
269
+ var plainPassword = "password123";
270
+ var isHashed = ncrypt.isHashed(plainPassword);
271
+ console.log(isHashed); // false
272
+
273
+ // signature
274
+ ncrypt.isHashed(password: string, options?: {
275
+ separator?: string; // Separator character (default: '$')
276
+ });
277
+ ```
278
+
279
+ #### Advanced usage with custom options
280
+
281
+ You can customize the hashing algorithm, salt length, iterations, encoding, and separator:
282
+
283
+ ```ts
284
+ var { ncrypt } = require('ncrypt-js');
285
+
286
+ // Generate with custom options
287
+ var hashedPassword = ncrypt.generate("password123", {
288
+ algorithm: "sha256", // Use SHA-256 instead of SHA-1
289
+ saltLength: 16, // Use 16 character salt
290
+ iterations: 1000, // Apply hashing 1000 times
291
+ encoding: "base64", // Use base64 encoding
292
+ separator: "." // Use '.' as separator instead of '$'
293
+ });
294
+
295
+ // Verify with matching options
296
+ var isValid = ncrypt.verify("password123", hashedPassword, {
297
+ encoding: "base64",
298
+ separator: "."
299
+ });
300
+ console.log(isValid); // true
301
+ ```
302
+
303
+ **Available hash algorithms:** Any algorithm supported by Node.js `crypto.createHmac()`, such as `'sha1'`, `'sha256'`, `'sha512'`, `'md5'`, etc.
304
+
305
+ **Note:** The `encoding` and `separator` options must match between `generate()` and `verify()` calls for verification to succeed. To be safe, ensure you create a single options object and use the same object everywhere.
306
+
307
+ ```ts
308
+ const same_options_obj = {
309
+ ...
310
+ }
311
+
312
+ ncrypt.generate("pass", same_options_obj)
313
+ ncrypt.verify("pass", hasedPass, same_options_obj)
314
+ ```
204
315
 
205
316
  ## Built With
206
317
 
@@ -210,7 +321,7 @@ Written in [TypeScript](https://typscriptlang.org/), built into ECMAScript 5 usi
210
321
 
211
322
  To contribute, simply fork this project, and issue a pull request.
212
323
 
213
- ## Version Management
324
+ ## Versioning
214
325
 
215
326
  We use [SemVer](http://semver.org/) for version management. For the versions available, see the [tags on this repository](https://github.com/ajimae/ncrypt-js/tags).
216
327
 
@@ -1,3 +1,10 @@
1
+ declare type THASH_ENC = {
2
+ algorithm?: string;
3
+ saltLength?: number;
4
+ iterations?: number;
5
+ encoding?: "base64" | "hex";
6
+ separator?: string;
7
+ };
1
8
  /**
2
9
  * @class Ncrypt
3
10
  * @type {Ncrypt.<object>}
@@ -20,6 +27,9 @@ export default class Ncrypt {
20
27
  * crypto random initial vector generated from core node {crypto} module
21
28
  */
22
29
  private readonly initialVector;
30
+ /**
31
+ * hashing salt
32
+ */
23
33
  /**
24
34
  * crypto random key generated from core node {crypto} module
25
35
  * {note}: please read the value for KEY from your app's environment
@@ -61,6 +71,47 @@ export default class Ncrypt {
61
71
  * @returns {string.<string>} decrypted data
62
72
  */
63
73
  private decode;
74
+ /**
75
+ *
76
+ * generate salt method
77
+ * @param length
78
+ * @param enc
79
+ * @returns
80
+ */
81
+ private static generateSalt;
82
+ /**
83
+ *
84
+ * generate hash method
85
+ * @param algorithm
86
+ * @param salt
87
+ * @param password
88
+ * @param iterations
89
+ * @param enc
90
+ * @param separator
91
+ * @returns
92
+ */
93
+ private static generateHash;
94
+ /**
95
+ *
96
+ * generate hashed password method
97
+ * @param password
98
+ * @param options
99
+ * @returns
100
+ */
101
+ static generate(password: string, options?: THASH_ENC): string;
102
+ /**
103
+ *
104
+ * verify password method
105
+ */
106
+ static verify(password: string, hashedPassword: string, options?: THASH_ENC): boolean;
107
+ /**
108
+ *
109
+ * isHashed method
110
+ * @param password
111
+ * @param options
112
+ * @returns
113
+ */
114
+ static isHashed(password: string, options?: THASH_ENC): boolean;
64
115
  /**
65
116
  * generate random strings
66
117
  * @example
@@ -74,7 +125,7 @@ export default class Ncrypt {
74
125
  * @param {enc.<string>} enc
75
126
  * @returns {*.<string>} string
76
127
  */
77
- static randomString(size?: number, enc?: 'hex' | 'base64'): string;
128
+ static randomString(size?: number, enc?: "hex" | "base64"): string;
78
129
  /**
79
130
  * data to be encrypted
80
131
  * @param {data.<stirng>} data
@@ -88,3 +139,4 @@ export default class Ncrypt {
88
139
  */
89
140
  decrypt(text: string): string | number | boolean | object;
90
141
  }
142
+ export {};
@@ -21,27 +21,32 @@ class Ncrypt {
21
21
  /**
22
22
  * algorithm used for encoding message
23
23
  */
24
- this.algorithm = 'aes-256-cbc';
24
+ this.algorithm = "aes-256-cbc";
25
25
  /**
26
26
  * ecoding for encrypted stirng
27
27
  */
28
- this.enc = (process.env.NCRYPT_ENC) || 'hex';
28
+ this.enc = process.env.NCRYPT_ENC || "hex";
29
29
  /**
30
30
  * crypto random initial vector generated from core node {crypto} module
31
31
  */
32
32
  this.initialVector = crypto.randomBytes(16);
33
+ /**
34
+ * hashing salt
35
+ */
36
+ // private readonly saltChars =
37
+ // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
33
38
  /**
34
39
  * crypto random key generated from core node {crypto} module
35
40
  * {note}: please read the value for KEY from your app's environment
36
41
  */
37
- this.key = crypto.scryptSync(process.env.KEY || 'please provide a KEY in your .env file or config', 'salt', 32);
42
+ this.key = crypto.scryptSync(process.env.KEY || "please provide a KEY in your .env file or config", "salt", 32);
38
43
  /**
39
44
  * convert all entered text to decimal equivalent character codes
40
45
  * @param {text.<string>} text to be converted
41
46
  * @return {Array.<number>} array of character codes
42
47
  */
43
48
  this.convertTextToDecimal = (text) => {
44
- return text.split('').map((value) => value.charCodeAt(0));
49
+ return text.split("").map((value) => value.charCodeAt(0));
45
50
  };
46
51
  /**
47
52
  * encode provided secret on decimal character codes
@@ -49,8 +54,7 @@ class Ncrypt {
49
54
  * @returns {*.<number>} decimal string
50
55
  */
51
56
  this.applySecretToCharacters = (charCodes) => {
52
- return this.convertTextToDecimal(this.secret)
53
- .reduce((firstValue, secondValue) => (firstValue ^ secondValue), charCodes);
57
+ return this.convertTextToDecimal(this.secret).reduce((firstValue, secondValue) => firstValue ^ secondValue, charCodes);
54
58
  };
55
59
  /**
56
60
  * convert character bytes to hexadecimal equivalent
@@ -58,7 +62,7 @@ class Ncrypt {
58
62
  * @returns {*.<string>} hexadecimal string
59
63
  */
60
64
  this.convertByteToHexadecimal = (number) => {
61
- return ('0' + Number(number).toString(16)).substr(-2);
65
+ return ("0" + Number(number).toString(16)).substr(-2);
62
66
  };
63
67
  /**
64
68
  * intermediate data encoder function
@@ -78,11 +82,11 @@ class Ncrypt {
78
82
  * @returns {string.<string>} decrypted data
79
83
  */
80
84
  this.decode = (text) => {
81
- if (typeof text !== 'string') {
82
- throw new TypeError('argument must be a string, or a string-like object');
85
+ if (typeof text !== "string") {
86
+ throw new TypeError("argument must be a string, or a string-like object");
83
87
  }
84
- const iv = text.split('.')[0];
85
- const encryptedData = text.split('.')[1];
88
+ const iv = text.split(".")[0];
89
+ const encryptedData = text.split(".")[1];
86
90
  let _iv = Buffer.from(iv, this.enc);
87
91
  let encryptedText = Buffer.from(encryptedData, this.enc);
88
92
  let decipher = crypto.createDecipheriv(this.algorithm, Buffer.from(this.key), _iv);
@@ -91,10 +95,99 @@ class Ncrypt {
91
95
  return decrypted.toString();
92
96
  };
93
97
  this.secret = secret;
94
- // bind public instnace methods
98
+ // bind public instance methods
95
99
  this.encrypt = this.encrypt.bind(this);
96
100
  this.decrypt = this.decrypt.bind(this);
97
101
  }
102
+ /**
103
+ *
104
+ * generate salt method
105
+ * @param length
106
+ * @param enc
107
+ * @returns
108
+ */
109
+ static generateSalt(length, enc = "hex") {
110
+ if (typeof length != "number" ||
111
+ length <= 0 ||
112
+ length !== parseInt(length, 10)) {
113
+ throw new Error("Invalid salt length");
114
+ }
115
+ // ensure your JS environment supports the `crypto.randomBytes()` function
116
+ return crypto
117
+ .randomBytes(Math.ceil(length / 2))
118
+ .toString(enc)
119
+ .substring(0, length);
120
+ }
121
+ /**
122
+ *
123
+ * generate hash method
124
+ * @param algorithm
125
+ * @param salt
126
+ * @param password
127
+ * @param iterations
128
+ * @param enc
129
+ * @param separator
130
+ * @returns
131
+ */
132
+ static generateHash(algorithm, salt, password, iterations = 1, enc = "hex", separator = "$") {
133
+ try {
134
+ let hash = password;
135
+ for (let i = 0; i < iterations; ++i) {
136
+ hash = crypto.createHmac(algorithm, salt).update(hash).digest(enc);
137
+ }
138
+ return (algorithm + separator + salt + separator + iterations + separator + hash);
139
+ }
140
+ catch (e) {
141
+ throw new Error("Invalid message digest algorithm");
142
+ }
143
+ }
144
+ /**
145
+ *
146
+ * generate hashed password method
147
+ * @param password
148
+ * @param options
149
+ * @returns
150
+ */
151
+ static generate(password, options = {}) {
152
+ options.algorithm = options.algorithm || "sha1";
153
+ options.saltLength = options.saltLength || 8;
154
+ options.iterations = options.iterations || 1;
155
+ options.encoding = options.encoding || "hex";
156
+ options.separator = options.separator || "$";
157
+ let salt = this.generateSalt(options.saltLength, options.encoding);
158
+ return this.generateHash(options.algorithm, salt, password, options.iterations, options.encoding, options.separator);
159
+ }
160
+ /**
161
+ *
162
+ * verify password method
163
+ */
164
+ static verify(password, hashedPassword, options = {}) {
165
+ if (!password || !hashedPassword)
166
+ return false;
167
+ options.encoding = options.encoding || "hex";
168
+ options.separator = options.separator || "$";
169
+ let parts = hashedPassword.split(options.separator);
170
+ if (parts.length != 4)
171
+ return false;
172
+ try {
173
+ return (this.generateHash(parts[0], parts[1], password, parts[2], options.encoding, options.separator) == hashedPassword);
174
+ }
175
+ catch (e) { }
176
+ return false;
177
+ }
178
+ /**
179
+ *
180
+ * isHashed method
181
+ * @param password
182
+ * @param options
183
+ * @returns
184
+ */
185
+ static isHashed(password, options = {}) {
186
+ if (!password)
187
+ return false;
188
+ options.separator = options.separator || "$";
189
+ return password.split(options.separator).length == 4;
190
+ }
98
191
  /**
99
192
  * generate random strings
100
193
  * @example
@@ -108,7 +201,7 @@ class Ncrypt {
108
201
  * @param {enc.<string>} enc
109
202
  * @returns {*.<string>} string
110
203
  */
111
- static randomString(size, enc = 'base64') {
204
+ static randomString(size, enc = "base64") {
112
205
  return crypto.randomBytes(size || 64).toString(enc);
113
206
  }
114
207
  /**
@@ -123,15 +216,17 @@ class Ncrypt {
123
216
  * hexadecimal mapping
124
217
  */
125
218
  try {
126
- const encodedMessage = JSON.stringify(data).split('')
219
+ const encodedMessage = JSON.stringify(data)
220
+ .split("")
127
221
  .map(this.convertTextToDecimal)
128
222
  .map(this.applySecretToCharacters)
129
223
  .map(this.convertByteToHexadecimal)
130
- .join('');
224
+ .join("");
131
225
  return this.encode(encodedMessage);
132
226
  }
133
227
  catch (e) {
134
- throw new Error('invalid data was entered, enter data of type object, number, string or boolean to be encrypted.' + e);
228
+ throw new Error("invalid data was entered, enter data of type object, number, string or boolean to be encrypted." +
229
+ e);
135
230
  }
136
231
  }
137
232
  /**
@@ -141,11 +236,12 @@ class Ncrypt {
141
236
  */
142
237
  decrypt(text) {
143
238
  const encodeData = this.decode(text);
144
- const data = (encodeData).match(/.{1,2}/g)
239
+ const data = encodeData
240
+ .match(/.{1,2}/g)
145
241
  .map((hex) => parseInt(hex, 16))
146
242
  .map(this.applySecretToCharacters)
147
243
  .map((charCode) => String.fromCharCode(charCode))
148
- .join('');
244
+ .join("");
149
245
  return JSON.parse(data);
150
246
  }
151
247
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ncrypt-js",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "description": "a light weight javascript data encryption and decryption library",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -51,7 +51,6 @@
51
51
  "files": [
52
52
  "dist",
53
53
  "package.json",
54
- "LICENSE",
55
- "tsconfig.json"
54
+ "LICENSE"
56
55
  ]
57
56
  }
package/tsconfig.json DELETED
@@ -1,23 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2015",
4
- "module": "commonjs",
5
- "lib": ["es2015", "es2016", "dom", "es2017", "es6", "es5"],
6
- "esModuleInterop": true,
7
- "noImplicitAny": true,
8
- "moduleResolution": "node",
9
- "declaration": true,
10
- "sourceMap": false,
11
- "outDir": "dist",
12
- "baseUrl": ".",
13
- "paths": {
14
- "*": ["node_modules/*","src/types/*"]
15
- }
16
- },
17
- "include": [
18
- "src/**/*", "index.ts",
19
- ],
20
- "exclude": [
21
- "test/**/*"
22
- ]
23
- }