久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

在 PHP 中加密字符串并在 Node.js 中解密

Encrypt string in PHP and decrypt in Node.js(在 PHP 中加密字符串并在 Node.js 中解密)
本文介紹了在 PHP 中加密字符串并在 Node.js 中解密的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我通過 Apache 和 Node.js 服務器之間的不安全連接發送數據.我需要在 PHP 中加密數據并在 Node.js 中解密.我花了 2 天的時間試圖讓它工作,但是我只設法讓消息簽名工作,沒有加密.我嘗試通過 AES128-CBC、AES256-CBC、DES、AES128、AES256 作為算法,但是沒有任何效果..

我在 PHP 中嘗試過:

$data = json_encode(Array('mk' => $_SESSION['key'], 'algorithm' => 'SHA1', 'username' => $_SESSION['userid'], 'expires' => $expires));$payload = openssl_encrypt($data, 'des', '716c26ef');返回 base64_encode($payload);

在 Node.js 中:

var enc_json = new Buffer(response[1], 'base64');var decipher = crypto.createDecipher('des', '716c26ef');var json = decipher.update(enc_json).toString('ascii');json += decipher.final('ascii');

除了錯誤的解密數據外,我還收到如下錯誤:

TypeError:錯誤:0606508A:數字信封例程:EVP_DecryptFinal_ex:數據不是塊長度的倍數類型錯誤:錯誤:0606506D:數字信封例程:EVP_DecryptFinal_ex:錯誤的最終塊長度

我需要一個簡單的加密,因為數據不太敏感(沒有密碼或用戶數據),但是數據只能由接收者讀取.密鑰長度可以任意,但加密/解密的過程必須盡可能簡單,請不要使用IV.

解決方案

我這周遇到了同樣的問題,但以相反的方式(PHP 加密 -> NodeJS 解密)并設法使此代碼段正常工作:

aes256cbc.js

var crypto = require('crypto');var encrypt = 函數(純文本、加密方法、秘密、iv){var encryptor = crypto.createCipheriv(encryptionMethod, secret, iv);返回 encryptor.update(plain_text, 'utf8', 'base64') + encryptor.final('base64');};var 解密 = 函數(encryptedMessage、encryptionMethod、secret、iv){var 解密器 = crypto.createDecipheriv(encryptionMethod, secret, iv);返回解密器.更新(加密消息,'base64','utf8')+decryptor.final('utf8');};var textToEncrypt = new Date().toISOString().substr(0,19) + '|我的超級機密信息.';var encryptionMethod = 'AES-256-CBC';var secret = "My32charPasswordAndInitVectorStr";//必須是32個字符長度var iv = secret.substr(0,16);var encryptedMessage = encrypt(textToEncrypt, encryptionMethod, secret, iv);變量解密消息 = 解密(加密消息,加密方法,秘密,iv);控制臺日志(加密消息);控制臺日志(解密消息);

aes256cbc.php

這里避免陷入密鑰/iv 大小/解密問題的秘訣是擁有恰好 32 個字符長度和 16 個字符長度的秘訣用于 IV.此外,在 NodeJS 中使用base64"和utf8"非常很重要,因為這些是 PHP 中的默認值.

以下是一些示例運行:

