簡體   English   中英

RSA 加密,在 PHP (phpseclib) 中加密並在 JavaScript (crypto.subtle) 中解密

[英]RSA Encryption, Encrypt in PHP (phpseclib) and Decrypt in 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, 0, 1]),
                hash: {name: "SHA-256"}
            },
            true,
            ["decrypt"]
          );
    }
    (async() => {
        let keyPair = await window.crypto.subtle.generateKey(
          {
                name: "RSA-OAEP",
                modulusLength: 1024,
                publicExponent: new Uint8Array([1, 0, 1]),
                hash: {name: "SHA-256"}
          },
          true,
          ["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() function 中,它使用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, 0, 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 代碼執行加密,並且在上面的代碼中應用私鑰進行解密。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM