Php RSA PKCS#1加密与NodeJS

Php RSA PKCS#1加密与NodeJS,php,node.js,rsa,cryptojs,phpseclib,Php,Node.js,Rsa,Cryptojs,Phpseclib,我想用公钥和RSA PKCS#1模式加密一些数据。我使用phpseclib库在PHP上完成了这项工作,它可以正常工作 以下是我的PHP代码: <?php include(__DIR__ . DIRECTORY_SEPARATOR . 'phpseclib/Crypt/RSA.php'); $apiKey = 'xxxxxxxxxxxxxxxxxxxx'; $publicKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxx

我想用公钥和RSA PKCS#1模式加密一些数据。我使用
phpseclib
库在PHP上完成了这项工作,它可以正常工作

以下是我的PHP代码:

<?php
include(__DIR__ . DIRECTORY_SEPARATOR . 'phpseclib/Crypt/RSA.php');
$apiKey = 'xxxxxxxxxxxxxxxxxxxx';
$publicKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx';

// request values in JSON format
$Parameters = array(
    "name" => "Example Name",
    "mobile" => "99999999999",
    "remark" => "Product ",
    "email" => "example@example.com",
    "language" => "en",
    "fields" => array (
        "udf1" => "",
        "udf2" => "",
        "udf3" => "",
    ),
);

// Create rsa object
$rsa = new Crypt_RSA();
// Load public key
$rsa->loadKey($publicKey);
// Set the mode to PKCS#1
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);

//Start the loop through the PHP array to encrypt the value
$returnValue = [];
if($Parameters){
    foreach($Parameters as $x => $x_value){
        if($x == "fields"){
            $_Fields = [];
            foreach($x_value as $y => $y_value){
                $ciphertext = $rsa->encrypt($y_value);
                // Convert it into Base64
                $y_value_encrypted = base64_encode($ciphertext);
                // insert the line array into the overall array
                $_Fields[$y] = $y_value_encrypted;  
            }
            $returnValue[$x] = $_Fields;
        }else{
            $ciphertext = $rsa->encrypt($x_value);
            // Convert it into Base64
            $x_value_encrypted = base64_encode($ciphertext);                    
            // insert the line array into the overall array
            $returnValue[$x] = $x_value_encrypted;                  
        }
    }

    print $returnValue;

    $curl = curl_init();
    curl_setopt_array($curl, array(
        CURLOPT_URL => 'https://api.example.com/v1',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => "POST",
        CURLOPT_POSTFIELDS => $returnValue,
        CURLOPT_HTTPHEADER => array(
            "authorization: Bearer $apiKey",
            "content-type: application/json"
        ),
    ));
    $result = curl_exec($curl);
    $err = curl_error($curl);
    curl_close($curl);

    print $result;

}

?>

像我在PHP上做的那样,在NodeJ上使用RSA PKCS#1模式,用公钥加密字符串的正确方法是什么


请注意,加密在NodeJs上有效,但问题在于加密方式。

我建议如下更改Node.js中的加密函数,我相信这将在PHP中正确解密

function encrypt(requestData) {
    var dataToEncrypt = requestData;
    var returnValue = {};
    if (dataToEncrypt) {
        for (var i in dataToEncrypt) {
            //Encrypt 'fields' values
            if (i == 'fields') {
                var fields_array = {};
                var fields = dataToEncrypt[i];
                for (var y in fields) {
                    fields_array[y] = crypto.publicEncrypt({key:publicKey, padding: crypto.constants.RSA_PKCS1_PADDING}, Buffer.from(fields[y], 'utf8') ).toString('base64');
                }
                returnValue[i] = fields_array;
            } else {
                //Encrypt other values
                returnValue[i] = crypto.publicEncrypt({key:publicKey, padding: crypto.constants.RSA_PKCS1_PADDING}, Buffer.from(dataToEncrypt[i], 'utf8') ).toString('base64');
            }
        }
    }

    Send(returnValue);
    return returnValue;
}
输出将如下所示:

{
    "name": "fdz8lUYD0hsmRGz5nqgTvQVZ82rNZylFCQ2It24HHbL1JdKrbFAia9pzLu45AZ0uf45oUo6H8qzVKO/HmJBnWSMI3CYf1HSPcZC4EmtaSE2SIWf7Z29j5lt4vDIwGKDiefMz2IuKcQhnWy3e3/hDi3uhUaKPDczLZ0ZgBAzf9iI=",
    "mobile": "oBYToRCFftSppUNulagXexPmMKag3tXFEQYV2rRq6VobptxkdZB3Thlhrhait+eVP/5lZzkekGgup5o0kTIAPkJdXvr1ttu4dEJNR6oa6TXBZ4YFMx0ndhLS2HJaYbLMQ5JjK7P4iKW6A6wKuEJlTaUjPL1tHXxMwAG5HjdO5zg=",
    "remark": "pXCA406AVprrvcX33zYlrS8jEZ4wsQDc6RJux1mRBb4tj5tp09JgtoLF2rhJ7cjHLEiWpLlHSSBcC5gkOy2eK8prfshQTgJuGvnEqKMMKGwMhKUJebzP+yio4n6SlHqVasU2ejZksDEY7sSj8BIum9JiL8i9ylQ4chBuZNLXGgc=",
    "email": "0g9zm4WlydNfLU0D0V5bOvxS9JiaQ8a/y4qXAlMealmxZegC973g2FttvolgPDUfxU7HfV10bzXbwgfiXJZXodGMrwYiAWDvhQz424I1SrZznhZEE3djHkz6zr69KBR6HV91Yv43AMyAYyHGHI4YIwzs1Pa8fInBnnTUreVvBo8=",
    "language": "yrSJsmCFMi8py6e8iMXiIjn1r/VAiT858ss4GkPPLFOoxtJopC0XLudG9mDh0MQp6bZRIQifiJwsHi07jpSHHOZTCeiO2R0qCF3VI/FCV3YsyUPHSX3ZdKHYqkzIlwhocDKOPt7ZlAlNhW4U8UbBTAq7YsiyPBtkYA/ikxpgsOE=",
    "fields": {
        "udf1": "SdrCwXYnj6zIW51VzQD8TRXScE7lyrr+tn6eglBInoH+yAZE/IRx0R9nNihCUCbvoIL1s6rT5Irl4Y3KB7CGp6b0wIA3itryKhkaVLYUJpqjXen4lqVLPsdsUpAeboJEgcO0aUbhq2ybawAwr5T1IADUyI/5o937zBv2cJkR7dU=",
        "udf2": "Q0FpyOYmOPUju1Xopr2DXTdRgUJKJ4JlmoxwhWoM3ZEYbIkC76UqT7jAyCtJ5yOTpuh9dyX8VMdI0mx8ziT3ytwrjusDcOKPN8D8SNLxszYAabZVPankcB0WlB+u5GN4owyead1NpDzmWvkyHf+iEf7OFHY4FkrEq3h39Vu50TE=",
        "udf3": "fxs3phQu1DFPZbke13ka7veX2DlMD7DcjB98f31G2UqjJW7RTYzBQ8ddNdYWyuRPsG5N9zTGBLvm4+9om2TinAJd+NXJDOjhOf0pihifQJ/hypOjovWCgt5nlaptvd2Gi3vU9ny5LQ0r3CIwU17iTH2w9QCos/Ncta7Ev2VQ83E="
    }
}
我还建议在PHP和Node.js中创建简单的测试脚本,以测试字符串的简单加密和解密

这很好地解决了这个问题。我建议确保Node.js加密的输出可以用PHP解密,反之亦然

simple_encrypt.php

set_include_path(get_include_path() . PATH_SEPARATOR . 'phpseclib');

include(__DIR__  . '/phpseclib/Crypt/RSA.php');

$publicKey = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbVuHaQIctLFZK1oIn2+P2j8z4
1S5kdQSo2AWYRMeo2yd+00ozdYjDpJ9eNpZyk1F7Dx9b+SmU39R0Tz89/IiTL78T
ZTOQ1FFFvktJhKT413QiegBAx09DhX3I+NQwvZWdU9SkptAGz9PD6zIeJTlh5HHA
fC/P+oLUhpQjkd+JBQIDAQAB
-----END PUBLIC KEY-----';