$ node aes256cbc.js &&php aes256cbc.phpzra3FX4iyCc7qPc1dZs+G3ZQ40f5bSw8P9n5OtWl1t86nV5Qfh4zNRPFbsciyyHyU3Qi4Ga1oTiTwzrPIZQXLw==2015-01-27T18:29:12|我的超級機密信息.zra3FX4iyCc7qPc1dZs+G3ZQ40f5bSw8P9n5OtWl1t86nV5Qfh4zNRPFbsciyyHyU3Qi4Ga1oTiTwzrPIZQXLw==2015-01-27T18:29:12|我的超級機密信息.$ 節點 aes256cbc.js &&php aes256cbc.phpzra3FX4iyCc7qPc1dZs+G6B6+8aavHNc/Ymv9L6Omod8Di3tMbvOa2B7O2Yiyoutm9fy9l0G+P5VJT9z2qNESA==2015-01-27T18:29:15|我的超級機密信息.zra3FX4iyCc7qPc1dZs+G6B6+8aavHNc/Ymv9L6Omod8Di3tMbvOa2B7O2Yiyoutm9fy9l0G+P5VJT9z2qNESA==2015-01-27T18:29:15|我的超級機密信息.$ 節點 aes256cbc.js &&php aes256cbc.phpzra3FX4iyCc7qPc1dZs+G4oD1Fr5yLByON6QDE56UOqP6kkfGJzpyH6TbwZYX2oGlh2JGv+aHYUMh0qQnAj/uw==2015-01-27T18:29:29|我的超級機密信息.zra3FX4iyCc7qPc1dZs+G4oD1Fr5yLByON6QDE56UOqP6kkfGJzpyH6TbwZYX2oGlh2JGv+aHYUMh0qQnAj/uw==2015-01-27T18:29:29|我的超級機密信息.$ 節點 aes256cbc.js &&php aes256cbc.phpzra3FX4iyCc7qPc1dZs+G5OVCbCaUy8a0LLF+Bn8UT4X3nYbtynO0Zt2mvXnnli9dRxrxMw43uWnkh8MIwVHXA==2015-01-27T18:29:31|我的超級機密信息.zra3FX4iyCc7qPc1dZs+G5OVCbCaUy8a0LLF+Bn8UT4X3nYbtynO0Zt2mvXnnli9dRxrxMw43uWnkh8MIwVHXA==2015-01-27T18:29:31|我的超級機密信息.$ 節點 aes256cbc.js &&php aes256cbc.phpfdsqSyHBJjlwD0jYfOUZM2FrONG6Fk5d7FOItYEdbnaZIhhmg/apa8/jPwKFkDXD9eNqWC3w0JzY5wjtZADiBA==2015-01-27T18:30:08|我的超級機密信息.fdsqSyHBJjlwD0jYfOUZM2FrONG6Fk5d7FOItYEdbnaZIhhmg/apa8/jPwKFkDXD9eNqWC3w0JzY5wjtZADiBA==2015-01-27T18:30:08|我的超級機密信息.$ 節點 aes256cbc.js &&php aes256cbc.phpfdsqSyHBJjlwD0jYfOUZM4SRfi6jG5EoDFEF6d9xCIyluXSiMaKlhd89ovpeOz/YyEIlPbYR4ly00gf6hWfKHw==2015-01-27T18:30:45|我的超級機密信息.fdsqSyHBJjlwD0jYfOUZM4SRfi6jG5EoDFEF6d9xCIyluXSiMaKlhd89ovpeOz/YyEIlPbYR4ly00gf6hWfKHw==2015-01-27T18:30:45|我的超級機密信息.

注意:

我使用時間戳|消息"格式來避免中間人攻擊.例如,如果加密的消息包含要驗證的 ID,則 MitM 可以捕獲該消息并在他每次想要重新驗證時重新發送.

因此,我可以檢查加密消息上的時間戳是否在一個很小的時間間隔內.這樣一來,由于時間戳的原因,同一條消息每秒都會以不同的方式加密,并且無法在此固定時間間隔之外使用.

