2014-10-28 115 views
0

我已經通過閱讀關於堆棧溢出的各種答案嘗試了一些建議和技巧,但它們似乎並不足夠,或者可能存在一些基本的東西。基本上我試圖在php中加密一個值,並將它傳遞到JavaScript所讀取的網頁併發送到節點服務器進行處理。但我無法獲得相同的價值回到節點服務器,我用PHP加密。PHP中的加密和node.js中的解密

下面是PHP代碼和PHP的版本是運行在Windows 7 5.5.12 64位: -

function encrypt($string){ 
$key = hash("SHA256", '1d417e2ffb2a00a3', true); 
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
$padding = $blockSize - (strlen($string) % $blockSize); 
$string .= str_repeat(chr($padding), $padding); 

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,$string, MCRYPT_MODE_CBC, $iv); 
$result['cipher'] = base64_encode($ciphertext); 
$result['iv'] = base64_encode($iv); 
return $result; 
} 

我的node.js版本0.10.31運行在Windows 7 64位和代碼如下: -

var express = require("express"); 
var Server = require("http").Server; 
var cookie = require("cookie"); 
var app = express(); 
var server = Server(app); 
var sio = require("socket.io")(server); 
var crypto = require('crypto'); 

sio.sockets.on("connection", function(socket) { 
try{ 
     socket.on('incoming_data', function(data){ 
      var txt = new Buffer(data.encrypted_text,'base64'); 
      var key = new Buffer('1d417e2ffb2a00a3','utf8'); 
      var iv = new Buffer(data.iv,'base64'); 
      var decipher = crypto.createDecipheriv('aes-128-cbc',key,iv); 
      var chunks = []; 
      chunks.push(decipher.update(txt,'hex','binary')); 
      chunks.push(decipher.final('binary')); 
      var fuid = chunks.join(''); 
      console.log(fuid); 
     }); 
    }catch(e){ 
     console.log("err:-"+e); 
     console.log(e); 
    } 
});// on connection ends 
server.listen(9267, function(){ 
    console.log('Node server listening on *:9267'); 
}); 

process.on('uncaughtException', function(err) { 
    console.log("FATAL: "+new Date().getTime()+": "+err); 
}); 

錯誤我從控制檯的NodeJS打印FUID得到的是如下: -

FATAL: 1414483246855: TypeError: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt 

我要找答案如下: -

1)我的代碼存在問題,需要修復哪些內容才能在節點服務器上獲取與字符串相同的值。

2)想要連接加密文本和iv並將它們作爲單個base64編碼字符串發送到服務器。所以想要將代碼分離回節點服務器所需的代碼準備好傳遞給加密模塊。

3)此代碼似乎容易受到Oracle填充攻擊的影響。如果你能建議我怎樣才能保證安全,這將是非常棒的。

感謝

回答

0

的問題可能是您的編碼:

chunks.push(decipher.update(txt,'hex','binary')); 

hex看起來很奇怪,因爲你輸入的緩衝區,而不是字符串。

下快速測試作品(還回答2):

PHP:

$key = 'secretsecretsecr'; 
$string = 'attack at dawn'; 

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
$padding = $blockSize - (strlen($string) % $blockSize); 
$string .= str_repeat(chr($padding), $padding); 
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,$string, MCRYPT_MODE_CBC, $iv); 

$packet = chr($iv_size) . $iv . $ciphertext; 

print base64_encode($packet); 

節點:

var crypto = require('crypto'); 

var key = 'secretsecretsecr'; 
var data = 'paste what the php code printed'; 

var txt = new Buffer(data,'base64'); 
var iv_size = txt[0]; 
var iv = txt.slice(1, iv_size + 1); 
var ct = txt.slice(iv_size + 1); 
var decipher = crypto.createDecipheriv('aes-128-cbc',key,iv); 
var chunks = []; 
chunks.push(decipher.update(ct)); 
chunks.push(decipher.final()); 

console.log(chunks.join('')); 

的沿通IV大小,你也可以簡單地硬編碼它在節點端。

對於3),我絕不是專家,從我讀過的解決方法是使用HMAC簽名您的加密數據包,以確保它們來自您的應用程序而不是來自「oracle」( http://www.ietf.org/id/draft-mcgrew-aead-aes-cbc-hmac-sha2-05.txt)。

+0

關於十六進制輸入編碼我離開它,因爲節點文檔說,如果輸入是一個緩衝區,那麼提供的編碼將被忽略。這似乎也許是一個版本問題。你測試了什麼環境? – 2014-10-28 09:34:08

+0

@Avdhesh:PHP 5.3.6/Ubuntu,節點v0.11.12/OSX Mavericks。 – georg 2014-10-28 09:37:09

+0

我的不好。實際上我得到了與之前相同的錯誤「致命:1414489055585:TypeError:錯誤:06065064:數字信封例程:EVP_DecryptFinal_ex:錯誤解密」 – 2014-10-28 09:39:33