$privateKey = '-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDbVuHaQIctLFZK1oIn2+P2j8z41S5kdQSo2AWYRMeo2yd+00oz
dYjDpJ9eNpZyk1F7Dx9b+SmU39R0Tz89/IiTL78TZTOQ1FFFvktJhKT413QiegBA
x09DhX3I+NQwvZWdU9SkptAGz9PD6zIeJTlh5HHAfC/P+oLUhpQjkd+JBQIDAQAB
AoGAFv4WkuBsyyl4qkOuRSthzDjqzbLbOCCkKmbqvzmGjIbcrwjLIHXTrl6VbjTe
tIgI5JODQArwdvC3vrGH+aF9V27XW4Vl4WllPlBIzvaq1JufPOGupzNmssScFWV5
IL+P1Sx5F22rO+w+lIUdVFgbInITu4Bs2rvKsjAyBmvq7MkCQQD0kQvDWuPWkHSj
xzUjAXl+rT8ZOmANC1x35bLAEUHL2EWCejV9jO48TnwkqOQabT/rEWjrv4g7VHC0
ErNg1bAjAkEA5ZfrSKjyxoEbbK1lQz1GBMpyXGSpbTVJ+eMinBYY4JOnswLLUpmP
/OIJtLrOq38zSzNE2iHoxoGQDt1OlQDgtwJASPG2G3dRe16sm2jALYe0EBdmOYUS
vvFDjDNDhEvhXwZLfSYsLB1LtUsHdfu1xTgOl3Mi4yXGYUPHNb5aKCi0FwJAQGaH
sd7qEnI+jhJpOB4k2M0snOwDdkWfVX+3wo6UNdJVFOpwu9+lOurwjAhmVkaczbg4
1PL0B1JqZTEAjN0tKwJBAMRx0oqN5JNqc3iCrjDxJ9e94t7poVV7if0TfLBVzceR
5mgjPSOMjjkpzVG1P6+37V4whe26u3BhX04PD8Nzl3c=
-----END RSA PRIVATE KEY-----';

$rsa = new Crypt_RSA();
$rsa->loadKey($publicKey);

$plainText = 'abc';

$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$cipherText = $rsa->encrypt($plainText);
$rsa->loadKey($privateKey);

echo "\nEncrypted (base64): " . base64_encode($cipherText);
echo "\nDecrypted: " . $rsa->decrypt($cipherText);
simple_encrypt.js

const crypto = require('crypto');

const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbVuHaQIctLFZK1oIn2+P2j8z4
1S5kdQSo2AWYRMeo2yd+00ozdYjDpJ9eNpZyk1F7Dx9b+SmU39R0Tz89/IiTL78T
ZTOQ1FFFvktJhKT413QiegBAx09DhX3I+NQwvZWdU9SkptAGz9PD6zIeJTlh5HHA
fC/P+oLUhpQjkd+JBQIDAQAB
-----END PUBLIC KEY-----`;

const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDbVuHaQIctLFZK1oIn2+P2j8z41S5kdQSo2AWYRMeo2yd+00oz
dYjDpJ9eNpZyk1F7Dx9b+SmU39R0Tz89/IiTL78TZTOQ1FFFvktJhKT413QiegBA
x09DhX3I+NQwvZWdU9SkptAGz9PD6zIeJTlh5HHAfC/P+oLUhpQjkd+JBQIDAQAB
AoGAFv4WkuBsyyl4qkOuRSthzDjqzbLbOCCkKmbqvzmGjIbcrwjLIHXTrl6VbjTe
tIgI5JODQArwdvC3vrGH+aF9V27XW4Vl4WllPlBIzvaq1JufPOGupzNmssScFWV5
IL+P1Sx5F22rO+w+lIUdVFgbInITu4Bs2rvKsjAyBmvq7MkCQQD0kQvDWuPWkHSj
xzUjAXl+rT8ZOmANC1x35bLAEUHL2EWCejV9jO48TnwkqOQabT/rEWjrv4g7VHC0
ErNg1bAjAkEA5ZfrSKjyxoEbbK1lQz1GBMpyXGSpbTVJ+eMinBYY4JOnswLLUpmP
/OIJtLrOq38zSzNE2iHoxoGQDt1OlQDgtwJASPG2G3dRe16sm2jALYe0EBdmOYUS
vvFDjDNDhEvhXwZLfSYsLB1LtUsHdfu1xTgOl3Mi4yXGYUPHNb5aKCi0FwJAQGaH
sd7qEnI+jhJpOB4k2M0snOwDdkWfVX+3wo6UNdJVFOpwu9+lOurwjAhmVkaczbg4
1PL0B1JqZTEAjN0tKwJBAMRx0oqN5JNqc3iCrjDxJ9e94t7poVV7if0TfLBVzceR
5mgjPSOMjjkpzVG1P6+37V4whe26u3BhX04PD8Nzl3c=
-----END RSA PRIVATE KEY-----`;

const plainText = "abc";

