1

I'm trying to decrypt a string in PHP which was originally encrypted in NodeJS.

PHP:

openssl_decrypt($raw_id, "aes-128-cbc", "s7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m", 0, null)

This seems to always returnfalse.

Encryption in Nodejs:

function encrypt(text) {
    var cipher = crypto.createCipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
    var encrypted = cipher.update(text, 'utf8', 'hex')
    encrypted  += cipher.final('hex')

    return encrypted; 
}

function decrypt(text) {
    var cipher = crypto.createDecipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
    var decrypted = cipher.update(text, 'hex', 'utf8')
    decrypted += cipher.final('utf8');

    return decrypted;
}

I basically want to encrypt, for example, encrypt("Pizza") in Nodejs, send it to the PHP page (3879f91a59e9a458db62f905b0a488a1), and decrypt it from there (openssl_decrypt: return Pizza).

I know this code is not safe, since I'm not using an IV but I'm not sure how to add one.

1 Answer 1

1

Your method is not secure and can also be victim to man in the middle attacks, you should always use a IV and a HMAC
You can encrypt in php like this

$key = substr('encyptionsec123342',0,32)
function encrypt ($message, $method, $secret, &$hmac) {
    $iv = substr(bin2hex(openssl_random_pseudo_bytes(16)),0,16);
    $encrypted = base64_encode($iv) . openssl_encrypt($message, $method, $secret, 0, $iv);
    $hmac = hash_hmac('md5', $encrypted, $secret);
    return $encrypted;
}

function decrypt ($encrypted, $method, $secret, $hmac) {
    if (hash_hmac('md5', $encrypted, $secret) == $hmac) {
        $iv = base64_decode(substr($encrypted, 0, 24));
        return openssl_decrypt(substr($encrypted, 24), $method, $secret, 0, $iv);
    }
}

function encryptWithTSValidation ($message, $method, $secret, &$hmac) {
    date_default_timezone_set('UTC');
    $message = substr(date('c'),0,19) . "$message";
    return encrypt($message, $method, $secret, $hmac);
}

function decryptWithTSValidation ($encrypted, $method, $secret, $hmac, $intervalThreshold) {
    $decrypted = decrypt($encrypted, $method, $secret, $hmac);
    $now = new DateTime();
    $msgDate = new DateTime(str_replace("T"," ",substr($decrypted,0,19)));
    if (($now->getTimestamp() - $msgDate->getTimestamp()) <= $intervalThreshold) {
        return substr($decrypted,19);
    }
}

This is a secure AES-256-CBC method and with HMAC to stop man in the middle attacks.
Node.js

var secret = "encyptionsec123342";
secret = secret.substr(0, 32);
var method = 'AES-256-CBC';
var encrypt = function(message, method, secret, hmac) {
    var iv = crypto.randomBytes(16).toString('hex').substr(0, 16);
    var encryptor = crypto.createCipheriv(method, secret, iv);
    var encrypted = new Buffer.alloc(iv).toString('base64') + encryptor.update(message, 'utf8', 'base64') + encryptor.final('base64');
    hmac = crypto.createHmac('md5', secret).update(encrypted).digest('hex');
    return encrypted;
};
var decrypt = function(encrypted, method, secret, hmac) {
    if (crypto.createHmac('md5', secret).update(encrypted).digest('hex') == hmac) {
        var iv = new Buffer.from(encrypted.substr(0, 24), 'base64').toString();
        var decryptor = crypto.createDecipheriv(method, secret, iv);
        return decryptor.update(encrypted.substr(24), 'base64', 'utf8') + decryptor.final('utf8');
    }
};
var encryptWithTSValidation = function(message, method, secret, hmac) {
    var messageTS = new Date().toISOString().substr(0, 19) + message;
    return encrypt(messageTS, method, secret, hmac);
}
var decryptWithTSValidation = function(encrypted, method, secret, hmac, intervalThreshold) {
    var decrypted = decrypt(encrypted, method, secret, hmac);
    var now = new Date();
    var year = parseInt(decrypted.substr(0, 4)),
        month = parseInt(decrypted.substr(5, 2)) - 1,
        day = parseInt(decrypted.substr(8, 2)),
        hour = parseInt(decrypted.substr(11, 2)),
        minute = parseInt(decrypted.substr(14, 2)),
        second = parseInt(decrypted.substr(17, 2));
    var msgDate = new Date(Date.UTC(year, month, day, hour, minute, second))
    if (Math.round((now - msgDate) / 1000) <= intervalThreshold) {
        return decrypted.substr(19);
    }
}

To perform encryption and decryption in php,

$encrypted = encryptWithTSValidation($recipent, $method, $key, $hmac);
$decrypted = decryptWithTSValidation($encrypted,$method,$key, $hmac, 60*60*12)//this is 12 hours 

to generate a hmac, you can use simple md5 hashing

$hmac = hash_hmac('md5', $recipent, $key);

and in node.js

var decrypted = decryptWithTSValidation(encString, method, secret, hmac, 60 * 60);
var encrypted = decryptWithTSValidation(string, method, secret, hmac);

NOTE: Make sure to make a unique key that is of 32 bit and is same while encryption and decryption in nodejs and php. Also keep it safe and never store it in a database.
Code Reference : Encrypt string in PHP and decrypt in Node.js

Sign up to request clarification or add additional context in comments.

7 Comments

@AppelFlap Happy to help
What is the MitM attack here? If you want to suggest a better alternative suggest Authenticated Encryption as AES-GCM that is included in TLS 1.4
@kelalaka nodejs is used for “real-time” applications, it may be possible the user is using it in web sockets etc.
@kelalaka no i mean the op might be using it in direct communications like webscokets maybe that's why he's integrating node.js and php like i once did
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.