@adonisjs/encryption
Advanced tools
Comparing version 1.0.4 to 2.0.0
/** | ||
* @module @adonisjs/encryption | ||
*/ | ||
/// <reference types="node" /> | ||
/** | ||
* The binding for the given module is defined inside `providers/AppProvider.ts` | ||
@@ -10,10 +6,19 @@ * file. | ||
declare module '@ioc:Adonis/Core/Encryption' { | ||
export type EncryptionConfigContract = { | ||
key: string; | ||
hmac: boolean; | ||
reviver: (key: string, value: string) => any; | ||
import { base64 } from '@poppinss/utils'; | ||
/** | ||
* Config accepted by the encryption | ||
*/ | ||
export type EncryptionOptions = { | ||
algorithm?: 'aes-256-cbc'; | ||
secret: string; | ||
}; | ||
export interface EncryptionContract { | ||
/** | ||
* Message verifier is similar to the encryption. However, the actual payload | ||
* is not encrypted and just base64 encoded. This is helpful when you are | ||
* not concerned about the confidentiality of the data, but just want to | ||
* make sure that is not tampered after encoding. | ||
*/ | ||
export interface MessageVerifierContract { | ||
/** | ||
* Encrypt a given piece of value using the app secret. A wide range of | ||
* Sign a given piece of value using the app secret. A wide range of | ||
* data types are supported. | ||
@@ -28,22 +33,52 @@ * | ||
* | ||
* Encrypt/decrypting a date object will result in returning a date string. | ||
* You can optionally define a purpose for which the value was signed and | ||
* mentioning a different purpose/no purpose during unsign will fail. | ||
*/ | ||
encrypt(payload: any): string; | ||
sign(payload: any, expiresIn?: string | number, purpose?: string): string; | ||
/** | ||
* Decrypt a previously encrypted value | ||
* Unsign, previously signed value | ||
*/ | ||
decrypt(payload: string): any; | ||
unsign<T extends any>(payload: string, purpose?: string): T | null; | ||
} | ||
/** | ||
* The encryption class allows encrypting and decrypting values using `aes-256-cbc` or `aes-128-cbc` | ||
* algorithms. The encrypted value uses a unique iv for every encryption and this ensures semantic | ||
* security (read more https://en.wikipedia.org/wiki/Semantic_security). | ||
*/ | ||
export interface EncryptionContract { | ||
/** | ||
* Create a new instance of encryption with custom runtime config | ||
* Reference to the message verifier | ||
*/ | ||
create(options?: Partial<EncryptionConfigContract>): EncryptionContract; | ||
verifier: MessageVerifierContract; | ||
/** | ||
* BASE64 Encode value | ||
* Reference to base64 object for base64 encoding/decoding values | ||
*/ | ||
base64Encode(arrayBuffer: ArrayBuffer | SharedArrayBuffer): string; | ||
base64Encode(data: string, encoding?: BufferEncoding): string; | ||
base64: typeof base64; | ||
/** | ||
* BASE64 decode the encoded value | ||
* Current algorithm in use | ||
*/ | ||
base64Decode(encoded: string | Buffer, encoding?: BufferEncoding): string; | ||
algorithm: EncryptionOptions['algorithm']; | ||
/** | ||
* Encrypt a given piece of value using the app secret. A wide range of | ||
* data types are supported. | ||
* | ||
* - String | ||
* - Arrays | ||
* - Objects | ||
* - Booleans | ||
* - Numbers | ||
* - Dates | ||
* | ||
* You can optionally define a purpose for which the value was encrypted and | ||
* mentioning a different purpose/no purpose during decrypt will fail. | ||
*/ | ||
encrypt(payload: any, expiresIn?: string | number, purpose?: string): string; | ||
/** | ||
* Decrypt a previously encrypted value | ||
*/ | ||
decrypt<T extends any>(payload: string, purpose?: string): T; | ||
/** | ||
* Create a children instance with different secret key | ||
*/ | ||
child(options?: EncryptionOptions): EncryptionContract; | ||
} | ||
@@ -50,0 +85,0 @@ const Encryption: EncryptionContract; |
@@ -1,3 +0,8 @@ | ||
/** | ||
* @module @adonisjs/encryption | ||
*/ | ||
/* | ||
* @adonisjs/encryption | ||
* | ||
* (c) Harminder Virk <virk@adonisjs.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ |
@@ -0,5 +1,5 @@ | ||
import { IocContract } from '@adonisjs/fold'; | ||
/** | ||
* @module @adonisjs/encryption | ||
* Encryption provider to binding encryption class to the container | ||
*/ | ||
import { IocContract } from '@adonisjs/fold'; | ||
export default class EncryptionProvider { | ||
@@ -6,0 +6,0 @@ protected $container: IocContract; |
"use strict"; | ||
/* | ||
* @adonisjs/encryption | ||
* | ||
* (c) Harminder Virk <virk@adonisjs.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Encryption_1 = require("../src/Encryption"); | ||
/** | ||
* @module @adonisjs/encryption | ||
* Encryption provider to binding encryption class to the container | ||
*/ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Encryption_1 = require("../src/Encryption"); | ||
class EncryptionProvider { | ||
@@ -14,3 +22,3 @@ constructor($container) { | ||
const Config = this.$container.use('Adonis/Core/Config'); | ||
return new Encryption_1.Encryption(Config.get('app.appKey')); | ||
return new Encryption_1.Encryption({ secret: Config.get('app.appKey') }); | ||
}); | ||
@@ -17,0 +25,0 @@ } |
@@ -0,45 +1,53 @@ | ||
/// <reference path="../../adonis-typings/encryption.d.ts" /> | ||
import { base64 as utilsBase64 } from '@poppinss/utils'; | ||
import { EncryptionContract, EncryptionOptions } from '@ioc:Adonis/Core/Encryption'; | ||
import { MessageVerifier } from '../MessageVerifier'; | ||
/** | ||
* @module @adonisjs/encryption | ||
* The encryption class allows encrypting and decrypting values using `aes-256-cbc` or `aes-128-cbc` | ||
* algorithms. The encrypted value uses a unique iv for every encryption and this ensures semantic | ||
* security (read more https://en.wikipedia.org/wiki/Semantic_security). | ||
*/ | ||
/// <reference types="node" /> | ||
import { EncryptionContract, EncryptionConfigContract } from '@ioc:Adonis/Core/Encryption'; | ||
/** | ||
* Encryption class uses `AES-256` to encrypt raw values using `Objects`, | ||
* `Arrays` and even `Date` objects. When `hmac=true`, an HMAC is | ||
* generated with `sha256` encryption. | ||
*/ | ||
export declare class Encryption implements EncryptionContract { | ||
private secret; | ||
private options?; | ||
private options; | ||
/** | ||
* Simple encryptor .d.ts files are broken and hence we need | ||
* to cast it to any at the time of usage | ||
* The key for signing and encrypting values. It is derived | ||
* from the user provided secret. | ||
*/ | ||
private encryptor; | ||
constructor(secret: string, options?: Partial<EncryptionConfigContract> | undefined); | ||
private cryptoKey; | ||
/** | ||
* Encrypts value with `AES-256` encryption. HMAC is disabled by default for | ||
* returning shorter output. Feel free to grab a [[newInstance]] of the | ||
* encryption class with `hmac=true`. | ||
* Use `dot` as a separator for joining encrypted value, iv and the | ||
* hmac hash. The idea is borrowed from JWT's in which each part | ||
* of the payload is concatenated with a dot. | ||
*/ | ||
encrypt(payload: any): string; | ||
private separator; | ||
/** | ||
* Decrypt existing encrypted value. Returns `null`, when unable to | ||
* decrypt. | ||
* Reference to the instance of message verifier for signing | ||
* and verifying values. | ||
*/ | ||
decrypt(payload: string): any; | ||
verifier: MessageVerifier; | ||
/** | ||
* Returns a custom instance of [[Encryption]] class with custom | ||
* configuration | ||
* Reference to base64 object for base64 encoding/decoding values | ||
*/ | ||
create(options?: Partial<EncryptionConfigContract>): Encryption; | ||
base64: typeof utilsBase64; | ||
/** | ||
* Base64 encode Buffer or string | ||
* The algorithm in use | ||
*/ | ||
base64Encode(arrayBuffer: ArrayBuffer | SharedArrayBuffer): string; | ||
base64Encode(data: string, encoding?: BufferEncoding): string; | ||
algorithm: "aes-256-cbc"; | ||
constructor(options: EncryptionOptions); | ||
/** | ||
* Base64 decode a previously encoded string or Buffer. | ||
* Validates the app secret | ||
*/ | ||
base64Decode(encoded: string | Buffer, encoding?: BufferEncoding): string; | ||
private validateSecret; | ||
/** | ||
* Encrypt value with optional expiration and purpose | ||
*/ | ||
encrypt(value: any, expiresAt?: string | number, purpose?: string): string; | ||
/** | ||
* Decrypt value and verify it against a purpose | ||
*/ | ||
decrypt(value: string, purpose?: string): any; | ||
/** | ||
* Returns a new instance of encryption with custom secret key | ||
*/ | ||
child(options: EncryptionOptions): Encryption; | ||
} |
"use strict"; | ||
/** | ||
* @module @adonisjs/encryption | ||
*/ | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/* | ||
* @adonisjs/encryption | ||
* | ||
* (c) Harminder Virk <virk@adonisjs.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
* @adonisjs/encryption | ||
* | ||
* (c) Harminder Virk <virk@adonisjs.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
const simple_encryptor_1 = __importDefault(require("simple-encryptor")); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/// <reference path="../../adonis-typings/encryption.ts" /> | ||
const crypto_1 = require("crypto"); | ||
const utils_1 = require("@poppinss/utils"); | ||
const Hmac_1 = require("../Hmac"); | ||
const MessageBuilder_1 = require("../MessageBuilder"); | ||
const MessageVerifier_1 = require("../MessageVerifier"); | ||
/** | ||
* Encryption class uses `AES-256` to encrypt raw values using `Objects`, | ||
* `Arrays` and even `Date` objects. When `hmac=true`, an HMAC is | ||
* generated with `sha256` encryption. | ||
* The encryption class allows encrypting and decrypting values using `aes-256-cbc` or `aes-128-cbc` | ||
* algorithms. The encrypted value uses a unique iv for every encryption and this ensures semantic | ||
* security (read more https://en.wikipedia.org/wiki/Semantic_security). | ||
*/ | ||
class Encryption { | ||
constructor(secret, options) { | ||
this.secret = secret; | ||
constructor(options) { | ||
this.options = options; | ||
this.encryptor = simple_encryptor_1.default(Object.assign({ | ||
key: this.secret, | ||
debug: false, | ||
hmac: false, | ||
}, this.options)); | ||
/** | ||
* The key for signing and encrypting values. It is derived | ||
* from the user provided secret. | ||
*/ | ||
this.cryptoKey = crypto_1.createHash('sha256').update(this.options.secret).digest(); | ||
/** | ||
* Use `dot` as a separator for joining encrypted value, iv and the | ||
* hmac hash. The idea is borrowed from JWT's in which each part | ||
* of the payload is concatenated with a dot. | ||
*/ | ||
this.separator = '.'; | ||
/** | ||
* Reference to the instance of message verifier for signing | ||
* and verifying values. | ||
*/ | ||
this.verifier = new MessageVerifier_1.MessageVerifier(this.options.secret); | ||
/** | ||
* Reference to base64 object for base64 encoding/decoding values | ||
*/ | ||
this.base64 = utils_1.base64; | ||
/** | ||
* The algorithm in use | ||
*/ | ||
this.algorithm = this.options.algorithm || 'aes-256-cbc'; | ||
this.validateSecret(); | ||
} | ||
/** | ||
* Encrypts value with `AES-256` encryption. HMAC is disabled by default for | ||
* returning shorter output. Feel free to grab a [[newInstance]] of the | ||
* encryption class with `hmac=true`. | ||
* Validates the app secret | ||
*/ | ||
encrypt(payload) { | ||
return this.encryptor.encrypt(payload); | ||
validateSecret() { | ||
if (typeof (this.options.secret) !== 'string') { | ||
throw new utils_1.Exception('Missing "app.appKey". Makes sure to define it inside the config file', 500, 'E_MISSING_APP_KEY'); | ||
} | ||
if (this.options.secret.length < 16) { | ||
throw new utils_1.Exception('"app.appKey" must have minimum length of 16 characters', 500, 'E_INVALID_APP_KEY'); | ||
} | ||
} | ||
/** | ||
* Decrypt existing encrypted value. Returns `null`, when unable to | ||
* decrypt. | ||
* Encrypt value with optional expiration and purpose | ||
*/ | ||
decrypt(payload) { | ||
return this.encryptor.decrypt(payload); | ||
encrypt(value, expiresAt, purpose) { | ||
/** | ||
* Using a random string as the iv for generating unpredictable values | ||
*/ | ||
const iv = utils_1.randomString(16); | ||
/** | ||
* Creating chiper | ||
*/ | ||
const cipher = crypto_1.createCipheriv(this.algorithm, this.cryptoKey, iv); | ||
/** | ||
* Encoding value to a string so that we can set it on the cipher | ||
*/ | ||
const encodedValue = new MessageBuilder_1.MessageBuilder().build(value, expiresAt, purpose); | ||
/** | ||
* Set final to the cipher instance and encrypt it | ||
*/ | ||
const encrypted = Buffer.concat([cipher.update(encodedValue, 'utf8'), cipher.final()]); | ||
/** | ||
* Concatenate `encrypted value` and `iv` by urlEncoding them. The concatenation is required | ||
* to generate the HMAC, so that HMAC checks for integrity of both the `encrypted value` | ||
* and the `iv`. | ||
*/ | ||
const result = `${this.base64.urlEncode(encrypted)}${this.separator}${this.base64.urlEncode(iv)}`; | ||
/** | ||
* Returns the result + hmac | ||
*/ | ||
return `${result}${this.separator}${new Hmac_1.Hmac(this.cryptoKey).generate(result)}`; | ||
} | ||
/** | ||
* Returns a custom instance of [[Encryption]] class with custom | ||
* configuration | ||
* Decrypt value and verify it against a purpose | ||
*/ | ||
create(options) { | ||
return new Encryption(this.secret, options); | ||
} | ||
base64Encode(data, encoding) { | ||
if (typeof (data) === 'string') { | ||
return Buffer.from(data, encoding).toString('base64'); | ||
decrypt(value, purpose) { | ||
if (typeof (value) !== 'string') { | ||
throw new utils_1.Exception('"Encryption.decrypt" expects a string value', 500, 'E_RUNTIME_EXCEPTION'); | ||
} | ||
return Buffer.from(data).toString('base64'); | ||
/** | ||
* Make sure the encrypted value is in correct format. ie | ||
* [encrypted value]--[iv]--[hash] | ||
*/ | ||
const [encryptedEncoded, ivEncoded, hash] = value.split(this.separator); | ||
if (!encryptedEncoded || !ivEncoded || !hash) { | ||
return null; | ||
} | ||
/** | ||
* Make sure we are able to urlDecode the encrypted value | ||
*/ | ||
const encrypted = this.base64.urlDecode(encryptedEncoded, 'binary'); | ||
if (!encrypted) { | ||
return null; | ||
} | ||
/** | ||
* Make sure we are able to urlDecode the iv | ||
*/ | ||
const iv = this.base64.urlDecode(ivEncoded); | ||
if (!iv) { | ||
return null; | ||
} | ||
/** | ||
* Make sure the hash is correct, it means the first 2 parts of the | ||
* string are not tampered. | ||
*/ | ||
const isValidHmac = new Hmac_1.Hmac(this.cryptoKey).compare(`${encryptedEncoded}${this.separator}${ivEncoded}`, hash); | ||
if (!isValidHmac) { | ||
return null; | ||
} | ||
/** | ||
* The Decipher can raise exceptions with malformed input, so we wrap it | ||
* to avoid leaking sensitive information | ||
*/ | ||
try { | ||
const decipher = crypto_1.createDecipheriv(this.algorithm, this.cryptoKey, iv); | ||
const decrypted = decipher.update(encrypted, 'binary', 'utf8') + decipher.final('utf8'); | ||
return new MessageBuilder_1.MessageBuilder().verify(decrypted, purpose); | ||
} | ||
catch (error) { | ||
return null; | ||
} | ||
} | ||
/** | ||
* Base64 decode a previously encoded string or Buffer. | ||
* Returns a new instance of encryption with custom secret key | ||
*/ | ||
base64Decode(encoded, encoding = 'utf-8') { | ||
return Buffer.isBuffer(encoded) | ||
? encoded.toString(encoding) | ||
: Buffer.from(encoded, 'base64').toString(encoding); | ||
child(options) { | ||
return new Encryption(options); | ||
} | ||
} | ||
exports.Encryption = Encryption; |
@@ -1,4 +0,1 @@ | ||
/** | ||
* @module @adonisjs/encryption | ||
*/ | ||
export { Encryption } from './src/Encryption'; |
"use strict"; | ||
/** | ||
* @module @adonisjs/encryption | ||
*/ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/* | ||
@@ -14,3 +10,4 @@ * @adonisjs/encryption | ||
*/ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var Encryption_1 = require("./src/Encryption"); | ||
exports.Encryption = Encryption_1.Encryption; |
{ | ||
"name": "@adonisjs/encryption", | ||
"version": "1.0.4", | ||
"version": "2.0.0", | ||
"description": "Encryption provider for AdonisJs", | ||
@@ -40,5 +40,5 @@ "main": "build/providers/EncryptionProvider.js", | ||
"@adonisjs/fold": "^6.3.2", | ||
"@adonisjs/mrm-preset": "^2.2.4", | ||
"@types/node": "^13.7.0", | ||
"commitizen": "^4.0.3", | ||
"@adonisjs/mrm-preset": "^2.3.0", | ||
"@types/node": "^13.11.1", | ||
"commitizen": "^4.0.4", | ||
"cz-conventional-changelog": "^3.1.0", | ||
@@ -48,9 +48,9 @@ "del-cli": "^3.0.0", | ||
"eslint": "^6.8.0", | ||
"eslint-plugin-adonis": "^1.0.6", | ||
"husky": "^4.2.1", | ||
"eslint-plugin-adonis": "^1.0.9", | ||
"husky": "^4.2.5", | ||
"japa": "^3.0.1", | ||
"mrm": "^2.0.4", | ||
"mrm": "^2.2.1", | ||
"np": "^5.2.1", | ||
"ts-node": "^8.6.2", | ||
"typescript": "^3.7.5" | ||
"ts-node": "^8.8.2", | ||
"typescript": "^3.8.3" | ||
}, | ||
@@ -77,3 +77,5 @@ "nyc": { | ||
"dependencies": { | ||
"simple-encryptor": "^3.0.0" | ||
"@hapi/bourne": "^2.0.0", | ||
"@poppinss/utils": "^2.2.0", | ||
"ms": "^2.1.2" | ||
}, | ||
@@ -80,0 +82,0 @@ "np": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27802
17
640
3
1
+ Added@hapi/bourne@^2.0.0
+ Added@poppinss/utils@^2.2.0
+ Addedms@^2.1.2
+ Added@hapi/bourne@2.1.0(transitive)
+ Added@poppinss/utils@2.5.10(transitive)
+ Addedbuffer-alloc@1.2.0(transitive)
+ Addedbuffer-alloc-unsafe@1.1.0(transitive)
+ Addedbuffer-fill@1.0.0(transitive)
+ Addedfast-safe-stringify@2.1.1(transitive)
+ Addedfs-readdir-recursive@1.1.0(transitive)
+ Addedklona@2.0.6(transitive)
+ Addedms@2.1.3(transitive)
+ Addedrequire-all@3.0.0(transitive)
+ Addedresolve-from@5.0.0(transitive)
- Removedsimple-encryptor@^3.0.0
- Removedscmp@2.0.0(transitive)
- Removedsimple-encryptor@3.0.0(transitive)