关于 RSA 签名问题的 Nodejs 解决方案

发布于 1周前 作者 wuwangju 来自 nodejs/Nestjs

关于 RSA 签名问题的 Nodejs 解决方案

最近在接 SDK 支付的时候遇到一个签名问题,文档里给了 php demo,我拿过来也跑通了,但是把签名算法换成 nodejs 怎么跑都不通,不知道为啥。麻烦大佬帮忙看看

private_key

MIICXgIBAAKBgQDZjpotEmPKwRPKeqb6kqLgmiJkmUQ6EgMAlHBLCAdykb8mAKNWPFs+uyyknOAg+kqQzS9oEoF1P2YYDzYLVQeU4x2c9PtLPMxhXOqdiS6tdJ7RBa2SS4z0WaPmjGAds8qvVnec8Kp5/UXpIDXHRfJ7vNCwNB5O1BEJO/uIRMNIOwIDAQABAoGBAM/HCOpo+NPIyN0FfPotF8/IhXZshqOrViC0o/aU6X/7QILL8zNGG6Ly4nUouknkoVhgDpmnqupOrXPm+yehgsVljoeYRDVEmoyPvFNm+lbv5iDsnHlOohkyEdIO8tMYX7FT269YjWd7PGV1cnHqYUUAq0ncxbu2/RbPbXXsWcAJAkEA83tyOnvKMm46wEaLYXbUzS2iWCv+X0/4h5IKU9q9D2kYhApGaPIOWKf7qtLigkwvSwZ6ZU4kPKcmM817WR64vwJBAOS98iTBD6tYMe6U0Y5E1rO/sQQrIpMwJ2Y6PJQ/uU8z6rXsbEztUR/pbEExkf2a0xCByRxPEwrIRgzBat2Q84UCQHvAvLhY/tZPDHF56ZHqMhLvJNqn0axkGy/c3H7uaLWSdzF1f4ALt5r8FoAmm5YaXtdFPaSL6QMi+dnOkOklIkUCQQCFt0AhGjb1vCXcSWTDHRzBkRKC1FBu6JxvlyWoqCPE2B2h4aZhxe1BkWu2JKsqLGKr6KLPCK6iA/dnJ344La8dAkEA71Mz9WB4fhhU3e284lM1Y6ybS+F5a04racip9NbRAp9bnaDXDBO/EeFM4JZtb48IgnIJ0hfe09y+MDFgw4tgFA==

要加密的数据

var data ={"appid":"301074772","waresid":1,"cporderid":"123412zxcvzasdfqwesdfdsrasdghj","price":0.01,"currency":"RMB","appuserid":"10123059","cpprivateinfo":"11qwe123r23q232111"}

php 代码

/**格式化公钥
 * $priKey PKCS#1 格式的私钥串
 * return pem 格式私钥, 可以保存为.pem 文件
 */
function formatPriKey($priKey) {
    $fKey = "-----BEGIN RSA PRIVATE KEY-----\n";
    $len = strlen($priKey);
    for($i = 0; $i < $len; ) {
        $fKey = $fKey . substr($priKey, $i, 64) . "\n";
        $i += 64;
    }
    $fKey .= "-----END RSA PRIVATE KEY-----";
    return $fKey;
}
function sign($data, $priKey) {
    //转换为 openssl 密钥
    $res = openssl_get_privatekey($priKey);
	$content = json_encode($data);
    //调用 openssl 内置签名方法,生成签名$sign
    openssl_sign($content, $sign, $res, OPENSSL_ALGO_MD5);
//释放资源
openssl_free_key($res);

//base64 编码
$sign = base64_encode($sign);
return $sign;

}

php 得到的结果是: YK5XuhB+ZhntOwm/riSCaCIqqLlrih+VgBRQa3H5VCUU6P/o38c+Q/UduQqFMQhLH7aZJ/z3ovSwgVxy+WFThGPthaQUPsLrALLZlReAcpuql28V8mD16WAnvxfY6R76jtdz4pF8gxNg4GeWXJXHc5M8RhInPeAai7F4gUlIbWI=

nodejs 代码如下:

function () {
    data = JSON.stringify(data);
    var p_key = '-----BEGIN RSA PRIVATE KEY-----\n';
    var strLength = Math.ceil(key.length / 64);
    for (var i = 0; i < strLength; i++) {
        var temp = key.substr(64 * i, 64);
        p_key += temp + '\n';
    }
    p_key += "-----END RSA PRIVATE KEY-----";
var sign = crypto.createSign('RSA-SHA256'); // 这里 SHA1 和 SHA256 都试了一直不对
var b = new Buffer(str);
sign.update(b);
return sign.sign(p_key, 'base64');

};

nodejs 结果: veNheq8kz/OyphVRNwHqXYYWhFJ/pqqkwDyKPwg29ig1wlzoEAzTfvDAN7Eoe+RGUW41dvRO7RjKaPRFdzihglmBwPQMBzzIeLGcJgb1vF41UFwNGIPnAa9HDqcIBWOLzSf72Qe26x0Qa15R80ZSJO8ztXxzshcqC/BqkaFAnMY=


4 回复

不是写的 MD5 么?

怎么又成了 SHA1 ?


解决了。 确实是 MD5。 文档里说 RSA。我就一直在 RSA😂

2017 年已经 sha1 碰撞了,建议升级到 sha2-256 以上

关于 RSA 签名问题的 Node.js 解决方案,你可以使用 Node.js 内置的 crypto 模块来处理。以下是一个基本的示例,展示了如何生成 RSA 密钥对、创建签名以及验证签名。

首先,确保你的 Node.js 环境已经安装。然后,你可以使用以下代码:

const crypto = require('crypto');

// 生成 RSA 密钥对
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
  modulusLength: 2048,
});

const data = '这是一段需要签名的数据';
const buffer = Buffer.from(data, 'utf8');

// 创建签名
const signature = crypto.createSign('SHA256');
signature.update(buffer);
signature.end();
const sign = signature.sign(privateKey, 'hex');

console.log('签名:', sign);

// 验证签名
const verify = crypto.createVerify('SHA256');
verify.update(buffer);
verify.end();
const isValid = verify.verify(publicKey, sign, 'hex');

console.log('签名验证结果:', isValid ? '成功' : '失败');

在这个示例中,我们首先生成了一个 RSA 密钥对,包括公钥和私钥。然后,我们使用私钥对数据进行了签名,并使用公钥对签名进行了验证。

注意,crypto.generateKeyPairSync 是一个同步方法,用于生成密钥对。如果你需要异步操作,可以使用 crypto.generateKeyPair 方法。

这个示例展示了基本的 RSA 签名和验证流程,你可以根据实际需求进行调整和扩展。

回到顶部