function encryptWithPublicKey(plainText, publicKey) {
    const buffer = Buffer.from(plainText);
    return crypto.publicEncrypt( { key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING } , buffer);
}

function decryptWithPrivateKey(cipherTextBuffer, privateKey) {
    const decrypted = crypto.privateDecrypt( { key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING} , cipherTextBuffer);
    return decrypted.toString("utf8");
}

let cipherText = encryptWithPublicKey(plainText, publicKey);
let decrypted = decryptWithPrivateKey(cipherText, privateKey);

console.log("Encrypted (base64):", cipherText.toString("base64"));
console.log("Decrypted:", decrypted)

NB:我们不希望两个脚本的结果相同,因为输出是不确定的。

if
-和
else
-块中尝试
=
操作符,而不是
+=
操作符。@Topaco感谢您的评论,但是
+=/code>需要将所有字段值添加到结果中。使用
=
操作符无法解决问题。您是否运行了
控制台.log(加密(参数))并检查结果?字段
n
的密文以前一个字段
n-1
的密文开头,开头有一个
未定义的
,例如
name:undefineda…b mobile:undefineda…bc…d备注:undefineda…bc…de…f
等。谢谢@Terry的帮助。我可以确认问题已解决。太好了,很高兴能提供帮助!
const crypto = require('crypto');

const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbVuHaQIctLFZK1oIn2+P2j8z4
1S5kdQSo2AWYRMeo2yd+00ozdYjDpJ9eNpZyk1F7Dx9b+SmU39R0Tz89/IiTL78T
ZTOQ1FFFvktJhKT413QiegBAx09DhX3I+NQwvZWdU9SkptAGz9PD6zIeJTlh5HHA
fC/P+oLUhpQjkd+JBQIDAQAB
-----END PUBLIC KEY-----`;

const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDbVuHaQIctLFZK1oIn2+P2j8z41S5kdQSo2AWYRMeo2yd+00oz
dYjDpJ9eNpZyk1F7Dx9b+SmU39R0Tz89/IiTL78TZTOQ1FFFvktJhKT413QiegBA
x09DhX3I+NQwvZWdU9SkptAGz9PD6zIeJTlh5HHAfC/P+oLUhpQjkd+JBQIDAQAB
AoGAFv4WkuBsyyl4qkOuRSthzDjqzbLbOCCkKmbqvzmGjIbcrwjLIHXTrl6VbjTe
tIgI5JODQArwdvC3vrGH+aF9V27XW4Vl4WllPlBIzvaq1JufPOGupzNmssScFWV5
IL+P1Sx5F22rO+w+lIUdVFgbInITu4Bs2rvKsjAyBmvq7MkCQQD0kQvDWuPWkHSj
xzUjAXl+rT8ZOmANC1x35bLAEUHL2EWCejV9jO48TnwkqOQabT/rEWjrv4g7VHC0
ErNg1bAjAkEA5ZfrSKjyxoEbbK1lQz1GBMpyXGSpbTVJ+eMinBYY4JOnswLLUpmP
/OIJtLrOq38zSzNE2iHoxoGQDt1OlQDgtwJASPG2G3dRe16sm2jALYe0EBdmOYUS
vvFDjDNDhEvhXwZLfSYsLB1LtUsHdfu1xTgOl3Mi4yXGYUPHNb5aKCi0FwJAQGaH
sd7qEnI+jhJpOB4k2M0snOwDdkWfVX+3wo6UNdJVFOpwu9+lOurwjAhmVkaczbg4
1PL0B1JqZTEAjN0tKwJBAMRx0oqN5JNqc3iCrjDxJ9e94t7poVV7if0TfLBVzceR
5mgjPSOMjjkpzVG1P6+37V4whe26u3BhX04PD8Nzl3c=
-----END RSA PRIVATE KEY-----`;

const plainText = "abc";

function encryptWithPublicKey(plainText, publicKey) {
    const buffer = Buffer.from(plainText);
    return crypto.publicEncrypt( { key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING } , buffer);
}

function decryptWithPrivateKey(cipherTextBuffer, privateKey) {
    const decrypted = crypto.privateDecrypt( { key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING} , cipherTextBuffer);
    return decrypted.toString("utf8");
}

let cipherText = encryptWithPublicKey(plainText, publicKey);
let decrypted = decryptWithPrivateKey(cipherText, privateKey);

console.log("Encrypted (base64):", cipherText.toString("base64"));
console.log("Decrypted:", decrypted)