簡體   English   中英

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

[英]Encrypt string in PHP and decrypt in 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');
return 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: 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

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

本周我正在為同樣的問題苦苦掙扎,但以相反的方式(PHP 加密 -> NodeJS 解密)並設法使此代碼段正常工作:

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\n";
echo "$decryptedMessage\n";
?>

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

以下是一些示例運行:

$ 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.

筆記:

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

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

編輯:

在這里我誤用了初始化向量(IV)。 作為@ArtjomB。 解釋一下,IV應該是加密消息的第一部分,也應該是一個隨機值。 還建議在 HTTP 標頭 ( x-hmac: *value* ) 中使用hmac值以驗證消息是否來自有效來源(但這並沒有解決之前描述的“重新發送”消息問題)。

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

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);

請注意, crypto.createHmac(...).digest('hex')hex消化。 這是 PHP 中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.\n";
echo "Encrypted: $encrypted\n";
echo "Decrypted: $decrypted\n";
?>

以下是一些示例運行:

$ 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.

最后但並非最不重要的是,如果您沒有在 php 中安裝 openssl mod,您可以使用mcrypt代替rijndael128pkcs7填充(),如下所示:

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\n";
    $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.\n";
echo "Encrypted: $encrypted\n";
echo "Decrypted: $decrypted\n";
?>

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

$ 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 單獨工作。 傳入示例文本,對其進行加密,立即解密,並將其與原始明文變量嚴格相等進行比較。 它們完全一樣嗎? 輸出兩者,以及 - 它們是相同的類型並且看起來完全沒有受到干擾嗎? 注意非打印字符 - 檢查長度和字符編碼!

現在,再使用一個比前一個多或少 1 個字符的示例文本執行上述操作。 這可以調試塊大小/零填充問題 - 這很重要。

如果那行得通——而且很少立即行得通,由於難以預測的原因,請繼續使用 Node.js。

在 Node.js 中,做與在 PHP 中所做的相同的事情,即使這看起來像是白​​費力氣——出於其他原因,這一點很快就會顯而易見。 在您的 Node.js 中一起加密和解密。 它是否適用於上述所有相同的附帶條件?

完成后,“有趣”的部分就來了:在 Node.js 和 PHP 中獨立使用相同的加密方法,讓它們都輸出給您“最終”准備傳輸的加密文本。

如果一切順利,它們應該是完美的,完全一樣的。 如果不是,則您的加密實現和方法在系統之間不兼容存在問題。 某些設置錯誤或沖突(可能是零填充或許多其他可能性,或 IV 等),或者您需要嘗試不同的實現。

如果我不得不盲目猜測,我會說 base64 編碼和解碼存在問題(這是最常見的問題)。 事情往往要完成兩次,因為在 Web 應用程序中調試二進制數據類型(通過瀏覽器)可能很棘手。 有時事情被編碼兩次但只解碼一次,或者一種實現將“有幫助地”自動編碼/解碼某些東西而不清楚它在做什么,等等。

也有可能是 Node 和 PHP 之間的零填充實現問題,如下所示: Node.js 中的 AES 加密 PHP 中的解密。 失敗。

您的錯誤代碼強烈建議您解決最后兩個問題。 加密方法預測精確長度的塊大小,如果它們關閉,則表示傳遞給函數的數據已損壞 - 如果插入單個額外字符,或者編碼處理方式不同等,則會發生這種情況。

如果您一次完成上述每一個步驟,確保您不能急於求成,並且必須檢查該過程中每一個辛苦的小步驟,那么應該更清楚到底哪里出了問題,然后就可以了故障排除。

這是codeiginiter框架默認的解密等效js腳本(aes128cbc),希望對大家有所幫助。

 let crypto = require("crypto");
 let secret = 'xxxxxxxxxxxxxxxxxxxx';

 // ikm is initial keying material
 var hkdf = function (hashAlg, salt, ikm) {
  this.hashAlg = hashAlg;

  // create the hash alg to see if it exists and get its length
  var hash = crypto.createHash(this.hashAlg);
  this.hashLength = hash.digest().length;
  this.salt = salt || new Buffer(this.hashLength).fill(0).toString();
  this.ikm = ikm;

  // now we compute the PRK
  var hmac = crypto.createHmac(this.hashAlg, this.salt);
  hmac.update(this.ikm);
  this.prk = hmac.digest();
};

hkdf.prototype = {
derive: function(info, size, cb) {
  var prev = new Buffer(0);
  var output;
  var buffers = [];
  var num_blocks = Math.ceil(size / this.hashLength);
  info = new Buffer(info);

  for (var i=0; i<num_blocks; i++) {
    var hmac = crypto.createHmac(this.hashAlg, this.prk);
    hmac.update(prev);
    hmac.update(info);
    hmac.update(new Buffer([i + 1]));
    prev = hmac.digest();
    buffers.push(prev);
  }

  output = Buffer.concat(buffers, size);
  return output;
}
};

  function decrypt(code)
 {
 if (typeof code !== 'string')
    return false;
 code = code.substring(128);
 var buff = new Buffer(code, 'base64');
 var iv = buff.slice(0, 16);
 var encyptedText = buff.slice(16).toString('base64');
 var _hkdf = new hkdf('sha512', null, secret);
 var derive_key = _hkdf.derive('encryption', secret.length);
 var key = derive_key.slice(0, 16);
 var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
 var result = decipher.update(encyptedText, 'base64');
 result += decipher.final();
 return result.replace(/[']/g, '');
}

基於@inieto 的回答,我創建了兩個簡單的加密和解密類,一個用於php ,另一個用於易於使用的打字稿 https://github.com/5imun/Endecryptor只需包含/導入它們即可。 php 示例:

#Include Endecryptor before using it
$secret = 'hxXxVEVNa3S6OQdgltNoDkbZ10b0MkQV';
$method = 'AES-256-CBC';
$valid_request_TS_interval = 100; # in seconds
$endecryptor = new Endecryptor($secret, $method, $valid_request_TS_interval );

$original_message = '{"test":"Hello, World!"}';
$endecryptor->encryptWithTS($original_message);

echo "Encrypted message: $endecryptor->temp_encrypted\n";
echo "Encrypted message hmac: $endecryptor->temp_hmac\n";

if ( $endecryptor->decryptAndValidateTS( $endecryptor->temp_encrypted, $endecryptor->temp_hmac ) ) {
  echo "Original message:  $original_message\n";
  echo "Decrypted message: $endecryptor->temp_decrypted\n";
} else {
  echo 'Description was not successful';
}

結果:

Encrypted message: MjliMmM5NzljYWQ0YjA4Mw==ULxsH1juCOrieEkiRpHY1CMkKtvSvB5X+b8E9cOcQ7yYt+SUKj+I6FjaGvYjEldt
Encrypted message: hmac: 5aa8f1b268dfef0dc2f48f1a25204e82
Original  message:  {"test":"Hello, World!"}
Decrypted message: {"test":"Hello, World!"}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM