Nodejs RSA 解密问题
Nodejs RSA 解密问题
最近在做酷派支付验证,遇到签名验证问题,卡好久了。
源数据如下:
var trans_data = '{"exorderno":"10004200000001100042","transid":"02113013118562300203","waresid":1,"appid":"20004600000001200046","feetype":0,"money":3000,"count":1,"result":0,"transtype":0,"transtime":"2013-01-31 18:57:27","cpprivate":"123456"}';
var key = 'MjhERTEwQkFBRDJBRTRERDhDM0FBNkZBMzNFQ0RFMTFCQTBCQzE3QU1UUTRPRFV6TkRjeU16UTVNRFUyTnpnek9ETXJNVE15T1RRME9EZzROVGsyTVRreU1ETXdNRE0zTnpjd01EazNNekV5T1RJek1qUXlNemN4';
var sign = '28adee792782d2f723e17ee1ef877e7 166bc3119507f43b06977786376c0434 633cabdb9ee80044bc8108d2e9b3c86e';
这个 key 经过 2 次 base64_decode 拿到的有效数据为:14885347234905678383+132944888596192030037770097312923242371
其中+的前面为 privatekey,后面为 modkey
文档里是这样写的: key = base64(${private_key}+${mod_key}),即 key 是由 private_key 和 mod_key 中间用加号“+”连接后做了 base64 编码得到的字符串。商户需要先把 private_key 和 mod_key 从 key 中解析出来。然后用 RSA 算法和解析出来的 keys 对签名 sign 进行解密得到的字符串,与将 transdata 进行 MD5 加密后的字符串进行比较。如果两者相等,则签名验证通过。
我在网上有找到这个:RSAKeyPair
,但是都只有说加密,没说解密,我找到了它的解密函数,但是解出来是乱码
我自己先用简单的数据加密,然后再调它的解密,出来还是乱码。
对加解密这块的知识实在是匮乏,求各位大神帮忙,解决了红包感谢!
我现在临时的解决方案是:解密算法用 php 实现的,然后用 node 执行 php 脚本
RSA 加解密原理是一样,加密用公钥,解密用私钥,你找到了加密方法,就找到了解密方法,另外你暴露出 privatekey 是不是不太好
还有那个 sign 就是 transdata 进行 MD5 之后,用发送方的 私钥 进行 RSA 加密后的数据,
你要做的就是 把 sign 用 发送方的公钥 进行 RSA 加密,比对一下 transdata 的 MD5 值 ,如果相等则证明消息来源于发送方,因为只有发送方才具有私钥。其中 RSA 加密都是一样的方法,只是传递的密钥不同
既然有 php 代码了,那照着翻译一遍就好了,楼主要懒得写可以出钱雇人翻译,这种有代码你给几个输入输出的值,这么需求明确的活很多人愿意接的
Google 搜索一下就有了: https://github.com/rzcoder/node-rsa
既然暴露了私钥就重新生成一对密钥吧。
我把 14885347234905678383+132944888596192030037770097312923242371 使用 base64 加密两次结果跟楼主不一样,大概问题在这里吧。
TVRRNE9EVXpORGN5TXpRNU1EVTJOemd6T0RNck1UTXlPVFEwT0RnNE5UazJNVGt5
TURNd01ETTNOemN3TURrMwpNekV5T1RJek1qUXlNemN4Q2c9PQo=
谢谢你的恢复
没事的,这个数据是 demo 里的
我知道的 RSA-MD5 是用发送方用私钥加密,然后接收方拿到签名后,用公钥进行验签。
但是酷派给的这个 是解密,而且它给过来的 key 也不是 RSA 格式的。它的 php demo 里确实是解密了。
这是 demo 里的,没事的。
它这个很奇葩,key 第一次 base64_decode 之后,会把结果里前面 40 个长度的字符串去掉,即取 41 到结尾的字符串再 base64_decode 一次 结果就正常了,demo 里就是这样写的。
这个我看过了。不是的。
你发 PHP 解密来看看?
<br>CoolpayDecryptDemo.php<br><?php<br><br>require 'CoolpayDecrypt.php';<br><br>//以下三个数据为演示数据 trans_data 和 sign 为报文中获取的字段,key 为从商户自服务获取的应用密钥。<br>$trans_data = '{"exorderno":"10004200000001100042","transid":"02113013118562300203","waresid":1,"appid":"20004600000001200046","feetype":0,"money":3000,"count":1,"result":0,"transtype":0,"transtime":"2013-01-31 18:57:27","cpprivate":"123456"}';<br>$key = 'MjhERTEwQkFBRDJBRTRERDhDM0FBNkZBMzNFQ0RFMTFCQTBCQzE3QU1UUTRPRFV6TkRjeU16UTVNRFUyTnpnek9ETXJNVE15T1RRME9EZzROVGsyTVRreU1ETXdNRE0zTnpjd01EazNNekV5T1RJek1qUXlNemN4';<br>$sign = '28adee792782d2f723e17ee1ef877e7 166bc3119507f43b06977786376c0434 633cabdb9ee80044bc8108d2e9b3c86e';<br>// $sign ='2b6efac86ef6b58448a8d13a7341a904 fc56eaddca4ad6b2b95c3762dd0cb9b 2dc35815c9a1da8128112501b809c6c1';<br><br>$tools = new CoolpayDecrypt();<br>$result = $tools->validsign($trans_data,$sign,$key);<br>// $result = $tools->gensign($trans_data,$key);<br>// echo $result;<br>if($result == 0)<br> //验签名成功,添加处理业务逻辑的代码;<br> echo 'SUCCESS';<br>else<br> echo 'FAILED';<br>?><br>
CoolpayDecrypt.php
<?php
require ‘RSAUtil.php’;
class CoolpayDecrypt{
public function validsign($trans_data,$sign,$key){
$rsa = new RSAUtil();
//解析 key 需要从商户自服务提供的 key 中解析出我们的真正的 key. 商户自服务提供的 key = mybase64(private_key+mod_key);
$key1 = base64_decode($key);
//echo “$key1”;
$key2 = substr($key1,40,strlen($key1)-40);
// echo “$key2”;
$key3 = base64_decode($key2);
// echo “$key3”;
//php 5.3 环境用下面这个
if(phpversion () > “5.3”){
list($private_key, $mod_key) = explode("+", $key3);
}else{
list($private_key, $mod_key) = split("\+", $key3);
}
//使用解析出来的 key,解密包体中传过来的 sign 签名值
$sign_md5 = $rsa->decrypt($sign, $private_key, $mod_key);
$msg_md5 = md5($trans_data);
return strcmp($msg_md5,$sign_md5);
}
}
?>
RSAUtil.php 这个里面基本就只用到了这个函数
require ‘Math.php’;
public function decrypt($string, $d, $n){
//解决某些机器验签时好时坏的 bug
//BCMath 里面的函数 有的机器 php.ini 设置不起作用
//要在 RSAUtil 的方法 decrypt 加 bcscale(0);这样一行代码才行
//要不有的机器计算的时候会有小数点 就会失败
bcscale(0);
$bln = $this->keylen * 2 - 1;
$bitlen = ceil($bln / 8);
$arr = explode(’ ', $string);
$data = ‘’;
foreach($arr as $v){
$v = Math::hex2dec($v);
$v = bcpowmod($v, $d, $n);
$data .= Math::int2byte($v);
}
return trim($data);
}
然后还有一个 Math.php 文件 就是在 RSAUtil.php 里会用到,不过代码有点多
不好意思,这个格式太乱了,不知道怎么格式化
看了下代码,不难啊。64510824,可以跟你交流一下
6453 10824,qq 号
加您了
这个解密函数好像是自己写的吧,我没学过 php,不过查了下几个函数,都是很基本的。你自己用 node 一点点照着写就行了。
好像和 RSA 没关系,就是用 2 个 key,把 sign 还原成 MD5 值。然后和原始数据的 MD5 值比较
楼主你看下 Math::hex2dec(), Math::int2byte()是怎么实现的
是啊,之前没解决就放那了,最近又要接,没法了。只能再来搞了。
它这里面牵涉到大量的 BigInt 以及位与运算,实在是难搞定
都是一些 BigInt 以及位与运算什么的
我的意思是如果你想自己写的话就要参考那两个函数了, 因为 RSA 算法大家应该用的都是同一个, 但输入和输出似乎是用那两个函数自定义了。
好的,谢谢!
那 2 个好像是普通的进制转换吧
不懂 PHP,不过看名字好像是的。因为刚刚拿私钥验证了一下发现对不上就怀疑那两个函数是不是有进行其他的格式化。随手试的,说错了请见谅。
非常感谢,稍等 我先看看,如果没问题一定红包感谢你!😀
针对您提到的Node.js RSA解密问题,以下是一个基本的示例,展示如何使用Node.js进行RSA解密。我们将使用Node.js内置的crypto
模块来实现这一功能。
首先,确保您已经安装了Node.js。然后,您可以创建一个JavaScript文件(例如rsaDecrypt.js
),并在其中编写以下代码:
const crypto = require('crypto');
// 示例私钥(PEM格式)
const privateKey = `-----BEGIN RSA PRIVATE KEY-----
...(您的私钥内容)
-----END RSA PRIVATE KEY-----`;
// 加密后的数据(Base64编码)
const encryptedData = '...(您的加密数据)';
// 将加密数据转换为Buffer
const encryptedBuffer = Buffer.from(encryptedData, 'base64');
// 创建解密对象
const decrypt = crypto.createDecrypt({
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PADDING
});
// 执行解密
decrypt.update(encryptedBuffer);
const decrypted = decrypt.final('utf8');
console.log('解密后的数据:', decrypted);
在上面的代码中,请将...(您的私钥内容)
替换为您的RSA私钥,...(您的加密数据)
替换为您的加密数据(Base64编码)。
运行此脚本时,它将使用提供的私钥解密加密数据,并输出解密后的内容。
请注意,RSA解密过程中涉及的密钥和数据应妥善保管,以避免安全风险。此外,根据具体需求,您可能需要调整填充方式(padding
)和其他参数。如果加密数据采用其他编码方式,也需相应调整Buffer.from
的参数。