這里我濫用了初始化向量 (IV).正如@ArtjomB. 所解釋的,IV 應該是加密消息的第一部分,并且它應該是一個隨機值.還建議在 HTTP 標頭 (x-hmac: *value*) 中使用 hmac 值以驗證消息是否來自有效來源(但這并沒有解決之前描述的重新發送"消息問題).

這是改進的版本,包括用于 php 和 node 的 hmac 以及作為加密消息一部分的 IV:

aes256cbc.js (v2)

var crypto = require('crypto');var encrypt = 函數(消息、方法、秘密、hmac){//var iv = crypto.randomBytes(16).toString('hex').substr(0,16);//在生產中使用它var iv = secret.substr(0,16);//將此用于測試目的(在 PHP 和 Node 加密器中具有相同的加密 IV)var encryptor = crypto.createCipheriv(method, secret, iv);var encrypted = new Buffer(iv).toString('base64') + encryptor.update(message, 'utf8', 'base64') + encryptor.final('base64');hmac.value = crypto.createHmac('md5', secret).update(encrypted).digest('hex');返回加密;};var 解密 = 函數(加密、方法、秘密、hmac){if (crypto.createHmac('md5', secret).update(encrypted).digest('hex') == hmac.value) {var iv = new Buffer(encrypted.substr(0, 24), 'base64').toString();var 解密器 = crypto.createDecipheriv(method, secret, iv);返回decryptor.update(encrypted.substr(24), 'base64', 'utf8') +decryptor.final('utf8');}};var encryptWithTSValidation = 函數(消息、方法、秘密、hmac){var messageTS = new Date().toISOString().substr(0,19) + message;返回加密(messageTS,方法,秘密,hmac);}vardecryptWithTSValidation = 函數(加密,方法,秘密,hmac,intervalThreshold){var 解密 = 解密(加密,方法,秘密,hmac);var now = new Date();var year = parseInt(decrypted.substr(0,4)), month = parseInt(decrypted.substr(5,2)) - 1,天 = parseInt(decrypted.substr(8,2)), 小時 = parseInt(decrypted.substr(11,2)),分鐘 = parseInt(decrypted.substr(14,2)), second = parseInt(decrypted.substr(17,2));var msgDate = new Date(Date.UTC(年、月、日、時、分、秒))if (Math.round((now - msgDate)/1000) <= intervalThreshold) {返回解密.substr(19);}}var message = '我的超級機密信息.';var 方法 = 'AES-256-CBC';var secret = "My32charPasswordAndInitVectorStr";//必須是32個字符長度var hmac = {};//var encrypted = encrypt(message, method, secret, hmac);//var 解密 = 解密(加密,方法,秘密,hmac);var encrypted = encryptWithTSValidation(message, method, secret, hmac);var解密=decryptWithTSValidation(加密,方法,秘密,hmac,60*60*12);//60*60m*12=12hconsole.log("使用 HTTP 標頭 'x-hmac:" + hmac.value + "' 來驗證中間人攻擊.");console.log("加密:" + 加密);console.log("解密:" + 解密);

請注意,crypto.createHmac(...).digest('hex') 是用 hex 消化的.這是 hmac 在 PHP 中的默認設置.

aes256cbc.php (v2)

getTimestamp() - $msgDate->getTimestamp()) <= $intervalThreshold) {返回 substr($decrypted,19);}}$message = "我的超級機密信息.";$method = "AES-256-CBC";$secret = "My32charPasswordAndInitVectorStr";//必須是32個字符長度//$encrypted = encrypt($message, $method, $secret, $hmac);//$decrypted =decrypt($encrypted, $method, $secret, $hmac);$encrypted = encryptWithTSValidation($message, $method, $secret, $hmac);$decrypted =decryptWithTSValidation($encrypted, $method, $secret, $hmac, 60*60*12);//60*60m*12=12hecho "使用 HTTP 標頭 'x-hmac: $hmac' 來驗證對抗中間人攻擊.
";echo "加密: $encrypted
";echo "解密: $decrypted
";?>

以下是一些示例運行:

$ node aes256cbc.js &&php aes256cbc.php使用 HTTP 標頭 'x-hmac: 6862972ef0f463bf48523fc9e334bb42' 來驗證對抗中間件攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==I6cAKeoxeSP5TGgtK59PotB/iG2BUSU8Y6NhAhVabN9UB+ZCTn7q2in4JyLwQiGN解密:我的超級秘密信息.使用 HTTP 標頭 'x-hmac: 6862972ef0f463bf48523fc9e334bb42' 來驗證對抗中間件攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==I6cAKeoxeSP5TGgtK59PotB/iG2BUSU8Y6NhAhVabN9UB+ZCTn7q2in4JyLwQiGN解密:我的超級秘密信息.$ 節點 aes256cbc.js &&php aes256cbc.php使用 HTTP 標頭 'x-hmac: b2e63f216acde938a82142220652cf59' 來驗證中間人攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCluCk7Yg+U+S1CSgYBBR8dkZytORm8xwEDmD9WB1mpqC3XnSrB+wR3/KW解密:我的超級秘密信息.使用 HTTP 標頭 'x-hmac: b2e63f216acde938a82142220652cf59' 來驗證中間人攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCluCk7Yg+U+S1CSgYBBR8dkZytORm8xwEDmD9WB1mpqC3XnSrB+wR3/KW解密:我的超級秘密信息.$ 節點 aes256cbc.js &&php aes256cbc.php使用 HTTP 標頭 'x-hmac: 73181744453d55eb6f81896ffd284cd8' 來驗證對抗中間件攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CTGik4Lv9PnWuEg5SiADJcdKX1to0LrNKmuCiYIweBAZ解密:我的超級秘密信息.使用 HTTP 標頭 'x-hmac: 73181744453d55eb6f81896ffd284cd8' 來驗證對抗中間件攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CTGik4Lv9PnWuEg5SiADJcdKX1to0LrNKmuCiYIweBAZ解密:我的超級秘密信息.$ 節點 aes256cbc.js &&php aes256cbc.php使用 HTTP 標頭 'x-hmac: 5372ecca442d65f582866cf3b24cb2b6' 來驗證對抗中間件攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CYEITF6aozBNp7bA54qY0Ugg9v6ktwoH6nqRyatkFqy8解密:我的超級秘密信息.使用 HTTP 標頭 'x-hmac: 5372ecca442d65f582866cf3b24cb2b6' 來驗證對抗中間件攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CYEITF6aozBNp7bA54qY0Ugg9v6ktwoH6nqRyatkFqy8解密:我的超級秘密信息.

最后但并非最不重要的是,如果您沒有在 php 中安裝 openssl mod,您可以使用 mcrypt 代替 rijndael128pkcs7像這樣填充(source):

aes256cbc-mcrypt.php (v2)

getTimestamp() - $msgDate->getTimestamp()) <= $intervalThreshold) {返回 substr($decrypted,19);}}$message = "我的超級機密信息.";$method = MCRYPT_RIJNDAEL_128;$secret = "My32charPasswordAndInitVectorStr";//必須是32個字符長度//$encrypted = encrypt($message, $method, $secret, $hmac);//$decrypted =decrypt($encrypted, $method, $secret, $hmac);$encrypted = encryptWithTSValidation($message, $method, $secret, $hmac);$decrypted =decryptWithTSValidation($encrypted, $method, $secret, $hmac, 60*60*12);//60*60m*12=12hecho "使用 HTTP 標頭 'x-hmac: $hmac' 來驗證對抗中間人攻擊.
";echo "加密: $encrypted
";echo "解密: $decrypted
";?>

當然,接下來進行一些測試:

$ php aes256cbc-mcrypt.php &&節點 aes256cbc.js使用 HTTP 標頭 'x-hmac: 801282a9ed6b2d5bd2254140d7a17582' 來驗證中間人攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v9IyatyGeNT2yebrpJZ5xH73H5fFcV1zhqhRGwM0ToGU解密:我的超級秘密信息.使用 HTTP 標頭 'x-hmac: 801282a9ed6b2d5bd2254140d7a17582' 來驗證中間人攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v9IyatyGeNT2yebrpJZ5xH73H5fFcV1zhqhRGwM0ToGU解密:我的超級秘密信息.$ php aes256cbc-mcrypt.php &&節點 aes256cbc.js使用 HTTP 標頭 'x-hmac: 0ab2bc83108e1e250f6ecd483cd65329' 來驗證中間人攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v79P+j4YUl8ln8eu??7FDqEdbxMe1Z7BvW8iVUN1qFCiHM解密:我的超級秘密信息.使用 HTTP 標頭 'x-hmac: 0ab2bc83108e1e250f6ecd483cd65329' 來驗證中間人攻擊.加密:YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v79P+j4YUl8ln8eu??7FDqEdbxMe1Z7BvW8iVUN1qFCiHM解密:我的超級秘密信息.

I am sending data through insecure connection between Apache and Node.js servers. I need to encrypt data in PHP and decrypt in Node.js. I've spent 2 days trying to get it to work, however I only managed to get message signing to work, no encryption. I tried passing AES128-CBC, AES256-CBC, DES, AES128, AES256 as algorithms, however nothing worked well..

I tried this in PHP:

$data = json_encode(Array('mk' => $_SESSION['key'], 'algorithm' => 'SHA1', 'username' => $_SESSION['userid'], 'expires' => $expires));
$payload = openssl_encrypt($data, 'des', '716c26ef');
return base64_encode($payload);

And in Node.js:

