NodeJS version of Laravel's Encrypter Class, tested 5.4.30 to 6.X Illuminate/Encryption/Encrypter.php
With this module you can create the encrypted payload for a cookie from Node Js and be read by Laravel.
You can use it too as standalone module to encrypt and decrypt data with verified signature.
If you use this module as standalone, AKA without Laravel
backend involve in your scenarios you can use native node JSON lib
to serialize
the data before ciphering it.
options.key_length
now is 128|256
.
- NodeJs
>=v8.10.0 (npm v5.6.0)
- Laravel
>=5.4.30
$> npm i node-laravel-encryptor
const {Encryptor} = require('node-laravel-encryptor');
let encryptor = new Encryptor({
key: 'Laravel APP_KEY without base64:',
});
encryptor
.encrypt({foo: 'bar'})
.then(enc => console.log(encryptor.decrypt(enc)));
const enc = encryptor.encryptSync({foo: 'bar'});
console.log(encryptor.decrypt(enc));
Decrypt is always in sync mode.
Encryptor let you chose between php-serialize
npm package or JSON
node native implementation to serialize the data out of the box.
If you need to use other serialize library, like mspack
or any other custom lib, Encryptor let you inject, at the constructor or at runtime with
setSerializerDriver(your_lib)
, your custom Serializer Class.
If you use this module with the intend to be able to read and write ciphered data to/from Laravel you should instance Encryptor class without any
serialize_mode
option, just the defaults.
If you use this module without any Laravel Backend involve you should use json mode, instance Encryptor class with
serialize_mode:'json'
.
Encryptor will serialize only if data to cipher is an object.
You can force serialize if Encryptor class is using serialize_mode:'php'
to be able to serialize data to send back to Laravel if needed
const encryptor = new Encryptor({key});
const encryptor1 = new Encryptor({key, serialize_mode: 'php'});
encryptor and encryptor1 just do the same, initialize Encryptor class with serialize mode to 'php'
Encryptor defaults serialize data with
php-serialize
driver to be compliant with Laravel
If data needs to be serialized but it's not an object (because Laravel is serializing everything)
you can force Encryptor.encrypt()
to serialize data.
const encryptor = new Encryptor({key}); //serialize_mode = 'php'
encryptor.encrypt('foo', true) //foo now is encrypted and serialized
const encryptor = new Encryptor({key, serialize_mode: 'json'});
- adhere to Serializer Interface contract
Your custom Serializer must implement this two methods:
export interface Serialize_Interface {
serialize(data: any): string;
unSerialize(data: string): any;
}
- arguments:
- options:
<object>
{key, key_length}- key:
<string>
APP_KEY withoutbase64:
- key_length:
<number>
[optional] [default]<256>
values 128|256 for aes-[128]-cbc aes-[256]-cbc - serialize_mode:
<string>
[optional] [default]<php>
values<php>
|<json>
- key:
- serialize driver:
class to serialize
[optional]
- options:
- throw EncryptorError
If you use aes-128-cbc value should be 128 If you use aes-256-cbc value should be 256 or you can omit, it's a default value.
Will encrypt data with MAC signature, and return a Promise with encrypted base64 string.
With force_serialize
(only apply with serialize_mode:'php'
) you can force Encryptor to serialize data
before cipher even if data is not an object.
force_serialize
, will not take any effect if Encryptor is using other serializer driver than php-serialize
module.
- arguments:
- data:
<string>
|<object>
|<number>
- force_serialize:
<boolean>
[optional]
- data:
- return Promise
<string>
base64 json encoded object{iv, value, mac}
- throw EncryptorError
Will decrypt data with MAC signature verification, and return original data.
- arguments:
- data:
<string>
|<object>
|<number>
- data:
- return
<string>
|<object>
- throw EncryptorError
Will encrypt data with MAC signature, and return encrypted base64 string.
With force_serialize
(only apply with serialize_mode:'php'
) you can force Encryptor to serialize data
before cipher even if data is not an object.
force_serialize
, will not take any effect if Encryptor is using other serializer driver than php-serialize
module.
- arguments:
- data:
<string>
|<object>
|<number>
- force_serialize:
<boolean>
[optional]
- data:
- return
<string>
base64 json encoded object{iv, value, mac}
- throw EncryptorError
Encrypt and Decrypt methods will serialize or unserialize data if needed.
Will inject custom serializer driver to Encryptor Class
- arguments:
- custom_Serializer_lib:
object class serialize module
- custom_Serializer_lib:
- return
<void>
- throw EncryptorError
Will generate valid App_key a la Laravel
- arguments:
- length:
<number>
[optional], default 256, if you use aes-128-cbc use 128
- length:
- return
<string>
base64 - throw EncryptorError
will decipher data
- arguments:
- key:
<string>
base64 encoded key - data:
<string>
|<object>
|<number>
- key:
- return
<string>
base64 - throw EncryptorError
will cipher data
- arguments:
- key:
<string>
base64 encoded key - data:
<string>
|<object>
|<number>
- cb:
<function>
optional callback
- key:
- return
<string>
base64 - throw EncryptorError
➜ encryptor
Usage
encryptor --gen [128, 256]
encryptor --enc --key <key> --value <value> [--serialize_mode json|php]
encryptor --dec --key <key> --value <value> [--serialize_mode json|php]
➜ encryptor --gen 256
qS+rK37YXXCYHXUhYaQtFGE+RMRQHiolxTilCre4/xQ=
➜ encryptor --gen 128
qc5plfoS13rfJeQ9LcqNtg==
➜ encryptor --enc --key '5mimovgZ4oxbEoktPRKpVlu8LUL6JZRJb1+Y5JzJkIc=' \
--value '{"foo": 1}' --serialize_mode json
[OPTIONS]
[key] => 5mimovgZ4oxbEoktPRKpVlu8LUL6JZRJb1+Y5JzJkIc=
[value] => {"foo": 1}
[serialize_mode] => json
[OUTPUT]
[ciphered] => eyJpdiI6Ill6UTJOakV5WWpOa1lXUTNNRFkyTnc9PSIsInZhbHVlIjoiYjVtTE9GeDZ2QWhIRkRrUjIwWGhlQT09IiwibWFjIjoiNjUzNDQzNzRmYzUwZmY4NTdjNGY4MDdiZjcwZmFjMzU1YzlmYzU4MTQ1NmQ2MmYxY2I3ZDdiYWIwYTFmZWExMiJ9
➜ encryptor --enc --key '5mimovgZ4oxbEoktPRKpVlu8LUL6JZRJb1+Y5JzJkIc=' \
--value '{"foo": 1}'
[OPTIONS]
[key] => 5mimovgZ4oxbEoktPRKpVlu8LUL6JZRJb1+Y5JzJkIc=
[value] => {"foo": 1}
[serialize_mode] => php
[OUTPUT]
[ciphered] => eyJpdiI6Ik5EWmlaR0ZpTjJabFpEZGxOVFJrTmc9PSIsInZhbHVlIjoiYmo3RXJPMnNOamljamJITDMxZTVzcWxlUnpzN0RJdnZ4RUVpNTVvWlVKWT0iLCJtYWMiOiI2YjY4OGRiYjc0ZTg4NzlhMWYxMzI1MmZiOGY3Y2Q4YzM1MGEzMWUyZWE3ZWM3NjRmZTkyZTAwNGZkZGUyMmY0In0=
➜ encryptor --dec --key '5mimovgZ4oxbEoktPRKpVlu8LUL6JZRJb1+Y5JzJkIc=' \
--value 'eyJpdiI6Ik1HWTFZbVkwWmpneE1EZGlZVEkyT1E9PSIsInZhbHVlIjoiTXNvZWQ3WXE2SlVuVkpkNTM5SHdiQT09IiwibWFjIjoiMTA5OTllYTQ3YjcwYTIxYWU1MmVkZDAyNzIwODg1ZGE0YWJhZWIwOWMyNjVmYmY1ZDI0NTJjMDRhYjE0ODg3YiJ9' \
--serialize_mode json
[OPTIONS]
[key] => 5mimovgZ4oxbEoktPRKpVlu8LUL6JZRJb1+Y5JzJkIc=
[encrypted] => eyJpdiI6Ik1HWTFZbVkwWmpneE1EZGlZVEkyT1E9PSIsInZhbHVlIjoiTXNvZWQ3WXE2SlVuVkpkNTM5SHdiQT09IiwibWFjIjoiMTA5OTllYTQ3YjcwYTIxYWU1MmVkZDAyNzIwODg1ZGE0YWJhZWIwOWMyNjVmYmY1ZDI0NTJjMDRhYjE0ODg3YiJ9
[serialize_mode] => json
[OUTPUT]
[deciphered] => {"foo":1}
[RAW deciphered] => j:{"foo":1}
➜ encryptor --dec --key '5mimovgZ4oxbEoktPRKpVlu8LUL6JZRJb1+Y5JzJkIc=' \
--value 'eyJpdiI6Ik5EWmlaR0ZpTjJabFpEZGxOVFJrTmc9PSIsInZhbHVlIjoiYmo3RXJPMnNOamljamJITDMxZTVzcWxlUnpzN0RJdnZ4RUVpNTVvWlVKWT0iLCJtYWMiOiI2YjY4OGRiYjc0ZTg4NzlhMWYxMzI1MmZiOGY3Y2Q4YzM1MGEzMWUyZWE3ZWM3NjRmZTkyZTAwNGZkZGUyMmY0In0='
[OPTIONS]
[key] => 5mimovgZ4oxbEoktPRKpVlu8LUL6JZRJb1+Y5JzJkIc=
[encrypted] => eyJpdiI6Ik5EWmlaR0ZpTjJabFpEZGxOVFJrTmc9PSIsInZhbHVlIjoiYmo3RXJPMnNOamljamJITDMxZTVzcWxlUnpzN0RJdnZ4RUVpNTVvWlVKWT0iLCJtYWMiOiI2YjY4OGRiYjc0ZTg4NzlhMWYxMzI1MmZiOGY3Y2Q4YzM1MGEzMWUyZWE3ZWM3NjRmZTkyZTAwNGZkZGUyMmY0In0=
[serialize_mode] => php
[OUTPUT]
[deciphered] => {"foo":1}
[RAW deciphered] => a:1:{s:3:"foo";i:1;}
To be able to run PHP test
you should install:
- PHP
>= 7.1.3
- OpenSSL PHP Extension
- Mbstring PHP Extension
- Tokenizer PHP Extension
- Ctype PHP Extension
- JSON PHP Extension
- BCMath PHP Extension
$> npm run test
In order to run Artillery integration test and stress test with aSync|Sync mode we have
to install artillery and artillery expect plugin.
$> npm install -g artillery artillery-plugin-expect
$> npm run artillery_server_async
$> npm run artillery_expect
All virtual users finished
Summary report @ 11:28:45(+0200) 2019-09-21
Scenarios launched: 110
Scenarios completed: 110
Requests completed: 1100
RPS sent: 105.77
Request latency:
min: 0.8
max: 14.4
median: 1.2
p95: 2
p99: 3.5
Scenario counts:
Integration Test, parallel request: 110 (100%)
Codes:
200: 1100
$> npm run artillery_server_sync
$> npm run artillery_expect
All virtual users finished
Summary report @ 11:31:09(+0200) 2019-09-21
Scenarios launched: 110
Scenarios completed: 110
Requests completed: 1100
RPS sent: 105.87
Request latency:
min: 1
max: 27.3
median: 1.4
p95: 2.2
p99: 3.9
Scenario counts:
Integration Test, parallel request: 110 (100%)
Codes:
200: 1100
$> npm run artillery_server_async
$> npm run artillery_server_sync
$> npm run artillery
All virtual users finished
Summary report @ 11:20:34(+0200) 2019-09-21
Scenarios launched: 4220
Scenarios completed: 4220
Requests completed: 4220
RPS sent: 17.52
Request latency:
min: 1.1
max: 30.3
median: 1.9
p95: 3
p99: 4.8
Scenario counts:
stress test: 4220 (100%)
Codes:
200: 4220
All virtual users finished
Summary report @ 11:15:31(+0200) 2019-09-21
Scenarios launched: 4220
Scenarios completed: 4220
Requests completed: 4220
RPS sent: 17.52
Request latency:
min: 1.1
max: 30.6
median: 1.9
p95: 2.9
p99: 4.7
Scenario counts:
stress test: 4220 (100%)
Codes:
200: 4220
Laravel only allows AES-128-CBC
AES-256-CBC
.
If no algorithm is defined default is AES-256-CBC
{
"iv": "iv in base64",
"value": "encrypted data",
"mac": "Hash HMAC signature"
}
Pull requests are welcome.