在PHP中模拟WebCrypto RSA-OAEP加密。

问题描述 投票:-1回答:1

我们有一个服务器,它使用RSA-OAEP从客户端接收数据。

我没有访问服务器的权限,检查结果的唯一方法是发送一个请求并检查其回复。

我已经能够用WebCrypto发送正确的请求,但是用php没有成功。

我使用的代码是JS.NET的,而这是我的php函数。

var DataToEncrypt = 'abcd';
var pemEncodedKey = `-----BEGIN PUBLIC KEY-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END PUBLIC KEY-----`;
let encryptionKey;
function str2ab(str) {
    const buf = new ArrayBuffer(str.length);
    const bufView = new Uint8Array(buf);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}

function importPublicKey(pem) {
    const pemHeader = "-----BEGIN PUBLIC KEY-----";
    const pemFooter = "-----END PUBLIC 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(
        "spki",
        binaryDer,
        {
            name: "RSA-OAEP",
            hash: "SHA-256"
        },
        true,
        ["encrypt"]
    );
}

function getMessageEncoding() {
    const enc = new TextEncoder();
    return enc.encode(DataToEncrypt);
}
async function encryptMessage() {
    const encoded = getMessageEncoding();
    const ciphertext = await window.crypto.subtle.encrypt(
        {
            name: "RSA-OAEP"
        },
        encryptionKey,
        encoded
    );

    var decoder = new TextDecoder('utf8');
    var b64encoded = btoa(String.fromCharCode.apply(null, new Uint8Array(ciphertext)));
    document.getElementById('crypt').value = b64encoded;
}

document.getElementById('import').addEventListener("click", async () => {
    encryptionKey = await importPublicKey(pemEncodedKey);
});

document.getElementById('encrypt').addEventListener("click", function(){
    encryptMessage();
});

这是我的php函数(使用phpseclib)。

function encrypt($data) {
    $key = '-----BEGIN PUBLIC KEY-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END PUBLIC KEY-----';

    $rsa = new Crypt_RSA();
    $rsa->setHash('sha256');
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP);
    $rsa->loadKey($key); // public key
    $crypted = $rsa->encrypt($data);

    return base64_encode($crypted);
}
echo encrypt('abcd');

我尝试了这两种方法,结果都是发送请求到服务器,就像我前面提到的,只有js代码可以工作,而php的输出没有达到预期的效果。

javascript php rsa phpseclib webcrypto-api
1个回答
2
投票

我试着用js加密一些东西,然后用php(phpseclib)用一对我制作的公钥和私钥解密,结果成功了。

之后我试着把我的公钥重新格式化为每行64个字符(和js中的一样是一行),并使用setHash('sha256')和setMGFHash('sha256'),现在我的php函数工作了。

新的php函数 :

function encrypt($data)
{
    $key = '-----BEGIN PUBLIC KEY-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXX
-----END PUBLIC KEY-----';

    $rsa = new Crypt_RSA();
    $rsa->setHash('sha256');
    $rsa->setMGFHash('sha256');
    $lk = $rsa->loadKey($key); // public key
    $crypted = $rsa->encrypt($data);
    return base64_encode($crypted);
}
© www.soinside.com 2019 - 2024. All rights reserved.