RSA 加密、PHP 加密 (phpseclib) 和 JavaScript 解密 (crypto.subtle)

如何解决RSA 加密、PHP 加密 (phpseclib) 和 JavaScript 解密 (crypto.subtle)

我想要做的是在 javascript 中生成一个密钥对,并在 PHP 中使用这些加密,然后用 JS 解密。

我在附加的代码中有两个问题

  1. 它不会从装甲文本块重新加载私钥
  2. 它不会解密 PHP 加密的内容

两者都抛出错误 DOMException,而不是一个有用的错误。

这是我的代码...

PHP/JAVASCRIPT

<?php
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Crypt\RSA;
if ($_POST) {
    $public=$_POST['public'];
    $data='some text to encrypt';
    $key = PublicKeyLoader::load($public);
    $key = $key->withPadding(RSA::ENCRYPTION_OAEP);
    $encoded=base64_encode($key->encrypt($data));
    header('Content-Type: application/json');
    echo json_encode(array('encrypted'=>$encoded));
    exit;
}
?>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<script>
jQuery(document).ready(function($) {
    function ab2str(buf) {
        return String.fromCharCode.apply(null,new Uint8Array(buf));
    }
    function str2ab(str) {
        var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
        var bufView = new Uint16Array(buf);
        for (var i=0,strLen=str.length; i < strLen; i++) {
            bufView[i] = str.charCodeAt(i);
        }
        return buf;
    }
    function importPrivateKey(pem) {
        // fetch the part of the PEM string between header and footer
        const pemHeader = "-----BEGIN PRIVATE KEY-----\n";
        const pemFooter = "\n-----END PRIVATE KEY-----";
        const pemContents = pem.substring(pemHeader.length,pem.length - pemFooter.length);
        // base64 decode the string to get the binary data
        const binaryDerString = window.atob(pemContents);
        // convert from a binary string to an ArrayBuffer
        const binaryDer = str2ab(binaryDerString);

        return window.crypto.subtle.importKey(
            "pkcs8",binaryDer,{
                name: "RSA-OAEP",modulusLength: 1024,publicExponent: new Uint8Array([1,1]),hash: {name: "SHA-256"}
            },true,["decrypt"]
          );
    }
    (async() => {
        let keyPair = await window.crypto.subtle.generateKey(
          {
                name: "RSA-OAEP",hash: {name: "SHA-256"}
          },["encrypt","decrypt"]
        );
        
        var exported=await window.crypto.subtle.exportKey("pkcs8",keyPair.privateKey);
        var exportedAsString = ab2str(exported);
        var exportedAsBase64 = window.btoa(exportedAsString);
        var private = `-----BEGIN PRIVATE KEY-----\n${exportedAsBase64}\n-----END PRIVATE KEY-----`;
        
        var exported = await window.crypto.subtle.exportKey(
            "spki",keyPair.publicKey
        );
        var exportedAsString = ab2str(exported);
        var exportedAsBase64 = window.btoa(exportedAsString);
        var public = `-----BEGIN PUBLIC KEY-----\n${exportedAsBase64}\n-----END PUBLIC KEY-----`;

        console.log(public);
        console.log(private);
        
        $.ajax({
            url:window.location,type:'POST',data:{
                public:public
            },success:function(data) {
                (async() => {
                    console.log('*ENCRYPTED BY PHP*',data.encrypted);
                    // HELP!!! NEED TO BE ABLE TO RELOAD THE KEY FROM ARMORED STRING
                    var key=await importPrivateKey(private); // Error - Uncaught (in promise) DOMException
                    var buffer=str2ab(window.atob(data.encrypted));
                    // HELP!!! WONT DECRYPT WHAT PHP ENCODED USING THE PUBLIC KEY
                    var decrypted=await window.crypto.subtle.decrypt({name:"RSA-OAEP"},key,buffer);
                    
                    console.log('DECRYPTED',decrypted);
                })();
            }
        });
    })();
});
</script>

解决方法

错误在 str2ab() 函数中,该函数使用 Uint16Array 而不是 Uint8Array

如果修复了,就可以导入私钥,解密用PHP代码生成的密文:

function ab2str(buf) {
    return String.fromCharCode.apply(null,new Uint8Array(buf));
}

function str2ab(str) {
    // Fix: Don't double the size 
    var buf = new ArrayBuffer(str.length);                  
    // Fix: Apply a Uint8Array!
    var bufView = new Uint8Array(buf);                      
    for (var i=0,strLen=str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}

function importPrivateKey(pem) {

    const pemHeader = "-----BEGIN PRIVATE KEY-----\n";
    const pemFooter = "\n-----END PRIVATE KEY-----";
    const pemContents = pem.substring(pemHeader.length,pem.length - pemFooter.length);

    const binaryDerString = window.atob(pemContents);
    const binaryDer = str2ab(binaryDerString);

    return window.crypto.subtle.importKey(
        "pkcs8",binaryDer,{
            name: "RSA-OAEP",modulusLength: 1024,publicExponent: new Uint8Array([1,1]),hash: {name: "SHA-256"}
        },true,["decrypt"]
    );
}

(async function() {

    // Apply the private key from key pair generated with the posted JavaScript code
    var privateKey = 
    `-----BEGIN PRIVATE KEY-----                     
        MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKeQUdBu3zTX6QyfGfRWYxWWOnxd2xssTOIu6XczDByQEMfBbpQO9iM3u/Mn84zZFPFNvOKUNxcnftmrPiqUO9fBI2aAh77d2m65FBGsm4k/oUPzMNORGaDdBY4gg8FPMKo60kqBaMXAwzF8I4EUS/ot2fkBzSL0BGXT9o1NaO8bAgMBAAECgYAO2OPW8ywF86ervaFAHDN1YzVVdb+HXdqGJB/9tuE42q8R9BrHNbgrkLGvrveOoGGRrBCzhuyGubIsuVat0SqoI6qEnB9uahaIBfF5FZ7+bNW5OfkgerUUYP1S1MGFxUqINnUY1YHITmo6pUKHsiJtP7sihnCT6uEx8LqVNf1quQJBANs+VCZVUDq6eMy3E/u03HiAB8cyqLVMVQ4cLyoiWmFlnEFzZwMd20ZMjtcxICiizW3dlDvyxWYKH93irL0JyM0CQQDDp/VFsh83vKICVvM9IZHwE/Z8vZA3eTkGbWmgnr6qaxqge3FU02kUvIHHlvLmXYIt30lTq0Rn+Lz+TGV/jDeHAkBHYSaSiGojhLx5og1+gKbbEIv3vbWRuTVj76cnZ6HXXfaelIzwRdMzMw+6XgMjV8XcRCzTy7ma/Cbd3cPxk/LtAkEAwkehMVexz/KrHI+icG1JMI9iDnNdJPhmO4+hdzCqOyanBfwNiSF0Encslze4ci8f+NTjRwWlo2hGomzRzFk7OQJAPPd/o0azkg9nF+JxLiz7hF+/6MLVZgIfw04u05ANtOSVVQP4UTmJ/tNAe3OBUQVlRQAJ1m3jzUlir0ACPypC1Q==
    -----END PRIVATE KEY-----`;

    // Use the ciphertext generated with the PHP code
    var ciphertext = 'a8gEZ6/DymB8dTGPytQPNS8QiYFuUULK+/c0vtie1l722isC0Z/jSeC2ytA6MjVUuTdq7sPuNW850gEZ2XvKujLQzl9sjJ8pcsxznBzMK8v03YJCTBr2lbfHpEEtuSLaAR2UbovXDoCyIIvOnMjqlIS3Ug2PG4hALThn/aAUwE0=';

    var key = await importPrivateKey(privateKey);
    var decryptedBuffer = str2ab(window.atob(ciphertext));
    var decrypted = await window.crypto.subtle.decrypt(
        {name:"RSA-OAEP"},key,decryptedBuffer
    );
    
    console.log(ab2str(decrypted)); // some text to encrypt
})();

在这里,发布的 JavaScript 代码用于生成 RSA 密钥对。公钥:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnkFHQbt801+kMnxn0VmMVljp8XdsbLEziLul3MwwckBDHwW6UDvYjN7vzJ/OM2RTxTbzilDcXJ37Zqz4qlDvXwSNmgIe+3dpuuRQRrJuJP6FD8zDTkRmg3QWOIIPBTzCqOtJKgWjFwMMxfCOBFEv6Ldn5Ac0i9ARl0/aNTWjvGwIDAQAB
-----END PUBLIC KEY-----

用于使用已发布的PHP代码进行加密,并在上面的代码中应用私钥进行解密。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res