@carecard/auth-util 1.0.1 → 2.0.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/index.js ADDED
@@ -0,0 +1,29 @@
1
+ const pwdUtilAuth = require( './lib/pwdUtilAuth' );
2
+ const jwtUtilAuth = require( './lib/jwtUtilAuth' );
3
+ const strEncryptUtil = require( './lib/strEncryptUtil' );
4
+ const keyGen = require( './lib/keyGen' );
5
+
6
+ module.exports = {
7
+ jwtUtilAuth: {
8
+ createSignedJwtFromObject: jwtUtilAuth.createSignedJwtFromObject,
9
+ verifyJwtSignature: jwtUtilAuth.verifyJwtSignature,
10
+ getHeaderPayloadFromJwt: jwtUtilAuth.getHeaderPayloadFromJwt
11
+ },
12
+
13
+ pwdUtilAuth: {
14
+ createPasswordHashWithRandomSalt: pwdUtilAuth.createPasswordHashWithRandomSalt,
15
+ createPasswordHashBasedOnSavedAlgorithmSalt: pwdUtilAuth.createPasswordHashBasedOnSavedAlgorithmSalt
16
+ },
17
+
18
+ strEncryptUtil: {
19
+ encryptByPrivateKey: strEncryptUtil.encryptByPrivateKey,
20
+ decryptByPublicKey: strEncryptUtil.decryptByPublicKey,
21
+ encryptByKey: strEncryptUtil.encryptByKey,
22
+ decryptByKey: strEncryptUtil.decryptByKey
23
+ },
24
+
25
+ createRsaKeys: keyGen.generateKeyPair,
26
+
27
+ stringUtilAuth: require( './lib/stringUtilAuth' ),
28
+ };
29
+
@@ -0,0 +1,100 @@
1
+ const crypto = require( "crypto" );
2
+
3
+
4
+ /**
5
+ * Signs a token returns signature string
6
+ * @param token
7
+ * @param privateKey
8
+ * @param signingAlgorithm
9
+ * @returns {string}
10
+ */
11
+ const createBase64SignatureOfToken = function ( token = '', privateKey, signingAlgorithm ) {
12
+
13
+ const sign = crypto.createSign( signingAlgorithm );
14
+ sign.write( token );
15
+ sign.end();
16
+ return sign.sign( privateKey, 'base64' );
17
+ };
18
+
19
+ /**
20
+ * Verifies the signature returns true or false
21
+ * @param token
22
+ * @param signature
23
+ * @param publicKey
24
+ * @param signingAlgorithm
25
+ * @returns {boolean}
26
+ */
27
+ const verifyBase64SignatureOfToken = function ( token = '', signature, publicKey, signingAlgorithm ) {
28
+ const verify = crypto.createVerify( signingAlgorithm );
29
+ verify.update( token );
30
+ verify.end();
31
+ return verify.verify( publicKey, signature, 'base64' );
32
+ };
33
+
34
+ /**
35
+ * Creates the hash of given string
36
+ * @param string
37
+ * @param secret
38
+ * @param algorithm
39
+ * @returns {string}
40
+ */
41
+ const createHmacBase64 = function ( string = '', secret, algorithm ) {
42
+ const hmac = crypto.createHmac( algorithm, secret );
43
+ hmac.update( string );
44
+ return hmac.digest( 'base64' );
45
+ };
46
+
47
+ /**
48
+ * Create random salt
49
+ * @returns {string}
50
+ */
51
+ const createSaltBase64 = () => {
52
+ const date = new Date().valueOf();
53
+ const hmac = crypto.createHmac( 'SHA256', date.toString() );
54
+ hmac.update( date.toString() );
55
+ return hmac.digest( 'base64' );
56
+ };
57
+
58
+ /**
59
+ * Encrypt given string
60
+ * @param string
61
+ * @param salt
62
+ * @param secret
63
+ * @param algorithm
64
+ * @returns {string}
65
+ */
66
+ const encryptStringAsciiToBase64 = ( string, salt, secret, algorithm ) => {
67
+
68
+ const key = crypto.scryptSync( secret, salt, 24 );
69
+ const iv = Buffer.alloc( 16, 0 );
70
+ const cipher = crypto.createCipheriv( algorithm, key, iv );
71
+ let encrypted = cipher.update( string, 'ascii', 'base64' );
72
+ encrypted += cipher.final( 'base64' );
73
+ return encrypted;
74
+ };
75
+
76
+ /**
77
+ * Decrypts given string
78
+ * @param encryptedString
79
+ * @param salt
80
+ * @param secret
81
+ * @param algorithm
82
+ * @returns {string}
83
+ */
84
+ const decryptStringBase64ToAscii = ( encryptedString, salt, secret, algorithm ) => {
85
+ const key = crypto.scryptSync( secret, salt, 24 );
86
+ const iv = Buffer.alloc( 16, 0 );
87
+ const decipher = crypto.createDecipheriv( algorithm, key, iv );
88
+ let decrypted = decipher.update( encryptedString, 'base64', 'ascii' );
89
+ decrypted += decipher.final( 'ascii' );
90
+ return decrypted;
91
+ };
92
+
93
+ module.exports = {
94
+ createBase64SignatureOfToken,
95
+ verifyBase64SignatureOfToken,
96
+ createHmacBase64,
97
+ createSaltBase64,
98
+ encryptStringAsciiToBase64,
99
+ decryptStringBase64ToAscii
100
+ };
@@ -0,0 +1,81 @@
1
+ const stringUtilAuth = require( './stringUtilAuth' );
2
+ const cryptoUtilAuth = require( './cryptoUtilAuth' );
3
+
4
+ /**
5
+ * User supplied header, payload and signature create jwt.
6
+ * @returns {string|null}
7
+ * @param headerBase64
8
+ * @param payloadBase64
9
+ * @param signatureBase64
10
+ */
11
+ const _assembleJwt = ( headerBase64, payloadBase64, signatureBase64 ) => {
12
+ return headerBase64 + "." + payloadBase64 + "." + signatureBase64;
13
+ };
14
+
15
+ /**
16
+ * User supplied header, payload and signature create jwt.
17
+ * @returns {{payload: *, signature: *, header: *}}
18
+ * @param jwt
19
+ */
20
+ const _splitJwtInToHeaderPayloadSignature = ( jwt ) => {
21
+ return stringUtilAuth.dotConnectedStringToHeaderPayloadSignature( jwt );
22
+ };
23
+
24
+ /**
25
+ * Creates Url safe jwt
26
+ * @param headerObject
27
+ * @param payloadObject
28
+ * @param privateKey
29
+ * @return {string|null}
30
+ */
31
+ const createSignedJwtFromObject = ( headerObject, payloadObject, privateKey ) => {
32
+ try {
33
+ const algorithm = headerObject.alg;
34
+ const headerBase64UrlSafe = stringUtilAuth.objectToBase64UrlSafeString( headerObject );
35
+ const payloadBase64UrlSafe = stringUtilAuth.objectToBase64UrlSafeString( payloadObject );
36
+ const token = headerBase64UrlSafe + "." + payloadBase64UrlSafe;
37
+ const signature = cryptoUtilAuth.createBase64SignatureOfToken( token, privateKey, algorithm );
38
+ const urlSafeSignature = stringUtilAuth.makeStringUrlSafe( signature );
39
+ return _assembleJwt( headerBase64UrlSafe, payloadBase64UrlSafe, urlSafeSignature );
40
+ } catch ( error ) {
41
+ return null;
42
+ }
43
+ };
44
+
45
+ /**
46
+ * Verify signature of jwt
47
+ * @param jwt
48
+ * @param publicKey
49
+ * @return {boolean}
50
+ */
51
+ const verifyJwtSignature = ( jwt, publicKey ) => {
52
+ try {
53
+ const { header, payload, signature } = _splitJwtInToHeaderPayloadSignature( jwt );
54
+ const token = header + "." + payload;
55
+ const headerObject = stringUtilAuth.urlSafeBase64ToObject( header );
56
+ return cryptoUtilAuth.verifyBase64SignatureOfToken( token, signature, publicKey, headerObject.alg )
57
+ } catch ( error ) {
58
+ return false;
59
+ }
60
+ };
61
+
62
+ /**
63
+ * Returns header and payload object for jwt.
64
+ * @param jwt
65
+ * @return {{payload: any, header: any}}
66
+ */
67
+ const getHeaderPayloadFromJwt = jwt => {
68
+ const { header, payload, signature } = _splitJwtInToHeaderPayloadSignature( jwt );
69
+ let headerAscii = stringUtilAuth.base64ToAscii( header );
70
+ let payloadAscii = stringUtilAuth.base64ToAscii( payload );
71
+ return { header: JSON.parse( headerAscii ), payload: JSON.parse( payloadAscii ) }
72
+ };
73
+
74
+
75
+ module.exports = {
76
+ _assembleJwt,
77
+ _splitJwtInToHeaderPayloadSignature,
78
+ createSignedJwtFromObject,
79
+ verifyJwtSignature,
80
+ getHeaderPayloadFromJwt
81
+ };
package/lib/keyGen.js ADDED
@@ -0,0 +1,21 @@
1
+ const {
2
+ generateKeyPairSync,
3
+ } = require( 'node:crypto' );
4
+
5
+
6
+ const generateKeyPair = ( modulusLength = 4096 ) => ( generateKeyPairSync( 'rsa', {
7
+ modulusLength: modulusLength,
8
+ publicKeyEncoding: {
9
+ type: 'spki',
10
+ format: 'pem',
11
+ },
12
+ privateKeyEncoding: {
13
+ type: 'pkcs8',
14
+ format: 'pem',
15
+ },
16
+ } ) );
17
+
18
+
19
+ module.exports = {
20
+ generateKeyPair
21
+ };
@@ -0,0 +1,71 @@
1
+ const cryptoUtilAuth = require( './cryptoUtilAuth' );
2
+ const stringUtilAuth = require( './stringUtilAuth' );
3
+
4
+ /**
5
+ * Just assemble password together
6
+ * @param algorithmBase64
7
+ * @param hashBase64
8
+ * @param saltBase64
9
+ * @return {string}
10
+ */
11
+ const _assemblePasswordHash = ( algorithmBase64, hashBase64, saltBase64 ) => {
12
+ return "$1$" + algorithmBase64 + "$" + hashBase64 + "$" + saltBase64 + "$";
13
+ };
14
+
15
+ /**
16
+ * Break password into its parts does not reverse base64 encoding.
17
+ * @param passwordHashStored
18
+ * @return {{salt: *, version: *, alg: *, hash: *}}
19
+ */
20
+ const _disassemblePasswordHash = passwordHashStored => {
21
+ return stringUtilAuth.dollarSignConnectedStringToAlgorithmHashSalt( passwordHashStored );
22
+ };
23
+
24
+
25
+ /**
26
+ * Creates password hash ready to be saved in database.
27
+ * @param password
28
+ * @param secret
29
+ * @param salt
30
+ * @param algorithm
31
+ * @return {string}
32
+ */
33
+ const _createPasswordHash = ( password, secret, salt, algorithm ) => {
34
+ const algorithmBase64 = stringUtilAuth.asciiToBase64( algorithm );
35
+ const hashBase64 = cryptoUtilAuth.createHmacBase64( password, secret, algorithm );
36
+ return _assemblePasswordHash( algorithmBase64, hashBase64, salt );
37
+ };
38
+
39
+ /**
40
+ * Automatically adds random salt.
41
+ * @param password
42
+ * @param secret
43
+ * @param algorithm
44
+ * @return {string}
45
+ */
46
+ const createPasswordHashWithRandomSalt = ( password, secret, algorithm ) => {
47
+ const salt = cryptoUtilAuth.createSaltBase64();
48
+ return _createPasswordHash( password, secret, salt, algorithm );
49
+ };
50
+
51
+ /**
52
+ * Creates hash based on saved hash in database.
53
+ * @param password
54
+ * @param savedPasswordHash
55
+ * @param secret
56
+ * @return {string}
57
+ */
58
+ const createPasswordHashBasedOnSavedAlgorithmSalt = ( password, savedPasswordHash, secret ) => {
59
+ const { version, alg, hash, salt } = _disassemblePasswordHash( savedPasswordHash );
60
+ const algorithm = stringUtilAuth.base64ToAscii( alg );
61
+ return _createPasswordHash( password, secret, salt, algorithm );
62
+ };
63
+
64
+
65
+ module.exports = {
66
+ _assemblePasswordHash,
67
+ _disassemblePasswordHash,
68
+ _createPasswordHash,
69
+ createPasswordHashWithRandomSalt,
70
+ createPasswordHashBasedOnSavedAlgorithmSalt
71
+ }
@@ -0,0 +1,113 @@
1
+ const crypto = require( "crypto" );
2
+
3
+
4
+ function createKey( key, keyLength = 32 ) {
5
+ return crypto.scryptSync( key, key, keyLength );
6
+ }
7
+
8
+ const encryptByPrivateKey = ( encryptionConfigObj, textToEncrypt ) => {
9
+ try {
10
+
11
+ const encrypted = crypto.privateEncrypt(
12
+ encryptionConfigObj.privateKey,
13
+ Buffer.from( textToEncrypt )
14
+ );
15
+
16
+ return encrypted.toString( encryptionConfigObj.encryptedTextEncoding );
17
+
18
+ } catch ( error ) {
19
+
20
+ return error.code;
21
+
22
+ }
23
+ };
24
+
25
+ const decryptByPublicKey = ( decryptionConfigObj, textToDecrypt ) => {
26
+ try {
27
+
28
+ const decrypted = crypto.publicDecrypt(
29
+ decryptionConfigObj.publicKey,
30
+ Buffer.from(
31
+ textToDecrypt,
32
+ decryptionConfigObj.encryptedTextEncoding
33
+ )
34
+ );
35
+
36
+ return decrypted.toString( decryptionConfigObj.plainTextEncoding );
37
+
38
+ } catch ( error ) {
39
+
40
+ return error.code;
41
+
42
+ }
43
+ };
44
+
45
+ const encryptByKey = ( encryptConfigObj = {}, textToEncrypt ) => {
46
+ try {
47
+
48
+ const iv = Buffer.alloc( 16, 0 );
49
+
50
+ const cipher = crypto.createCipheriv(
51
+ encryptConfigObj.cipherAlgorithm,
52
+ createKey(
53
+ encryptConfigObj.encryptionKey,
54
+ encryptConfigObj.keyLength
55
+ ),
56
+ iv
57
+ );
58
+
59
+ let encrypted = cipher.update(
60
+ textToEncrypt,
61
+ encryptConfigObj.plainTextEncoding,
62
+ encryptConfigObj.encryptedTextEncoding
63
+ );
64
+
65
+ encrypted += cipher.final( encryptConfigObj.encryptedTextEncoding );
66
+
67
+ return encrypted;
68
+
69
+ } catch ( error ) {
70
+
71
+ return error.code;
72
+
73
+ }
74
+ };
75
+
76
+ const decryptByKey = ( encryptConfigObj, textToDecrypt ) => {
77
+ try {
78
+
79
+ const iv = Buffer.alloc( 16, 0 );
80
+
81
+ const decipher = crypto.createDecipheriv(
82
+ encryptConfigObj.cipherAlgorithm,
83
+ createKey(
84
+ encryptConfigObj.encryptionKey,
85
+ encryptConfigObj.keyLength
86
+ ),
87
+ iv
88
+ );
89
+
90
+ let decrypted = decipher.update(
91
+ textToDecrypt,
92
+ encryptConfigObj.encryptedTextEncoding,
93
+ encryptConfigObj.plainTextEncoding
94
+ );
95
+
96
+ decrypted += decipher.final( encryptConfigObj.plainTextEncoding );
97
+
98
+ return decrypted;
99
+
100
+ } catch ( error ) {
101
+
102
+ return error.code;
103
+
104
+ }
105
+ };
106
+
107
+
108
+ module.exports = {
109
+ encryptByPrivateKey,
110
+ decryptByPublicKey,
111
+ encryptByKey,
112
+ decryptByKey
113
+ }
@@ -0,0 +1,119 @@
1
+ 'use strict';
2
+ /**
3
+ * For incoming jwt token validation, splitting and parsing.
4
+ * For outgoing jwt token assembling to jwt, make it url safe.
5
+ */
6
+
7
+ /**
8
+ * Adjusts padding of base64String
9
+ * @param base64String
10
+ * @return {*}
11
+ */
12
+ const adjustBase64Padding = base64String => {
13
+ while ( base64String.length % 4 ) base64String += '=';
14
+ return base64String;
15
+ }
16
+
17
+ /**
18
+ * Removes /, + and = from the string
19
+ * @returns {string}
20
+ */
21
+ const makeStringUrlSafe = ( urlUnsafeString = '' ) => {
22
+ return urlUnsafeString
23
+ .replaceAll( '+', '-' )
24
+ .replaceAll( '/', '_' )
25
+ .replaceAll( '=', '' );
26
+ };
27
+
28
+ /**
29
+ * Put back /, + and = into the string
30
+ * @returns {string}
31
+ */
32
+ const reverseStringUrlSafe = ( urlSafeString = '' ) => {
33
+ let myString = urlSafeString
34
+ .replaceAll( '-', '+' )
35
+ .replaceAll( '_', '/' );
36
+ return adjustBase64Padding( myString );
37
+ };
38
+
39
+ /**
40
+ * Encode string to base64 string
41
+ * @param unCodedString
42
+ * @returns {string}
43
+ */
44
+ const asciiToBase64 = ( unCodedString ) => {
45
+ return Buffer.from( unCodedString ).toString( 'base64' );
46
+ }
47
+
48
+ /** Decode string from base64
49
+ * @param codedString
50
+ * @returns {string}
51
+ */
52
+ const base64ToAscii = ( codedString ) => {
53
+ return Buffer.from( codedString, 'base64' ).toString( 'ascii' );
54
+ }
55
+
56
+ /**
57
+ * Decompose $ connected string and return an object
58
+ * return null if error
59
+ * @param passwordHash
60
+ */
61
+ const dollarSignConnectedStringToAlgorithmHashSalt = ( passwordHash ) => {
62
+ const splitStringArray = passwordHash.split( '$' );
63
+ if ( splitStringArray.length !== 6 ) return null;
64
+ return {
65
+ version: splitStringArray[ 1 ],
66
+ alg: splitStringArray[ 2 ],
67
+ hash: splitStringArray[ 3 ],
68
+ salt: splitStringArray[ 4 ]
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Decompose . connected string and return an object with
74
+ * {header: 'string', payload: 'string', signature: 'string'}
75
+ * return null if error
76
+ */
77
+ const dotConnectedStringToHeaderPayloadSignature = ( jwt ) => {
78
+ const splitJWT = jwt.split( '.' );
79
+ if ( splitJWT.length !== 3 ) return null;
80
+ return {
81
+ header: splitJWT[ 0 ],
82
+ payload: splitJWT[ 1 ],
83
+ signature: splitJWT[ 2 ]
84
+ };
85
+ }
86
+
87
+
88
+ /**
89
+ * Turns object into url safe string
90
+ * @param object
91
+ * @return {string}
92
+ */
93
+ const objectToBase64UrlSafeString = object => {
94
+ let stringAscii = JSON.stringify( object );
95
+ let base64String = asciiToBase64( stringAscii );
96
+ return makeStringUrlSafe( base64String );
97
+ };
98
+
99
+ /**
100
+ * Turns base64 into object
101
+ * @param urlSafeBase64String
102
+ * @return {any}
103
+ */
104
+ const urlSafeBase64ToObject = urlSafeBase64String => {
105
+ let base64String = reverseStringUrlSafe( urlSafeBase64String );
106
+ let stringAscii = base64ToAscii( base64String );
107
+ return JSON.parse( stringAscii );
108
+ };
109
+
110
+ module.exports = {
111
+ makeStringUrlSafe,
112
+ reverseStringUrlSafe,
113
+ asciiToBase64,
114
+ base64ToAscii,
115
+ dollarSignConnectedStringToAlgorithmHashSalt,
116
+ dotConnectedStringToHeaderPayloadSignature,
117
+ objectToBase64UrlSafeString,
118
+ urlSafeBase64ToObject
119
+ };
package/package.json CHANGED
@@ -1,54 +1,22 @@
1
1
  {
2
2
  "name": "@carecard/auth-util",
3
- "version": "1.0.1",
4
- "private": false,
3
+ "version": "2.0.0",
4
+ "repository": "https://github.com/CareCard-ca/pkg-auth-util.git",
5
5
  "description": "Auth utility functions",
6
- "license": "ISC",
7
- "author": "PK Singh",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https:github.com/CareCard-ca/pkg-auth-util.git"
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "test": "export NODE_ENV=test && mocha --watch --recursive"
11
9
  },
12
10
  "keywords": [
13
11
  "auth",
14
12
  "utility",
15
13
  "cryptology"
16
14
  ],
17
- "type": "module",
18
- "publishConfig": {
19
- "access": "public"
20
- },
21
- "main": "./dist/cjs/index.cjs",
22
- "module": "./dist/esm/index.js",
23
- "types": "./dist/esm/index.d.ts",
24
- "exports": {
25
- ".": {
26
- "import": "./dist/esm/index.js",
27
- "require": "./dist/cjs/index.cjs",
28
- "types": "./dist/esm/index.d.ts"
29
- }
30
- },
31
- "files": [
32
- "dist"
33
- ],
34
- "scripts": {
35
- "build": "npm run build:esm && npm run build:cjs",
36
- "build:esm": "tsc -p tsconfig.esm.json",
37
- "build:cjs": "tsc -p tsconfig.cjs.json && node ./scripts/rename-cjs.js",
38
- "test": "NODE_NO_WARNINGS=1 jest --coverage",
39
- "format": "prettier --write .",
40
- "format:check": "prettier --check .",
41
- "lint": "eslint",
42
- "prepare": "husky"
43
- },
15
+ "author": "CareCard team",
16
+ "license": "ISC",
44
17
  "devDependencies": {
45
- "@types/jest": "30.0.0",
46
- "eslint": "9.39.2",
47
- "husky": "9.1.7",
48
- "jest": "30.2.0",
49
- "prettier": "3.7.4",
50
- "ts-jest": "29.4.6",
51
- "typescript": "5.9.3",
52
- "typescript-eslint": "8.50.1"
18
+ "mocha": "10.2.0"
19
+ },
20
+ "dependencies": {
53
21
  }
54
22
  }
package/readme.md CHANGED
@@ -7,7 +7,7 @@ This is a collection of utility functions for use in authentication
7
7
  ### Main functions
8
8
 
9
9
  ```js
10
- const { jwtUtilAuth, pwdUtilAuth } = require( '@carecard/auth-util' );
10
+ const { jwtUtilAuth, pwdUtilAuth } = require( '@chatpta/auth-util' );
11
11
  ```
12
12
 
13
13
  Create jwt