var enc_json = new Buffer(response[1], 'base64');
var decipher = crypto.createDecipher('des', '716c26ef');
var json = decipher.update(enc_json).toString('ascii');
json += decipher.final('ascii');

And besides wrong decrypted data I get error such as these:

TypeError: error:0606508A:digital envelope routines:EVP_DecryptFinal_ex:data not multiple of block length

TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length

I need a simple encryption as data is not too sensitive (no password or user data), however data should only be read by the recipient. Key length can be anything, but procedure to encrypt/decrypt has to be as simple as possible, please no IVs.

解決方案

I was struggling with the same problem this week but in the opposite way (PHP encrypts -> NodeJS decrypts) and had managed to get this snippet working:

aes256cbc.js

var crypto = require('crypto');

var encrypt = function (plain_text, encryptionMethod, secret, iv) {
    var encryptor = crypto.createCipheriv(encryptionMethod, secret, iv);
    return encryptor.update(plain_text, 'utf8', 'base64') + encryptor.final('base64');
};

var decrypt = function (encryptedMessage, encryptionMethod, secret, iv) {
    var decryptor = crypto.createDecipheriv(encryptionMethod, secret, iv);
    return decryptor.update(encryptedMessage, 'base64', 'utf8') + decryptor.final('utf8');
};

var textToEncrypt = new Date().toISOString().substr(0,19) + '|My super secret information.';
var encryptionMethod = 'AES-256-CBC';
var secret = "My32charPasswordAndInitVectorStr"; //must be 32 char length
var iv = secret.substr(0,16);

var encryptedMessage = encrypt(textToEncrypt, encryptionMethod, secret, iv);
var decryptedMessage = decrypt(encryptedMessage, encryptionMethod, secret, iv);

console.log(encryptedMessage);
console.log(decryptedMessage);

aes256cbc.php

<?php
date_default_timezone_set('UTC');
$textToEncrypt = substr(date('c'),0,19) . "|My super secret information.";
$encryptionMethod = "AES-256-CBC";
$secret = "My32charPasswordAndInitVectorStr";  //must be 32 char length
$iv = substr($secret, 0, 16);

$encryptedMessage = openssl_encrypt($textToEncrypt, $encryptionMethod, $secret,0,$iv);
$decryptedMessage = openssl_decrypt($encryptedMessage, $encryptionMethod, $secret,0,$iv);

echo "$encryptedMessage
";
echo "$decryptedMessage
";
?>

The secret here to avoid falling in key/iv size/decryption problems is to have the secret of exactly 32 characters length and 16 for the IV. Also, it is VERY important to use 'base64' and 'utf8' in NodeJS since these are the defaults in PHP.

Here are some sample runs:

$ node aes256cbc.js && php aes256cbc.php
zra3FX4iyCc7qPc1dZs+G3ZQ40f5bSw8P9n5OtWl1t86nV5Qfh4zNRPFbsciyyHyU3Qi4Ga1oTiTwzrPIZQXLw==
2015-01-27T18:29:12|My super secret information.
zra3FX4iyCc7qPc1dZs+G3ZQ40f5bSw8P9n5OtWl1t86nV5Qfh4zNRPFbsciyyHyU3Qi4Ga1oTiTwzrPIZQXLw==
2015-01-27T18:29:12|My super secret information.

$ node aes256cbc.js && php aes256cbc.php
zra3FX4iyCc7qPc1dZs+G6B6+8aavHNc/Ymv9L6Omod8Di3tMbvOa2B7O2Yiyoutm9fy9l0G+P5VJT9z2qNESA==
2015-01-27T18:29:15|My super secret information.
zra3FX4iyCc7qPc1dZs+G6B6+8aavHNc/Ymv9L6Omod8Di3tMbvOa2B7O2Yiyoutm9fy9l0G+P5VJT9z2qNESA==
2015-01-27T18:29:15|My super secret information.

$ node aes256cbc.js && php aes256cbc.php
zra3FX4iyCc7qPc1dZs+G4oD1Fr5yLByON6QDE56UOqP6kkfGJzpyH6TbwZYX2oGlh2JGv+aHYUMh0qQnAj/uw==
2015-01-27T18:29:29|My super secret information.
zra3FX4iyCc7qPc1dZs+G4oD1Fr5yLByON6QDE56UOqP6kkfGJzpyH6TbwZYX2oGlh2JGv+aHYUMh0qQnAj/uw==
2015-01-27T18:29:29|My super secret information.

