@carecard/auth-util 3.1.15 → 3.1.16
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/.agents/skills/carecard-workspace-standards/SKILL.md +30 -17
- package/.agents/skills/github-pr-create-update/SKILL.md +6 -6
- package/.agents/skills/github-pr-merge-cleanup/SKILL.md +6 -6
- package/.agents/skills/pkg-auth-util-auth-crypto-library/SKILL.md +8 -5
- package/.agents/skills/software-design-patterns-and-clean-code/SKILL.md +1 -1
- package/package.json +6 -6
- package/readme.md +13 -0
- package/.prettierignore +0 -17
- package/.prettierrc.cjs +0 -32
- package/jest.config.js +0 -16
- package/scripts/rename-cjs.js +0 -13
- package/src/cryptoUtilAuth.ts +0 -111
- package/src/index.ts +0 -6
- package/src/jwtUtilAuth.ts +0 -85
- package/src/keyGen.ts +0 -14
- package/src/pwdUtilAuth.ts +0 -78
- package/src/strEncryptUtil.ts +0 -159
- package/src/stringUtilAuth.ts +0 -102
- package/tests/cryptoUtilAuth.test.ts +0 -97
- package/tests/index.test.ts +0 -157
- package/tests/indexStringUtilAuth.test.ts +0 -95
- package/tests/jwtUtilAuth.test.ts +0 -33
- package/tests/keyGen.test.ts +0 -26
- package/tests/keys/keys.ts +0 -24
- package/tests/pwdUtilAuth.test.ts +0 -40
- package/tsconfig.base.json +0 -14
- package/tsconfig.cjs.json +0 -7
- package/tsconfig.esm.json +0 -7
package/src/pwdUtilAuth.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import * as cryptoUtilAuth from './cryptoUtilAuth';
|
|
2
|
-
import * as stringUtilAuth from './stringUtilAuth';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Just assemble password together
|
|
6
|
-
* @param algorithmBase64
|
|
7
|
-
* @param hashBase64
|
|
8
|
-
* @param saltBase64
|
|
9
|
-
* @return {string}
|
|
10
|
-
*/
|
|
11
|
-
export const _assemblePasswordHash = (
|
|
12
|
-
algorithmBase64: string,
|
|
13
|
-
hashBase64: string,
|
|
14
|
-
saltBase64: string,
|
|
15
|
-
): string => {
|
|
16
|
-
return '$1$' + algorithmBase64 + '$' + hashBase64 + '$' + saltBase64 + '$';
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Break password into its parts does not reverse base64 encoding.
|
|
21
|
-
* @param passwordHashStored
|
|
22
|
-
* @return {{salt: *, version: *, alg: *, hash: *}}
|
|
23
|
-
*/
|
|
24
|
-
export const _disassemblePasswordHash = (passwordHashStored: string): any => {
|
|
25
|
-
return stringUtilAuth.dollarSignConnectedStringToAlgorithmHashSalt(passwordHashStored);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Creates password hash ready to be saved in database.
|
|
30
|
-
* @param password
|
|
31
|
-
* @param secret
|
|
32
|
-
* @param salt
|
|
33
|
-
* @param algorithm
|
|
34
|
-
* @return {string}
|
|
35
|
-
*/
|
|
36
|
-
export const _createPasswordHash = (
|
|
37
|
-
password: string,
|
|
38
|
-
secret: string,
|
|
39
|
-
salt: string,
|
|
40
|
-
algorithm: string,
|
|
41
|
-
): string => {
|
|
42
|
-
const algorithmBase64 = stringUtilAuth.asciiToBase64(algorithm);
|
|
43
|
-
const hashBase64 = cryptoUtilAuth.createHmacBase64(password, secret, algorithm);
|
|
44
|
-
return _assemblePasswordHash(algorithmBase64, hashBase64, salt);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Automatically adds random salt.
|
|
49
|
-
* @param password
|
|
50
|
-
* @param secret
|
|
51
|
-
* @param algorithm
|
|
52
|
-
* @return {string}
|
|
53
|
-
*/
|
|
54
|
-
export const createPasswordHashWithRandomSalt = (
|
|
55
|
-
password: string,
|
|
56
|
-
secret: string,
|
|
57
|
-
algorithm: string,
|
|
58
|
-
): string => {
|
|
59
|
-
const salt = cryptoUtilAuth.createSaltBase64();
|
|
60
|
-
return _createPasswordHash(password, secret, salt, algorithm);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Creates hash based on saved hash in database.
|
|
65
|
-
* @param password
|
|
66
|
-
* @param savedPasswordHash
|
|
67
|
-
* @param secret
|
|
68
|
-
* @return {string}
|
|
69
|
-
*/
|
|
70
|
-
export const createPasswordHashBasedOnSavedAlgorithmSalt = (
|
|
71
|
-
password: string,
|
|
72
|
-
savedPasswordHash: string,
|
|
73
|
-
secret: string,
|
|
74
|
-
): string => {
|
|
75
|
-
const { alg, salt } = _disassemblePasswordHash(savedPasswordHash);
|
|
76
|
-
const algorithm = stringUtilAuth.base64ToAscii(alg);
|
|
77
|
-
return _createPasswordHash(password, secret, salt, algorithm);
|
|
78
|
-
};
|
package/src/strEncryptUtil.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
// src/strEncryptUtil.ts
|
|
2
|
-
import * as crypto from 'crypto';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Derive a key using scrypt.
|
|
6
|
-
*/
|
|
7
|
-
export function createKey(key: crypto.BinaryLike, keyLength = 32): Buffer {
|
|
8
|
-
// scryptSync returns a Buffer
|
|
9
|
-
return crypto.scryptSync(key, key, keyLength);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/* --------------------------------------------------
|
|
13
|
-
* Config Types
|
|
14
|
-
* -------------------------------------------------- */
|
|
15
|
-
|
|
16
|
-
export interface EncryptionConfig {
|
|
17
|
-
privateKey: string | Buffer | crypto.KeyObject;
|
|
18
|
-
encryptedTextEncoding: BufferEncoding; // e.g., 'base64' | 'hex' | ...
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface DecryptionConfig {
|
|
22
|
-
publicKey: string | Buffer | crypto.KeyObject;
|
|
23
|
-
encryptedTextEncoding: BufferEncoding; // encoding of input cipher text buffer
|
|
24
|
-
plainTextEncoding: BufferEncoding; // encoding for output text, e.g., 'utf8'
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface SymmetricCryptoConfig {
|
|
28
|
-
cipherAlgorithm: string; // e.g., 'aes-256-cbc'
|
|
29
|
-
encryptionKey: crypto.BinaryLike; // passphrase or raw key-like data
|
|
30
|
-
keyLength: number; // e.g., 32 for aes-256
|
|
31
|
-
plainTextEncoding: BufferEncoding; // e.g., 'utf8'
|
|
32
|
-
encryptedTextEncoding: BufferEncoding; // e.g., 'base64' | 'hex'
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/* --------------------------------------------------
|
|
36
|
-
* Helpers
|
|
37
|
-
* -------------------------------------------------- */
|
|
38
|
-
|
|
39
|
-
function getErrorCodeOrFallback(error: unknown): string {
|
|
40
|
-
// Safely narrow 'unknown' to read 'code' when available
|
|
41
|
-
if (
|
|
42
|
-
typeof error === 'object' &&
|
|
43
|
-
error !== null &&
|
|
44
|
-
'code' in error &&
|
|
45
|
-
typeof (error as { code?: unknown }).code === 'string'
|
|
46
|
-
) {
|
|
47
|
-
return (error as { code: string }).code;
|
|
48
|
-
}
|
|
49
|
-
if (error instanceof Error) {
|
|
50
|
-
// You can return message or name; using name keeps it short
|
|
51
|
-
return `ERROR:${error.name}`;
|
|
52
|
-
}
|
|
53
|
-
return 'UNKNOWN_ERROR';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/* --------------------------------------------------
|
|
57
|
-
* Asymmetric Encryption (RSA or similar)
|
|
58
|
-
* -------------------------------------------------- */
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Encrypts text using a private key, returning an encoded cipher text string.
|
|
62
|
-
* On error, returns a code string if present, otherwise a fallback.
|
|
63
|
-
*/
|
|
64
|
-
export const encryptByPrivateKey = (
|
|
65
|
-
encryptionConfigObj: EncryptionConfig,
|
|
66
|
-
textToEncrypt: string,
|
|
67
|
-
): string => {
|
|
68
|
-
try {
|
|
69
|
-
const encrypted = crypto.privateEncrypt(
|
|
70
|
-
encryptionConfigObj.privateKey,
|
|
71
|
-
Buffer.from(textToEncrypt, 'utf8'),
|
|
72
|
-
);
|
|
73
|
-
return encrypted.toString(encryptionConfigObj.encryptedTextEncoding);
|
|
74
|
-
} catch (error: unknown) {
|
|
75
|
-
return getErrorCodeOrFallback(error);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Decrypts text using a public key, returning a plain text string.
|
|
81
|
-
* On error, returns a code string if present, otherwise a fallback.
|
|
82
|
-
*/
|
|
83
|
-
export const decryptByPublicKey = (
|
|
84
|
-
decryptionConfigObj: DecryptionConfig,
|
|
85
|
-
textToDecrypt: string,
|
|
86
|
-
): string => {
|
|
87
|
-
try {
|
|
88
|
-
const decrypted = crypto.publicDecrypt(
|
|
89
|
-
decryptionConfigObj.publicKey,
|
|
90
|
-
Buffer.from(textToDecrypt, decryptionConfigObj.encryptedTextEncoding),
|
|
91
|
-
);
|
|
92
|
-
return decrypted.toString(decryptionConfigObj.plainTextEncoding);
|
|
93
|
-
} catch (error: unknown) {
|
|
94
|
-
return getErrorCodeOrFallback(error);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
/* --------------------------------------------------
|
|
99
|
-
* Symmetric Encryption (AES or similar)
|
|
100
|
-
* -------------------------------------------------- */
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Encrypts text using a symmetric algorithm and derived key, returning an encoded cipher string.
|
|
104
|
-
* On error, returns a code string if present, otherwise a fallback.
|
|
105
|
-
*
|
|
106
|
-
* NOTE: This uses a zero IV (Buffer.alloc(16, 0)) which is generally **not recommended** for production.
|
|
107
|
-
* Prefer a random IV per encryption and prepend/append it to the output for decryption.
|
|
108
|
-
*/
|
|
109
|
-
export const encryptByKey = (
|
|
110
|
-
encryptConfigObj: SymmetricCryptoConfig,
|
|
111
|
-
textToEncrypt: string,
|
|
112
|
-
): string => {
|
|
113
|
-
try {
|
|
114
|
-
const iv = Buffer.alloc(16, 0); // ⚠️ consider using a random IV for security
|
|
115
|
-
const key = createKey(encryptConfigObj.encryptionKey, encryptConfigObj.keyLength);
|
|
116
|
-
|
|
117
|
-
const cipher = crypto.createCipheriv(encryptConfigObj.cipherAlgorithm, key, iv);
|
|
118
|
-
|
|
119
|
-
let encrypted = cipher.update(
|
|
120
|
-
textToEncrypt,
|
|
121
|
-
encryptConfigObj.plainTextEncoding,
|
|
122
|
-
encryptConfigObj.encryptedTextEncoding,
|
|
123
|
-
);
|
|
124
|
-
encrypted += cipher.final(encryptConfigObj.encryptedTextEncoding);
|
|
125
|
-
|
|
126
|
-
return encrypted;
|
|
127
|
-
} catch (error: unknown) {
|
|
128
|
-
return getErrorCodeOrFallback(error);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Decrypts a cipher string using a symmetric algorithm and derived key,
|
|
134
|
-
* returning the plain text string. On error, returns a code string or fallback.
|
|
135
|
-
*
|
|
136
|
-
* NOTE: Must use the same IV that was used during encryption. Here it assumes a zero IV.
|
|
137
|
-
*/
|
|
138
|
-
export const decryptByKey = (
|
|
139
|
-
encryptConfigObj: SymmetricCryptoConfig,
|
|
140
|
-
textToDecrypt: string,
|
|
141
|
-
): string => {
|
|
142
|
-
try {
|
|
143
|
-
const iv = Buffer.alloc(16, 0); // ⚠️ must match the IV used in encryptByKey
|
|
144
|
-
const key = createKey(encryptConfigObj.encryptionKey, encryptConfigObj.keyLength);
|
|
145
|
-
|
|
146
|
-
const decipher = crypto.createDecipheriv(encryptConfigObj.cipherAlgorithm, key, iv);
|
|
147
|
-
|
|
148
|
-
let decrypted = decipher.update(
|
|
149
|
-
textToDecrypt,
|
|
150
|
-
encryptConfigObj.encryptedTextEncoding,
|
|
151
|
-
encryptConfigObj.plainTextEncoding,
|
|
152
|
-
);
|
|
153
|
-
decrypted += decipher.final(encryptConfigObj.plainTextEncoding);
|
|
154
|
-
|
|
155
|
-
return decrypted;
|
|
156
|
-
} catch (error: unknown) {
|
|
157
|
-
return getErrorCodeOrFallback(error);
|
|
158
|
-
}
|
|
159
|
-
};
|
package/src/stringUtilAuth.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
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
|
-
export const adjustBase64Padding = (base64String: string): string => {
|
|
13
|
-
while (base64String.length % 4) base64String += '=';
|
|
14
|
-
return base64String;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Removes /, + and = from the string
|
|
19
|
-
* @returns {string}
|
|
20
|
-
*/
|
|
21
|
-
export const makeStringUrlSafe = (urlUnsafeString: string = ''): string => {
|
|
22
|
-
return urlUnsafeString.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Put back /, + and = into the string
|
|
27
|
-
* @returns {string}
|
|
28
|
-
*/
|
|
29
|
-
export const reverseStringUrlSafe = (urlSafeString: string = ''): string => {
|
|
30
|
-
let myString = urlSafeString.replace(/-/g, '+').replace(/_/g, '/');
|
|
31
|
-
return adjustBase64Padding(myString);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Encode string to base64 string
|
|
36
|
-
* @param unCodedString
|
|
37
|
-
* @returns {string}
|
|
38
|
-
*/
|
|
39
|
-
export const asciiToBase64 = (unCodedString: string): string => {
|
|
40
|
-
return Buffer.from(unCodedString).toString('base64');
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/** Decode string from base64
|
|
44
|
-
* @param codedString
|
|
45
|
-
* @returns {string}
|
|
46
|
-
*/
|
|
47
|
-
export const base64ToAscii = (codedString: string): string => {
|
|
48
|
-
return Buffer.from(codedString, 'base64').toString('ascii');
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Decompose $ connected string and return an object
|
|
53
|
-
* return null if error
|
|
54
|
-
* @param passwordHash
|
|
55
|
-
*/
|
|
56
|
-
export const dollarSignConnectedStringToAlgorithmHashSalt = (passwordHash: string) => {
|
|
57
|
-
const splitStringArray = passwordHash.split('$');
|
|
58
|
-
if (splitStringArray.length !== 6) return null;
|
|
59
|
-
return {
|
|
60
|
-
version: splitStringArray[1],
|
|
61
|
-
alg: splitStringArray[2],
|
|
62
|
-
hash: splitStringArray[3],
|
|
63
|
-
salt: splitStringArray[4],
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Decompose . connected string and return an object with
|
|
69
|
-
* {header: 'string', payload: 'string', signature: 'string'}
|
|
70
|
-
* return null if error
|
|
71
|
-
*/
|
|
72
|
-
export const dotConnectedStringToHeaderPayloadSignature = (jwt: string) => {
|
|
73
|
-
const splitJWT = jwt.split('.');
|
|
74
|
-
if (splitJWT.length !== 3) return null;
|
|
75
|
-
return {
|
|
76
|
-
header: splitJWT[0],
|
|
77
|
-
payload: splitJWT[1],
|
|
78
|
-
signature: splitJWT[2],
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Turns object into url safe string
|
|
84
|
-
* @param object
|
|
85
|
-
* @return {string}
|
|
86
|
-
*/
|
|
87
|
-
export const objectToBase64UrlSafeString = (object: any): string => {
|
|
88
|
-
let stringAscii = JSON.stringify(object);
|
|
89
|
-
let base64String = asciiToBase64(stringAscii);
|
|
90
|
-
return makeStringUrlSafe(base64String);
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Turns base64 into object
|
|
95
|
-
* @param urlSafeBase64String
|
|
96
|
-
* @return {any}
|
|
97
|
-
*/
|
|
98
|
-
export const urlSafeBase64ToObject = (urlSafeBase64String: string): any => {
|
|
99
|
-
let base64String = reverseStringUrlSafe(urlSafeBase64String);
|
|
100
|
-
let stringAscii = base64ToAscii(base64String);
|
|
101
|
-
return JSON.parse(stringAscii);
|
|
102
|
-
};
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import * as assert from 'assert';
|
|
2
|
-
import * as cryptoUtilAuth from '../src';
|
|
3
|
-
import * as keys from './keys/keys';
|
|
4
|
-
|
|
5
|
-
describe('CryptoUtilAuth test', function () {
|
|
6
|
-
it('createBase64SignatureOfToken returns base64 signature of token', function () {
|
|
7
|
-
const algorithm = 'SHA256';
|
|
8
|
-
const token = 'Hi I am token';
|
|
9
|
-
const signature =
|
|
10
|
-
'G3uHnG5DIoi3YWaj+umNmCtzAfBMmxAGfkWxlXP9qTfEr48qJjIVIdD5ic5T9YSDMt+6+XsembuL2NP6h4xoe+qE/wRjNKXCF6Hg/VvBciOdZyUqX8TaiAbGsh6J2d42rjX1vchrqfrBgCW5kiyeZcTic8LQeNdL/2gO+F9bW8A=';
|
|
11
|
-
|
|
12
|
-
const returnedSignature = cryptoUtilAuth.createBase64SignatureOfToken(
|
|
13
|
-
token,
|
|
14
|
-
keys.privateKey,
|
|
15
|
-
algorithm,
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
assert.deepStrictEqual(returnedSignature, signature);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('verifyBase64SignatureOfToken returns true or false', function () {
|
|
22
|
-
const algorithm = 'SHA256';
|
|
23
|
-
const token = 'Hi I am token';
|
|
24
|
-
const signature =
|
|
25
|
-
'G3uHnG5DIoi3YWaj+umNmCtzAfBMmxAGfkWxlXP9qTfEr48qJjIVIdD5ic5T9YSDMt+6+XsembuL2NP6h4xoe+qE/wRjNKXCF6Hg/VvBciOdZyUqX8TaiAbGsh6J2d42rjX1vchrqfrBgCW5kiyeZcTic8LQeNdL/2gO+F9bW8A=';
|
|
26
|
-
const temperedSignature = 'temper' + signature;
|
|
27
|
-
const expectedValueTrue = true;
|
|
28
|
-
const expectedValueFalse = false;
|
|
29
|
-
|
|
30
|
-
const returnedValue = cryptoUtilAuth.verifyBase64SignatureOfToken(
|
|
31
|
-
token,
|
|
32
|
-
signature,
|
|
33
|
-
keys.publicKey,
|
|
34
|
-
algorithm,
|
|
35
|
-
);
|
|
36
|
-
const returnedValueFalse = cryptoUtilAuth.verifyBase64SignatureOfToken(
|
|
37
|
-
token,
|
|
38
|
-
temperedSignature,
|
|
39
|
-
keys.publicKey,
|
|
40
|
-
algorithm,
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
assert.deepStrictEqual(returnedValue, expectedValueTrue);
|
|
44
|
-
assert.deepStrictEqual(returnedValueFalse, expectedValueFalse);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('createHmacBase64 returns base 64 hmac', function () {
|
|
48
|
-
const algorithm = 'SHA256';
|
|
49
|
-
const token = 'Hi I am token';
|
|
50
|
-
const secret = 'My secret';
|
|
51
|
-
const expectedHmacBase64 = 'IpOkaPa1YPTXQYPr6adIGk3ACgeqWyV+nvB4+7Ox4Dg=';
|
|
52
|
-
|
|
53
|
-
const returnedHmacBase64 = cryptoUtilAuth.createHmacBase64(token, secret, algorithm);
|
|
54
|
-
|
|
55
|
-
assert.deepStrictEqual(returnedHmacBase64, expectedHmacBase64);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('createSaltBase64 returns random base 64 string', function () {
|
|
59
|
-
const randomSalt = cryptoUtilAuth.createSaltBase64();
|
|
60
|
-
|
|
61
|
-
assert.deepStrictEqual(randomSalt.length, 44);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('encryptStringAsciiToBase64 returns base 64 and encrypted string', function () {
|
|
65
|
-
const plainTextString = 'This is some text for encryption';
|
|
66
|
-
const encryptedString = 'juggjf+C81QzXvqa8qE1GHTbrMQydtoFszKw2kFjGDduCpXwS01cVnYyYl9an7l7';
|
|
67
|
-
const salt = 'my salt';
|
|
68
|
-
const secret = 'top secret';
|
|
69
|
-
const algorithm = 'aes-192-cbc';
|
|
70
|
-
|
|
71
|
-
const encryptedText = cryptoUtilAuth.encryptStringAsciiToBase64(
|
|
72
|
-
plainTextString,
|
|
73
|
-
salt,
|
|
74
|
-
secret,
|
|
75
|
-
algorithm,
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
assert.deepStrictEqual(encryptedText, encryptedString);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('decryptStringBase64ToAscii returns ascii string', function () {
|
|
82
|
-
const encryptedString = 'juggjf+C81QzXvqa8qE1GHTbrMQydtoFszKw2kFjGDduCpXwS01cVnYyYl9an7l7';
|
|
83
|
-
const plainTextString = 'This is some text for encryption';
|
|
84
|
-
const salt = 'my salt';
|
|
85
|
-
const secret = 'top secret';
|
|
86
|
-
const algorithm = 'aes-192-cbc';
|
|
87
|
-
|
|
88
|
-
const encryptedText = cryptoUtilAuth.decryptStringBase64ToAscii(
|
|
89
|
-
encryptedString,
|
|
90
|
-
salt,
|
|
91
|
-
secret,
|
|
92
|
-
algorithm,
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
assert.deepStrictEqual(encryptedText, plainTextString);
|
|
96
|
-
});
|
|
97
|
-
});
|
package/tests/index.test.ts
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import * as assert from 'assert';
|
|
2
|
-
import * as jwtUtilAuth from '../src/jwtUtilAuth';
|
|
3
|
-
import * as pwdUtilAuth from '../src/pwdUtilAuth';
|
|
4
|
-
import * as strEncryptUtil from '../src/strEncryptUtil';
|
|
5
|
-
import * as keys from './keys/keys';
|
|
6
|
-
|
|
7
|
-
describe('Index/JwtUtilAuth', function () {
|
|
8
|
-
it('createSignedJwtFromObject returns base64 url safe jwt', function () {
|
|
9
|
-
const header = {
|
|
10
|
-
alg: 'SHA512',
|
|
11
|
-
typ: 'JWT',
|
|
12
|
-
};
|
|
13
|
-
const payload = {
|
|
14
|
-
sub: '1234567890',
|
|
15
|
-
name: 'John Doe',
|
|
16
|
-
iat: 1516239022,
|
|
17
|
-
cpso: '81883',
|
|
18
|
-
roles: ['ph', 'ea'],
|
|
19
|
-
};
|
|
20
|
-
const expectedJwt =
|
|
21
|
-
'eyJhbGciOiJTSEE1MTIiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJjcHNvIjoiODE4ODMiLCJyb2xlcyI6WyJwaCIsImVhIl19.PWff8BvKP79ukuZrGEhyIw4HN86m99l4VZo9xL_Ul5EHQFC1RsEvxUig4z2sUZqAvQLcQjEhNR7hf0KkB7YeJTWZF4QLRX6GwC5SvE2kryrYSlZvop2SCbYdty38gzDw3xTdDzcJo0awE45Sk_ZlRnjgcDD-wXAW3i7ToXRcPxM';
|
|
22
|
-
|
|
23
|
-
const createdJwt = jwtUtilAuth.createSignedJwtFromObject(header, payload, keys.privateKey);
|
|
24
|
-
|
|
25
|
-
assert.deepStrictEqual(createdJwt, expectedJwt);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('verifyJwtSignature returns true or false', function () {
|
|
29
|
-
const jwt =
|
|
30
|
-
'eyJhbGciOiJTSEE1MTIiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJjcHNvIjoiODE4ODMiLCJyb2xlcyI6WyJwaCIsImVhIl19.PWff8BvKP79ukuZrGEhyIw4HN86m99l4VZo9xL_Ul5EHQFC1RsEvxUig4z2sUZqAvQLcQjEhNR7hf0KkB7YeJTWZF4QLRX6GwC5SvE2kryrYSlZvop2SCbYdty38gzDw3xTdDzcJo0awE45Sk_ZlRnjgcDD-wXAW3i7ToXRcPxM';
|
|
31
|
-
|
|
32
|
-
const isVerified = jwtUtilAuth.verifyJwtSignature(jwt, keys.publicKey);
|
|
33
|
-
|
|
34
|
-
assert.deepStrictEqual(isVerified, true);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('getHeaderPayloadFromJwt returns header, payload object', function () {
|
|
38
|
-
const jwt =
|
|
39
|
-
'eyJhbGciOiJTSEE1MTIiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJjcHNvIjoiODE4ODMiLCJyb2xlcyI6WyJwaCIsImVhIl19.PWff8BvKP79ukuZrGEhyIw4HN86m99l4VZo9xL_Ul5EHQFC1RsEvxUig4z2sUZqAvQLcQjEhNR7hf0KkB7YeJTWZF4QLRX6GwC5SvE2kryrYSlZvop2SCbYdty38gzDw3xTdDzcJo0awE45Sk_ZlRnjgcDD-wXAW3i7ToXRcPxM';
|
|
40
|
-
|
|
41
|
-
const expectedHeader = {
|
|
42
|
-
alg: 'SHA512',
|
|
43
|
-
typ: 'JWT',
|
|
44
|
-
};
|
|
45
|
-
const expectedPayload = {
|
|
46
|
-
sub: '1234567890',
|
|
47
|
-
name: 'John Doe',
|
|
48
|
-
iat: 1516239022,
|
|
49
|
-
cpso: '81883',
|
|
50
|
-
roles: ['ph', 'ea'],
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const { header, payload } = jwtUtilAuth.getHeaderPayloadFromJwt(jwt);
|
|
54
|
-
|
|
55
|
-
assert.deepStrictEqual(header, expectedHeader);
|
|
56
|
-
assert.deepStrictEqual(payload, expectedPayload);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe('Index/PwdUtilAuth', function () {
|
|
61
|
-
it('createPasswordHashWithRandomSalt called with save hash', function () {
|
|
62
|
-
const password = 'mySecretPassword';
|
|
63
|
-
const secret = 'bigSecret';
|
|
64
|
-
const algorithm = 'sha512';
|
|
65
|
-
|
|
66
|
-
const hash = pwdUtilAuth.createPasswordHashWithRandomSalt(password, secret, algorithm);
|
|
67
|
-
|
|
68
|
-
assert.deepStrictEqual(hash.length > 40, true);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('createPasswordHashBasedOnSavedAlgorithmSalt called with saved hash', function () {
|
|
72
|
-
const savedHash =
|
|
73
|
-
'$1$c2hhNTEy$SOk/04Wn/ce1YIXHlUIqt5SgsuCCLIFjxpzHloVSxFh/z8JuLFshAaGNCkIRf47QSPCOJpkJ476N2eq1Yg1+yg==$6h29BnpUkqfrmtnY1xUrAGZcpcAl5cUEJ4Qjj+BGXbo=$';
|
|
74
|
-
const password = 'mySecretPassword';
|
|
75
|
-
const secret = 'bigSecret';
|
|
76
|
-
|
|
77
|
-
const hash = pwdUtilAuth.createPasswordHashBasedOnSavedAlgorithmSalt(
|
|
78
|
-
password,
|
|
79
|
-
savedHash,
|
|
80
|
-
secret,
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
assert.deepStrictEqual(hash, savedHash);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('Index/strEncryptUtil', function () {
|
|
88
|
-
it('encryptByPrivateKey', function () {
|
|
89
|
-
const textToEncrypt = 'Asymmetric encryption';
|
|
90
|
-
const expectedEncryptedString =
|
|
91
|
-
'VtwwLocyYdCreTBRifUmFuLRQ3Lrmw0RxDEN9zQh9lTJ2+6K/iLj7F5TDqm10hIKtfeajacs5HgEPGLb4whSpy7ggMtCNZQoujJNElNq2d7TScquYWi34cGlURzNTIUqC66afYYF2djq1QNVkWMzrnLMztrHem09+VlmA+eGLdc=';
|
|
92
|
-
const encryptionConfigObj = {
|
|
93
|
-
cipherAlgorithm: 'aes-256-cbc',
|
|
94
|
-
keyLength: 32,
|
|
95
|
-
privateKey: keys.privateKey,
|
|
96
|
-
plainTextEncoding: 'utf8',
|
|
97
|
-
encryptedTextEncoding: 'base64',
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const encryptedString = strEncryptUtil.encryptByPrivateKey(encryptionConfigObj, textToEncrypt);
|
|
101
|
-
|
|
102
|
-
assert.deepStrictEqual(encryptedString, expectedEncryptedString);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('decryptByPublicKey', function () {
|
|
106
|
-
const inputEncryptedString =
|
|
107
|
-
'VtwwLocyYdCreTBRifUmFuLRQ3Lrmw0RxDEN9zQh9lTJ2+6K/iLj7F5TDqm10hIKtfeajacs5HgEPGLb4whSpy7ggMtCNZQoujJNElNq2d7TScquYWi34cGlURzNTIUqC66afYYF2djq1QNVkWMzrnLMztrHem09+VlmA+eGLdc=';
|
|
108
|
-
const expectedText = 'Asymmetric encryption';
|
|
109
|
-
const decryptionConfigObj = {
|
|
110
|
-
cipherAlgorithm: 'aes-256-cbc',
|
|
111
|
-
keyLength: 32,
|
|
112
|
-
publicKey: keys.publicKey,
|
|
113
|
-
plainTextEncoding: 'utf8',
|
|
114
|
-
encryptedTextEncoding: 'base64',
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const decryptedString = strEncryptUtil.decryptByPublicKey(
|
|
118
|
-
decryptionConfigObj,
|
|
119
|
-
inputEncryptedString,
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
assert.deepStrictEqual(decryptedString, expectedText);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('encryptByKey', function () {
|
|
126
|
-
const textToEncrypt = 'This is some text for encryption';
|
|
127
|
-
const expectedEncryptedString =
|
|
128
|
-
'/RMgsfS/ANEngXOwjFDYqxutOLnaY7XxDiJK403KZTcp8D76qPzwUYcYAF+lle4I';
|
|
129
|
-
const encryptConfigObj = {
|
|
130
|
-
cipherAlgorithm: 'aes-256-cbc',
|
|
131
|
-
keyLength: 32,
|
|
132
|
-
encryptionKey: keys.privateKey,
|
|
133
|
-
plainTextEncoding: 'utf8',
|
|
134
|
-
encryptedTextEncoding: 'base64',
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const encryptedString = strEncryptUtil.encryptByKey(encryptConfigObj, textToEncrypt);
|
|
138
|
-
|
|
139
|
-
assert.deepStrictEqual(encryptedString, expectedEncryptedString);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('decryptByKey', function () {
|
|
143
|
-
const encryptedString = '/RMgsfS/ANEngXOwjFDYqxutOLnaY7XxDiJK403KZTcp8D76qPzwUYcYAF+lle4I';
|
|
144
|
-
const expectedText = 'This is some text for encryption';
|
|
145
|
-
const encryptConfigObj = {
|
|
146
|
-
cipherAlgorithm: 'aes-256-cbc',
|
|
147
|
-
keyLength: 32,
|
|
148
|
-
encryptionKey: keys.privateKey,
|
|
149
|
-
plainTextEncoding: 'utf8',
|
|
150
|
-
encryptedTextEncoding: 'base64',
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const decryptedString = strEncryptUtil.decryptByKey(encryptConfigObj, encryptedString);
|
|
154
|
-
|
|
155
|
-
assert.deepStrictEqual(decryptedString, expectedText);
|
|
156
|
-
});
|
|
157
|
-
});
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import * as assert from 'assert';
|
|
2
|
-
import * as stringUtilAuth from '../src/stringUtilAuth';
|
|
3
|
-
|
|
4
|
-
describe('StringUtilAuth test', function () {
|
|
5
|
-
it('makeStringUrlSafe returns url safe string', function (done) {
|
|
6
|
-
const urlUnsafeString = 'eyJhbGciOiJzaGE1MTIiL/CJ0e+XAiOiJKV1QifQ.eyJpZkkCI6IjEyMz===';
|
|
7
|
-
const urlSafeString = 'eyJhbGciOiJzaGE1MTIiL_CJ0e-XAiOiJKV1QifQ.eyJpZkkCI6IjEyMz';
|
|
8
|
-
|
|
9
|
-
const returnedString = stringUtilAuth.makeStringUrlSafe(urlUnsafeString);
|
|
10
|
-
assert.deepStrictEqual(returnedString, urlSafeString);
|
|
11
|
-
done();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('reverseStringUrlSafe returns url safe string', function (done) {
|
|
15
|
-
const urlSafeString = 'eyJhbGciOiJzaGE1MTIiL_CJ0e-XAiOiJKV1QifQ.eyJpZkkCI6IjEyMz';
|
|
16
|
-
const urlUnsafeString = 'eyJhbGciOiJzaGE1MTIiL/CJ0e+XAiOiJKV1QifQ.eyJpZkkCI6IjEyMz===';
|
|
17
|
-
|
|
18
|
-
const returnedString = stringUtilAuth.reverseStringUrlSafe(urlSafeString);
|
|
19
|
-
assert.deepStrictEqual(returnedString, urlUnsafeString);
|
|
20
|
-
done();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('asciiToBase64 returns base 64 string', function (done) {
|
|
24
|
-
const asciiString = 'How are you';
|
|
25
|
-
const base64String = 'SG93IGFyZSB5b3U=';
|
|
26
|
-
|
|
27
|
-
const returnedString = stringUtilAuth.asciiToBase64(asciiString);
|
|
28
|
-
assert.deepStrictEqual(returnedString, base64String);
|
|
29
|
-
done();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('base64ToAscii returns ascii string', function (done) {
|
|
33
|
-
const base64String = 'SG93IGFyZSB5b3U=';
|
|
34
|
-
const asciiString = 'How are you';
|
|
35
|
-
|
|
36
|
-
const returnedString = stringUtilAuth.base64ToAscii(base64String);
|
|
37
|
-
assert.deepStrictEqual(returnedString, asciiString);
|
|
38
|
-
done();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('dollarSignConnectedStringToAlgorithmHashSalt split at $ returns object', function (done) {
|
|
42
|
-
const inputHash = '$1$c2hhNTEy$eyJhbGciOiJzaG$OiJzaGE1MTIiL$';
|
|
43
|
-
const expectedObject = {
|
|
44
|
-
version: '1',
|
|
45
|
-
alg: 'c2hhNTEy',
|
|
46
|
-
hash: 'eyJhbGciOiJzaG',
|
|
47
|
-
salt: 'OiJzaGE1MTIiL',
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const returnedObject = stringUtilAuth.dollarSignConnectedStringToAlgorithmHashSalt(inputHash);
|
|
51
|
-
assert.deepStrictEqual(returnedObject, expectedObject);
|
|
52
|
-
done();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('dotConnectedStringToHeaderPayloadSignature split at . returns object', function (done) {
|
|
56
|
-
const inputString = 'c2hhNTEy.eyJhbGciOiJzaG.OiJzaGE1MTIiL';
|
|
57
|
-
const expectedObject = {
|
|
58
|
-
header: 'c2hhNTEy',
|
|
59
|
-
payload: 'eyJhbGciOiJzaG',
|
|
60
|
-
signature: 'OiJzaGE1MTIiL',
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const returnedObject = stringUtilAuth.dotConnectedStringToHeaderPayloadSignature(inputString);
|
|
64
|
-
assert.deepStrictEqual(expectedObject, returnedObject);
|
|
65
|
-
done();
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('objectToBase64UrlSafeString returns url safe base64 string', function (done) {
|
|
69
|
-
const object = {
|
|
70
|
-
header: {
|
|
71
|
-
alg: 'HS512',
|
|
72
|
-
typ: 'JWT',
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
const expectedBase64String = 'eyJoZWFkZXIiOnsiYWxnIjoiSFM1MTIiLCJ0eXAiOiJKV1QifX0';
|
|
76
|
-
|
|
77
|
-
const returnedBase64String = stringUtilAuth.objectToBase64UrlSafeString(object);
|
|
78
|
-
assert.deepStrictEqual(returnedBase64String, expectedBase64String);
|
|
79
|
-
done();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('urlSafeBase64ToObject returns object', function (done) {
|
|
83
|
-
const base64String = 'eyJoZWFkZXIiOnsiYWxnIjoiSFM1MTIiLCJ0eXAiOiJKV1QifX0';
|
|
84
|
-
const expectedObject = {
|
|
85
|
-
header: {
|
|
86
|
-
alg: 'HS512',
|
|
87
|
-
typ: 'JWT',
|
|
88
|
-
},
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const returnedObject = stringUtilAuth.urlSafeBase64ToObject(base64String);
|
|
92
|
-
assert.deepStrictEqual(returnedObject, expectedObject);
|
|
93
|
-
done();
|
|
94
|
-
});
|
|
95
|
-
});
|