【问题标题】:encryption in PHP and decryption in node.jsPHP中的加密和node.js中的解密
【发布时间】:2014-10-28 17:13:28
【问题描述】:

我通过阅读有关堆栈溢出的各种答案尝试了建议和技巧,但它们似乎还不够,或者我可能缺少一些基本的东西。基本上,我正在尝试加密 php 中的值并将其传递到网页,从该网页由 JavaScript 读取并发送到节点服务器进行处理。但我无法在我用 php 加密的节点服务器上取回相同的值。

下面是php代码,php版本是5.5.12,在windows 7 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 填充攻击。如果您能建议我如何使其安全,那就太好了。

谢谢

【问题讨论】:

    标签: javascript php node.js encryption character-encoding


    【解决方案1】:

    问题可能与您的编码有关:

    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”(@ 987654321@).

    【讨论】:

    • 关于十六进制作为输入编码我把它留在那里,因为节点文档说如果输入是一个缓冲区,那么提供的编码将被忽略。这似乎是一个版本问题。你在什么环境下测试过?
    • @Avdhesh:PHP 5.3.6 / Ubuntu,节点 v0.11.12 / OSX Mavericks。
    • 我的错。实际上我遇到了与之前相同的错误“致命:1414489055585:TypeError:错误:06065064:数字信封例程:EVP_DecryptFinal_ex:错误解密”
    • @Avdhesh:您是否完全按照发布的方式运行这些代码?
    • 我再次检查,似乎我在 php 中使用之前对密钥进行了哈希处理。所以不行。我现在完全按照您上面发布的代码完成了它,并且它成功运行。非常感谢,我很抱歉造成混乱。你是男人
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 2012-06-26
    • 1970-01-01
    相关资源
    最近更新 更多