$ node aes256cbc.js && php aes256cbc.php
zra3FX4iyCc7qPc1dZs+G5OVCbCaUy8a0LLF+Bn8UT4X3nYbtynO0Zt2mvXnnli9dRxrxMw43uWnkh8MIwVHXA==
2015-01-27T18:29:31|My super secret information.
zra3FX4iyCc7qPc1dZs+G5OVCbCaUy8a0LLF+Bn8UT4X3nYbtynO0Zt2mvXnnli9dRxrxMw43uWnkh8MIwVHXA==
2015-01-27T18:29:31|My super secret information.

$ node aes256cbc.js && php aes256cbc.php
fdsqSyHBJjlwD0jYfOUZM2FrONG6Fk5d7FOItYEdbnaZIhhmg/apa8/jPwKFkDXD9eNqWC3w0JzY5wjtZADiBA==
2015-01-27T18:30:08|My super secret information.
fdsqSyHBJjlwD0jYfOUZM2FrONG6Fk5d7FOItYEdbnaZIhhmg/apa8/jPwKFkDXD9eNqWC3w0JzY5wjtZADiBA==
2015-01-27T18:30:08|My super secret information.

$ node aes256cbc.js && php aes256cbc.php
fdsqSyHBJjlwD0jYfOUZM4SRfi6jG5EoDFEF6d9xCIyluXSiMaKlhd89ovpeOz/YyEIlPbYR4ly00gf6hWfKHw==
2015-01-27T18:30:45|My super secret information.
fdsqSyHBJjlwD0jYfOUZM4SRfi6jG5EoDFEF6d9xCIyluXSiMaKlhd89ovpeOz/YyEIlPbYR4ly00gf6hWfKHw==
2015-01-27T18:30:45|My super secret information.

NOTE:

I use a "timestamp|message" format to avoid man in the middle attacks. For example, if the encrypted message contains an ID to be authenticated, the MitM could capture the message and re-send it every time he wants to re-authenticate.

Therefore, I could check the timestamp on the encrypted message to be within a little time interval. This way, the same message is encrypted differently each second because of the timestamp, and could not be used out of this fixed time interval.

EDIT:

Here I was misusing the Initialization Vector (IV). As @ArtjomB. explained, the IV should be the first part of the encrypted message, and also it should be a random value. It's also recommended to use a hmac value in a HTTP Header (x-hmac: *value*) in order to validate that the message was originated from a valid source (but this does not address the "re-send" message issue previously described).

Here's the improved version, including the hmac for php and node and the IV as a part of the encrypted message:

aes256cbc.js (v2)

var crypto = require('crypto');

var encrypt = function (message, method, secret, hmac) {
    //var iv = crypto.randomBytes(16).toString('hex').substr(0,16);    //use this in production
    var iv = secret.substr(0,16);    //using this for testing purposes (to have the same encryption IV in PHP and Node encryptors)
    var encryptor = crypto.createCipheriv(method, secret, iv);
    var encrypted = new Buffer(iv).toString('base64') + encryptor.update(message, 'utf8', 'base64') + encryptor.final('base64');
    hmac.value = 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.value) {
        var iv = new Buffer(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);
    }
}

var message = 'My super secret information.';
var method = 'AES-256-CBC';
var secret = "My32charPasswordAndInitVectorStr"; //must be 32 char length
var hmac = {};

//var encrypted = encrypt(message, method, secret, hmac);
//var decrypted = decrypt(encrypted, method, secret, hmac);
var encrypted = encryptWithTSValidation(message, method, secret, hmac);
var decrypted = decryptWithTSValidation(encrypted, method, secret, hmac, 60*60*12); //60*60m*12=12h

console.log("Use HTTP header 'x-hmac: " + hmac.value + "' for validating against MitM-attacks.");
console.log("Encrypted: " + encrypted);
console.log("Decrypted: " + decrypted);

Note that crypto.createHmac(...).digest('hex') is digested with hex. This is the default in PHP for hmac.

aes256cbc.php (v2)

<?php

function encrypt ($message, $method, $secret, &$hmac) {
    //$iv = substr(bin2hex(openssl_random_pseudo_bytes(16)),0,16);    //use this in production
    $iv = substr($secret, 0, 16);        //using this for testing purposes (to have the same encryption IV in PHP and Node encryptors)
    $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);
    }
}

$message = "My super secret information.";
$method = "AES-256-CBC";
$secret = "My32charPasswordAndInitVectorStr";  //must be 32 char length

//$encrypted = encrypt($message, $method, $secret, $hmac);
//$decrypted = decrypt($encrypted, $method, $secret, $hmac);

$encrypted = encryptWithTSValidation($message, $method, $secret, $hmac);
$decrypted = decryptWithTSValidation($encrypted, $method, $secret, $hmac, 60*60*12); //60*60m*12=12h

echo "Use HTTP header 'x-hmac: $hmac' for validating against MitM-attacks.
";
echo "Encrypted: $encrypted
";
echo "Decrypted: $decrypted
";
?>

Here are some sample runs:

$ node aes256cbc.js && php aes256cbc.php
Use HTTP header 'x-hmac: 6862972ef0f463bf48523fc9e334bb42' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==I6cAKeoxeSP5TGgtK59PotB/iG2BUSU8Y6NhAhVabN9UB+ZCTn7q2in4JyLwQiGN
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 6862972ef0f463bf48523fc9e334bb42' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==I6cAKeoxeSP5TGgtK59PotB/iG2BUSU8Y6NhAhVabN9UB+ZCTn7q2in4JyLwQiGN
Decrypted: My super secret information.

$ node aes256cbc.js && php aes256cbc.php
Use HTTP header 'x-hmac: b2e63f216acde938a82142220652cf59' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CSgYBBR8dkZytORm8xwEDmD9WB1mpqC3XnSrB+wR3/KW
Decrypted: My super secret information.
Use HTTP header 'x-hmac: b2e63f216acde938a82142220652cf59' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CSgYBBR8dkZytORm8xwEDmD9WB1mpqC3XnSrB+wR3/KW
Decrypted: My super secret information.

$ node aes256cbc.js && php aes256cbc.php
Use HTTP header 'x-hmac: 73181744453d55eb6f81896ffd284cd8' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CTGik4Lv9PnWuEg5SiADJcdKX1to0LrNKmuCiYIweBAZ
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 73181744453d55eb6f81896ffd284cd8' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CTGik4Lv9PnWuEg5SiADJcdKX1to0LrNKmuCiYIweBAZ
Decrypted: My super secret information.

$ node aes256cbc.js && php aes256cbc.php
Use HTTP header 'x-hmac: 5372ecca442d65f582866cf3b24cb2b6' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CYEITF6aozBNp7bA54qY0Ugg9v6ktwoH6nqRyatkFqy8
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 5372ecca442d65f582866cf3b24cb2b6' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CYEITF6aozBNp7bA54qY0Ugg9v6ktwoH6nqRyatkFqy8
Decrypted: My super secret information.

Last but not least, if you don't have openssl mod installed in php, you can use mcrypt instead with rijndael128 and pkcs7 padding (source) like this:

aes256cbc-mcrypt.php (v2)

<?php

function pkcs7pad($message) {
    $padding = 16 - (strlen($message) % 16);
    return $message . str_repeat(chr($padding), $padding);
}

function pkcs7unpad($message) {
    $padding = ord(substr($message, -1));  //get last char and transform it to Int
    return substr($message, 0, -$padding); //remove the last 'padding' string
}

