aes256-async 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -0
- package/README.md +118 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +1 -0
- package/dist/shared/constants.d.ts +11 -0
- package/dist/shared/constants.js +1 -0
- package/dist/shared/errors.d.ts +5 -0
- package/dist/shared/errors.js +1 -0
- package/dist/utils/index.d.ts +42 -0
- package/dist/utils/index.js +1 -0
- package/dist/validations/index.d.ts +35 -0
- package/dist/validations/index.js +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Jesus Graterol
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# AES-256 Async
|
2
|
+
|
3
|
+
The `aes256-async` package allows developers to easily encrypt and decrypt data by making use of the [AES-256](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) specification. It exposes syncrhonous and asynchronous functions to avoid blocking the main thread. Moreover, the secret can be of any size because it is hashed using the [Secure Hash Algorithm 2 (SHA-256)](https://en.wikipedia.org/wiki/SHA-2).
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
</br>
|
10
|
+
|
11
|
+
## Getting Started
|
12
|
+
|
13
|
+
Install the package:
|
14
|
+
```bash
|
15
|
+
npm install -S aes256-async
|
16
|
+
```
|
17
|
+
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Encrypt and decrypt data asynchronously:
|
22
|
+
|
23
|
+
```typescript
|
24
|
+
import { encrypt, decrypt } from 'aes256-async';
|
25
|
+
|
26
|
+
const secret = 'My.$ecreT';
|
27
|
+
|
28
|
+
await encrypt(secret, 'Hello world!')
|
29
|
+
// OrGfQ/91d7p/1BN6Q07Jly5ZK0/7pyczjk5vgw==
|
30
|
+
|
31
|
+
await decrypt(secret, 'OrGfQ/91d7p/1BN6Q07Jly5ZK0/7pyczjk5vgw==')
|
32
|
+
// 'Hello world!'
|
33
|
+
```
|
34
|
+
|
35
|
+
|
36
|
+
Encrypt and decrypt data synchronously (blocking the main thread):
|
37
|
+
|
38
|
+
```typescript
|
39
|
+
import { encryptSync, decryptSync } from 'aes256-async';
|
40
|
+
|
41
|
+
const secret = 'My.$ecreT';
|
42
|
+
|
43
|
+
encryptSync(secret, 'Hello world!')
|
44
|
+
// OrGfQ/91d7p/1BN6Q07Jly5ZK0/7pyczjk5vgw==
|
45
|
+
|
46
|
+
decryptSync(secret, 'OrGfQ/91d7p/1BN6Q07Jly5ZK0/7pyczjk5vgw==')
|
47
|
+
// 'Hello world!'
|
48
|
+
```
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
<br/>
|
55
|
+
|
56
|
+
## Built With
|
57
|
+
|
58
|
+
- TypeScript
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
<br/>
|
65
|
+
|
66
|
+
## Acknowledgements
|
67
|
+
|
68
|
+
- [JamesMGreene/node-aes256](https://github.com/JamesMGreene/node-aes256)
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
<br/>
|
74
|
+
|
75
|
+
## Running the Tests
|
76
|
+
|
77
|
+
```bash
|
78
|
+
# integration tests
|
79
|
+
npm run test:integration
|
80
|
+
|
81
|
+
# unit tests
|
82
|
+
npm run test:unit
|
83
|
+
```
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
<br/>
|
90
|
+
|
91
|
+
## License
|
92
|
+
|
93
|
+
[MIT](https://choosealicense.com/licenses/mit/)
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
<br/>
|
100
|
+
|
101
|
+
## Deployment
|
102
|
+
|
103
|
+
Install dependencies:
|
104
|
+
```bash
|
105
|
+
npm install
|
106
|
+
```
|
107
|
+
|
108
|
+
|
109
|
+
Build the library:
|
110
|
+
```bash
|
111
|
+
npm start
|
112
|
+
```
|
113
|
+
|
114
|
+
|
115
|
+
Publish to `npm`:
|
116
|
+
```bash
|
117
|
+
npm publish
|
118
|
+
```
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
/**
|
2
|
+
* Decrypts an encrypted message back to readable text.
|
3
|
+
* @param secret
|
4
|
+
* @param encryptedData
|
5
|
+
* @returns Promise<string>
|
6
|
+
* @throws
|
7
|
+
* - INVALID_OR_EMPTY_DATA: if the data is not a string or is an empty string.
|
8
|
+
* - INVALID_SECRET: if the secret is not a string or is an empty string.
|
9
|
+
* - INVALID_ENCRYPTED_DATA: if the encrypted data decrypts to an invalid or empty string.
|
10
|
+
* - WRONG_SECRET: if the data cannot be decrypted.
|
11
|
+
*/
|
12
|
+
declare const decrypt: (secret: string, encryptedData: string) => Promise<string>;
|
13
|
+
/**
|
14
|
+
* Encrypts a message to a piece of text that cannot be read unless it is decrypted with the secret
|
15
|
+
* that was used to encrypt it.
|
16
|
+
* @param secret
|
17
|
+
* @param data
|
18
|
+
* @returns Promise<string>
|
19
|
+
* @throws
|
20
|
+
* - INVALID_OR_EMPTY_DATA: if the data is not a string or is an empty string.
|
21
|
+
* - INVALID_SECRET: if the secret is not a string or is an empty string.
|
22
|
+
* - CORRUPTED_DATA: if the decrypted data does not match the original data.
|
23
|
+
* - WRONG_SECRET: if the data cannot be decrypted.
|
24
|
+
*/
|
25
|
+
declare const encrypt: (secret: string, data: string) => Promise<string>;
|
26
|
+
/**
|
27
|
+
* Decrypts an encrypted message back to readable text.
|
28
|
+
* @param secret
|
29
|
+
* @param encryptedData
|
30
|
+
* @returns string
|
31
|
+
* @throws
|
32
|
+
* - INVALID_OR_EMPTY_DATA: if the data is not a string or is an empty string.
|
33
|
+
* - INVALID_SECRET: if the secret is not a string or is an empty string.
|
34
|
+
* - INVALID_ENCRYPTED_DATA: if the encrypted data decrypts to an invalid or empty string.
|
35
|
+
* - WRONG_SECRET: if the data cannot be decrypted.
|
36
|
+
*/
|
37
|
+
declare const decryptSync: (secret: string, encryptedData: string) => string;
|
38
|
+
/**
|
39
|
+
* Encrypts a message to a piece of text that cannot be read unless it is decrypted with the secret
|
40
|
+
* that was used to encrypt it.
|
41
|
+
* @param secret
|
42
|
+
* @param data
|
43
|
+
* @returns string
|
44
|
+
* @throws
|
45
|
+
* - INVALID_OR_EMPTY_DATA: if the data is not a string or is an empty string.
|
46
|
+
* - INVALID_SECRET: if the secret is not a string or is an empty string.
|
47
|
+
* - CORRUPTED_DATA: if the decrypted data does not match the original data.
|
48
|
+
* - WRONG_SECRET: if the data cannot be decrypted.
|
49
|
+
*/
|
50
|
+
declare const encryptSync: (secret: string, data: string) => string;
|
51
|
+
export { decrypt, encrypt, decryptSync, encryptSync, };
|
package/dist/index.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
import{Buffer}from"node:buffer";import{decryptData,encryptData,decryptDataSync,encryptDataSync}from"./utils/index.js";import{validateInput,validateEncryptedBuffer,validateDecryptedData,validateEncryptionResult}from"./validations/index.js";const decrypt=async(t,a)=>{validateInput(t,a);const e=Buffer.from(a,"base64");validateEncryptedBuffer(e);const r=await decryptData(t,e);return validateDecryptedData(r),r},encrypt=async(t,a)=>{validateInput(t,a);const e=await encryptData(t,a);return validateEncryptionResult(a,await decrypt(t,e)),e},decryptSync=(t,a)=>{validateInput(t,a);const e=Buffer.from(a,"base64");validateEncryptedBuffer(e);const r=decryptDataSync(t,e);return validateDecryptedData(r),r},encryptSync=(t,a)=>{validateInput(t,a);const e=encryptDataSync(t,a);return validateEncryptionResult(a,decryptSync(t,e)),e};export{decrypt,encrypt,decryptSync,encryptSync};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
declare const CIPHER_ALGORITHM = "aes-256-ctr";
|
2
|
+
declare const HASHING_ALGORITHM = "sha256";
|
3
|
+
/**
|
4
|
+
* Illegal Character
|
5
|
+
* Many web pages and other document formats use UTF-8. This is the default character encoding.
|
6
|
+
* When decoding a Buffer into a string that does not exclusively contain valid UTF-8 data, the
|
7
|
+
* Unicode replacement character U+FFFD � will be used to represent those errors.
|
8
|
+
* https://nodejs.org/docs/latest/api/buffer.html#buffers-and-character-encodings
|
9
|
+
*/
|
10
|
+
declare const ILLEGAL_CHARACTER = "\uFFFD";
|
11
|
+
export { CIPHER_ALGORITHM, HASHING_ALGORITHM, ILLEGAL_CHARACTER, };
|
@@ -0,0 +1 @@
|
|
1
|
+
const CIPHER_ALGORITHM="aes-256-ctr",HASHING_ALGORITHM="sha256",ILLEGAL_CHARACTER="�";export{CIPHER_ALGORITHM,HASHING_ALGORITHM,ILLEGAL_CHARACTER};
|
@@ -0,0 +1 @@
|
|
1
|
+
const ERRORS={INVALID_OR_EMPTY_DATA:"INVALID_OR_EMPTY_DATA",INVALID_SECRET:"INVALID_SECRET",INVALID_ENCRYPTED_DATA:"INVALID_ENCRYPTED_DATA",WRONG_SECRET:"WRONG_SECRET",CORRUPTED_DATA:"CORRUPTED_DATA"};export{ERRORS};
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
2
|
+
/**
|
3
|
+
* Hashes the provided secret using the SHA-256 algorithm.
|
4
|
+
* @param secret
|
5
|
+
* @returns Promise<Buffer>
|
6
|
+
*/
|
7
|
+
declare const __hashSecret: (secret: string) => Promise<Buffer>;
|
8
|
+
/**
|
9
|
+
* Hashes the provided secret using the SHA-256 algorithm.
|
10
|
+
* @param secret
|
11
|
+
* @returns Buffer
|
12
|
+
*/
|
13
|
+
declare const __hashSecretSync: (secret: string) => Buffer;
|
14
|
+
/**
|
15
|
+
* Creates the cipher with random initialization vectors and returns the encrypted data.
|
16
|
+
* @param secret
|
17
|
+
* @param data
|
18
|
+
* @returns Promise<string>
|
19
|
+
*/
|
20
|
+
declare const encryptData: (secret: string, data: string) => Promise<string>;
|
21
|
+
/**
|
22
|
+
* Creates the cipher with random initialization vectors and returns the encrypted data.
|
23
|
+
* @param secret
|
24
|
+
* @param data
|
25
|
+
* @returns string
|
26
|
+
*/
|
27
|
+
declare const encryptDataSync: (secret: string, data: string) => string;
|
28
|
+
/**
|
29
|
+
* Creates the decipher and returns the result of the decryption.
|
30
|
+
* @param secret
|
31
|
+
* @param encryptedData
|
32
|
+
* @returns Promise<string>
|
33
|
+
*/
|
34
|
+
declare const decryptData: (secret: string, encryptedData: Buffer) => Promise<string>;
|
35
|
+
/**
|
36
|
+
* Creates the decipher and returns the result of the decryption.
|
37
|
+
* @param secret
|
38
|
+
* @param encryptedData
|
39
|
+
* @returns string
|
40
|
+
*/
|
41
|
+
declare const decryptDataSync: (secret: string, encryptedData: Buffer) => string;
|
42
|
+
export { __hashSecret, __hashSecretSync, encryptData, encryptDataSync, decryptData, decryptDataSync, };
|
@@ -0,0 +1 @@
|
|
1
|
+
import{Buffer}from"node:buffer";import crypto from"node:crypto";import{CIPHER_ALGORITHM,HASHING_ALGORITHM}from"../shared/constants.js";const __hashSecret=r=>new Promise(((t,e)=>{const a=crypto.createHash(HASHING_ALGORITHM);a.on("readable",(()=>{const r=a.read();r&&t(r)})),a.on("error",(r=>e(r))),a.write(r),a.end()})),__hashSecretSync=r=>{const t=crypto.createHash(HASHING_ALGORITHM);return t.update(r),t.digest()},encryptData=async(r,t)=>{const e=crypto.randomBytes(16),a=crypto.createCipheriv(CIPHER_ALGORITHM,await __hashSecret(r),e),c=Buffer.from(t),n=a.update(c);return Buffer.concat([e,n,a.final()]).toString("base64")},encryptDataSync=(r,t)=>{const e=crypto.randomBytes(16),a=crypto.createCipheriv(CIPHER_ALGORITHM,__hashSecretSync(r),e),c=Buffer.from(t),n=a.update(c);return Buffer.concat([e,n,a.final()]).toString("base64")},decryptData=async(r,t)=>{const e=t.subarray(0,16),a=await __hashSecret(r),c=crypto.createDecipheriv(CIPHER_ALGORITHM,a,e),n=t.subarray(16);return Buffer.concat([c.update(n),c.final()]).toString()},decryptDataSync=(r,t)=>{const e=t.subarray(0,16),a=crypto.createDecipheriv(CIPHER_ALGORITHM,__hashSecretSync(r),e),c=t.subarray(16);return Buffer.concat([a.update(c),a.final()]).toString()};export{__hashSecret,__hashSecretSync,encryptData,encryptDataSync,decryptData,decryptDataSync};
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
2
|
+
/**
|
3
|
+
* Ensures the data and the secret are valid strings.
|
4
|
+
* @param secret
|
5
|
+
* @param data
|
6
|
+
* @throws
|
7
|
+
* - INVALID_OR_EMPTY_DATA: if the data is not a string or is an empty string.
|
8
|
+
* - INVALID_SECRET: if the secret is not a string or is an empty string.
|
9
|
+
*/
|
10
|
+
declare const validateInput: (secret: string, data: string) => void;
|
11
|
+
/**
|
12
|
+
* Ensures the encrypted data is a valid string.
|
13
|
+
* @param input
|
14
|
+
* @throws
|
15
|
+
* - INVALID_ENCRYPTED_DATA: if the encrypted data decrypts to an invalid or empty string.
|
16
|
+
*/
|
17
|
+
declare const validateEncryptedBuffer: (input: Buffer) => void;
|
18
|
+
/**
|
19
|
+
* Ensures the decrypted data is valid. So far, whenever an incorrect secret is provided, Node.js
|
20
|
+
* returns a string containing characters like �.
|
21
|
+
* @param data
|
22
|
+
* @throws
|
23
|
+
* - WRONG_SECRET: if the data cannot be decrypted.
|
24
|
+
*/
|
25
|
+
declare const validateDecryptedData: (data: string) => void;
|
26
|
+
/**
|
27
|
+
* Compares the original data with the decrypted data to ensure the data was and can be decrypted
|
28
|
+
* correctly in the future.
|
29
|
+
* @param data
|
30
|
+
* @param decryptedData
|
31
|
+
* @throws
|
32
|
+
* - CORRUPTED_DATA: if the decrypted data does not match the original data.
|
33
|
+
*/
|
34
|
+
declare const validateEncryptionResult: (data: string, decryptedData: string) => void;
|
35
|
+
export { validateInput, validateEncryptedBuffer, validateDecryptedData, validateEncryptionResult, };
|
@@ -0,0 +1 @@
|
|
1
|
+
import{encodeError}from"error-message-utils";import{ILLEGAL_CHARACTER}from"../shared/constants.js";import{ERRORS}from"../shared/errors.js";const __validateSecret=e=>{if("string"!=typeof e||0===e.length)throw new Error(encodeError("The provided secret is invalid, please make sure to provide a non-empty string.",ERRORS.INVALID_SECRET))},__validateData=e=>{if("string"!=typeof e||0===e.length||e.includes(ILLEGAL_CHARACTER))throw new Error(encodeError("The provided data is invalid, please make sure to provide a non-empty string that only contains UTF-8 character encoding.",ERRORS.INVALID_OR_EMPTY_DATA))},validateInput=(e,r)=>{__validateSecret(e),__validateData(r)},validateEncryptedBuffer=e=>{if(e.length<17)throw new Error(encodeError("The provided encrypted data must decrypt to a non-empty string.",ERRORS.INVALID_ENCRYPTED_DATA))},validateDecryptedData=e=>{if("string"!=typeof e||0===e.length||e.includes(ILLEGAL_CHARACTER))throw new Error(encodeError("Failed to decrypt the data with the provided secret.",ERRORS.WRONG_SECRET))},validateEncryptionResult=(e,r)=>{if(e!==r)throw new Error(encodeError("The data could not be decrypted correctly.",ERRORS.CORRUPTED_DATA))};export{validateInput,validateEncryptedBuffer,validateDecryptedData,validateEncryptionResult};
|
package/package.json
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
{
|
2
|
+
"name": "aes256-async",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "The aes256-async package allows developers to easily encrypt and decrypt data by making use of the AES-256 specification. It exposes syncrhonous and asynchronous functions to avoid blocking the main thread. Moreover, the secret can be of any size because it is hashed using the Secure Hash Algorithm 2 (SHA-256).",
|
5
|
+
"private": false,
|
6
|
+
"type": "module",
|
7
|
+
"main": "dist/index.js",
|
8
|
+
"types": "dist/index.d.ts",
|
9
|
+
"scripts": {
|
10
|
+
"start": "ts-lib-builder --tsconfig=tsconfig.build.json",
|
11
|
+
"test": "echo \"Error: tests are executed with npm run test:(e2e|integration|unit|bench)\" && exit 1",
|
12
|
+
"test:e2e": "vitest run --config=vitest.test-e2e.config.ts",
|
13
|
+
"test:integration": "vitest run --config vitest.test-integration.config.ts",
|
14
|
+
"test:unit": "vitest run --config vitest.test-unit.config.ts",
|
15
|
+
"test:bench": "vitest bench",
|
16
|
+
"watch-test:e2e": "vitest --config=vitest.test-e2e.config.ts",
|
17
|
+
"watch-test:integration": "vitest --config vitest.test-integration.config.ts",
|
18
|
+
"watch-test:unit": "vitest --config vitest.test-unit.config.ts"
|
19
|
+
},
|
20
|
+
"repository": {
|
21
|
+
"type": "git",
|
22
|
+
"url": "git+https://github.com/jesusgraterol/aes256-async.git"
|
23
|
+
},
|
24
|
+
"keywords": [
|
25
|
+
"encryption",
|
26
|
+
"security",
|
27
|
+
"aes-256",
|
28
|
+
"sha-256",
|
29
|
+
"web",
|
30
|
+
"utilities",
|
31
|
+
"privacy"
|
32
|
+
],
|
33
|
+
"author": "Jesus Graterol",
|
34
|
+
"license": "MIT",
|
35
|
+
"bugs": {
|
36
|
+
"url": "https://github.com/jesusgraterol/aes256-async/issues"
|
37
|
+
},
|
38
|
+
"homepage": "https://github.com/jesusgraterol/aes256-async#readme",
|
39
|
+
"devDependencies": {
|
40
|
+
"@types/node": "^22.10.5",
|
41
|
+
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
42
|
+
"@typescript-eslint/parser": "^7.18.0",
|
43
|
+
"eslint-config-airbnb-typescript": "^18.0.0",
|
44
|
+
"ts-lib-builder": "^1.0.5",
|
45
|
+
"typescript": "^5.7.3",
|
46
|
+
"vitest": "^2.1.8"
|
47
|
+
},
|
48
|
+
"dependencies": {
|
49
|
+
"error-message-utils": "^1.1.2"
|
50
|
+
}
|
51
|
+
}
|