donderdag 25 april 2019

Node.js caching of required scripts

When I started exploring node.js I was wondering how the require() thing worked and how it would cache the scripts I required.

Would it return a new instance every time, basically functioning as a factory? Or would it return the same instance over and over?

So I did some reading up and found out that node.js caches it and returns the cached object/instance. Good, but then I read that it uses the filename for cache key, but it wasn't clear if the absolute file name is used as cache key or the relative file name.

So I did a test.

./index.js:

1
2
3
4
5
var test = require('./modules/test/test2.js');
console.log('expect world', test.hello);
test.hello = "dirt";
require('./modules/testbed.js');
console.log('expect universe', test.hello);

./modules/test/test2.js

1
2
3
module.exports = {
    hello: 'world'
}


./modules/testbed.js

1
2
3
var test2 = require('./test/test2.js');
console.log('expect dirt', test.hello);
test2.hello = "universe";

And then the output becomes

index.js:2   expect world world
testbed.js:2 expect dirt dirt
index.js:5   expect universe universe

Giving me confidence that it doesn't matter from which file or directory you require the module, as long as the filename is the same.

The only caveat is that if you use a case insensitive file system, things will break down if you're not consequent in your filename strings.

For example: if you change testbed.js to contain this:

1
2
3
var test2 = require('./test/Test2.js');// Note the uppercase T
console.log('expect dirt', test2.hello);
test2.hello = "universe";

The output will become:

index.js:2   expect world world
testbed.js:2 expect dirt world
index.js:5   expect universe dirt

because test.js and Test.js are different strings. So make sure to either always use consistent case for filenames.

dinsdag 26 februari 2019

How to recreate encryption by MCRYPT_RIJNDAEL_256 in PHP 7.2 and higher.

So with PHP7.2 around the edge and the deprecation of mcrypt, sometimes you still need to be able to encrypt with MCRYPT_RIJNDAEL_256

So I got around this question on stackoverflow: https://stackoverflow.com/questions/54887285/exact-alternate-to-mcrypt-encrypt-in-php-7-2

Researching this issue I found that openssl when it comes to MCRYPT_RIJNDAEL_256 says "Screw you, update your methods". So, the OP already had found a library which could do what he wanted it to do, but somehow the OP was using an outdated version.

This sent me on an experimenting spree which led to the code in the answer, a method to be able to encrypt and decrypt with the MCRYPT_RIJNDAEL_256  method as given in that answer.

To get this answer to work you'll need to incorporate the library phpseclib and install it in your code path.

Then you can use this code to translate the encrypted strings back and forth as you please.
Happy coding!

set_include_path(get_include_path() . PATH_SEPARATOR . 'phpseclib');
include('Crypt/Rijndael.php');
include('Crypt/Random.php');
use phpseclib\Crypt\Rijndael as Crypt_Rijndael;
function encryptRJ256($key,$iv,$text)
{
    $cipher = new Crypt_Rijndael('cbc'); 
    $cipher->setBlockLength(256);
    // keys are null-padded to the closest valid size
    // longer than the longest key and it's truncated
    $cipher->setKeyLength(256);
    $cipher->setKey($key);
    // the IV defaults to all-NULLs if not explicitly defined
    $cipher->setIV($iv);
    $cipher->disablePadding();
    $length = strlen($text);
    $pad = 32 - ($length % 32);
    $text = str_pad($text, $length + $pad, chr(0));
    return base64_encode($cipher->encrypt($text));
}
function decryptRJ256($key,$iv,$text)
{
    $cipher = new Crypt_Rijndael('cbc'); // could use CRYPT_RIJNDAEL_MODE_CBC
    $cipher->setBlockLength(256);
    // keys are null-padded to the closest valid size
    // longer than the longest key and it's truncated
    $cipher->setKeyLength(256);
    $cipher->setKey($key);
    // the IV defaults to all-NULLs if not explicitly defined
    $cipher->setIV($iv);
    $cipher->disablePadding();
    return $cipher->decrypt(base64_decode($text)); 
}