function encrypt ($message, $method, $secret, &$hmac) {
    //$iv = substr(bin2hex(mcrypt_create_iv(mcrypt_get_iv_size($method, MCRYPT_MODE_CBC), MCRYPT_DEV_URANDOM)),0,16);    //use this in production
    $iv = substr($secret, 0, 16);    //using this for testing purposes (to have the same encryption IV in PHP and Node encryptors)
    $message = pkcs7pad($message);
    $encrypted = base64_encode($iv) . base64_encode(mcrypt_encrypt($method, $secret, $message, MCRYPT_MODE_CBC, $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 pkcs7unpad(mcrypt_decrypt($method, $secret , base64_decode(substr($encrypted, 24)) , MCRYPT_MODE_CBC, $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();
    //echo "Decrypted: $decrypted
";
    $msgDate = new DateTime(str_replace("T"," ",substr($decrypted,0,19)));
    if (($now->getTimestamp() - $msgDate->getTimestamp()) <= $intervalThreshold) {
        return substr($decrypted,19);
    }
}

$message = "My super secret information.";
$method = MCRYPT_RIJNDAEL_128;
$secret = "My32charPasswordAndInitVectorStr";  //must be 32 char length

//$encrypted = encrypt($message, $method, $secret, $hmac);
//$decrypted = decrypt($encrypted, $method, $secret, $hmac);

$encrypted = encryptWithTSValidation($message, $method, $secret, $hmac);
$decrypted = decryptWithTSValidation($encrypted, $method, $secret, $hmac, 60*60*12); //60*60m*12=12h

echo "Use HTTP header 'x-hmac: $hmac' for validating against MitM-attacks.
";
echo "Encrypted: $encrypted
";
echo "Decrypted: $decrypted
";
?>

Ofcourse, some tests next:

$ php aes256cbc-mcrypt.php && node aes256cbc.js 
Use HTTP header 'x-hmac: 801282a9ed6b2d5bd2254140d7a17582' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v9IyatyGeNT2yebrpJZ5xH73H5fFcV1zhqhRGwM0ToGU
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 801282a9ed6b2d5bd2254140d7a17582' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v9IyatyGeNT2yebrpJZ5xH73H5fFcV1zhqhRGwM0ToGU
Decrypted: My super secret information.
$ php aes256cbc-mcrypt.php && node aes256cbc.js 
Use HTTP header 'x-hmac: 0ab2bc83108e1e250f6ecd483cd65329' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v79P+j4YUl8ln8eu7FDqEdbxMe1Z7BvW8iVUN1qFCiHM
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 0ab2bc83108e1e250f6ecd483cd65329' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v79P+j4YUl8ln8eu7FDqEdbxMe1Z7BvW8iVUN1qFCiHM
Decrypted: My super secret information.

這篇關于在 PHP 中加密字符串并在 Node.js 中解密的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Joining 2 tables in SELECT(MYSQL/PHP)(在 SELECT(MYSQL/PHP) 中加入 2 個表)
How to make lt;option selected=quot;selectedquot;gt; set by MySQL and PHP?(如何使lt;option selected=“selectedgt;由 MySQL 和 PHP 設置?)
Auto populate a select box using an array in PHP(使用 PHP 中的數組自動填充選擇框)
PHP SQL SELECT where like search item with multiple words(PHP SQL SELECT where like search item with multiple words)
json_encode produce JSON_ERROR_UTF8 from MSSQL-SELECT(json_encode 從 MSSQL-SELECT 產生 JSON_ERROR_UTF8)
MySQL ORDER BY rand(), name ASC(MySQL ORDER BY rand(),名稱 ASC)
主站蜘蛛池模板: 久久精品国产免费一区二区三区 | 亚洲欧美中文日韩在线v日本 | 天天天天操 | 中文字幕在线播放第一页 | 亚洲精品性视频 | 日本激情视频网 | 一级毛片视频免费观看 | 亚洲第1页 | 国产日韩欧美精品 | 96国产精品久久久久aⅴ四区 | 免费精品视频一区 | av中文字幕在线观看 | 亚洲精品电影在线观看 | 97超碰人人 | 国产美女永久免费无遮挡 | 婷婷激情综合 | 超碰精品在线 | 日韩精品一区二区三区第95 | 红桃视频一区二区三区免费 | 一区二区三区亚洲 | 久热精品视频 | 国产精品久久久久久久 | av中文字幕在线观看 | 天天操夜夜拍 | 日韩一区中文字幕 | 日本免费一区二区三区 | 狠狠操av | zzzwww在线看片免费 | 谁有毛片 | 久久这里只有精品首页 | 欧美在线免费 | 久久久精品黄色 | 在线观看国产视频 | 美女爽到呻吟久久久久 | 一二区视频 | 中国大陆高清aⅴ毛片 | 欧美一级三级 | 九九热免费在线观看 | 激情综合五月 | 欧美精品国产精品 | 国产成人精品一区二 |