phpseclib无法验证window.subtlecrypto

因此,是的,我的老板想将加密技术放入他的系统中,并且他希望消息在js中签名并在php中进行验证。目前,我正在使用mozilla的subtlecrypto api生成RSA-PSS密钥并签名和phpseclib进行验证。问题是,事实并非如此。

使用js密钥,phpseclib可以签名和验证就可以了,但是无法处理js签名。

这是我的代码。 JS:

    function keys(){
        var cryptoObj = window.crypto || window.msCrypto;
        let msg = '///';
        if(!cryptoObj)
        {
            alert("Crypto API is not supported by the Browser");
            return;
        }

        window.crypto.subtle.generateKey({
            name: "RSA-PSS",modulusLength: 2048,//can be 1024,2048,or 4096
            publicExponent: new Uint8Array([0x01,0x00,0x01]),hash: {name: "SHA-256"},//can be "SHA-1","SHA-256","SHA-384",or "SHA-512"
        },true,//whether the key is extractable (i.e. can be used in exportKey)
        ["sign","verify"] //can be any combination of "sign" and "verify"
    )
        .then(function(key) {
            publicKey = key.publicKey;
            privateKey = key.privateKey;
            // For Demo Purpos Only Exported in JWK format
            if (document.getElementById('public').value == "") {
                window.crypto.subtle.exportKey("spki",key.publicKey).then(
                function (keydata) {
                    publicKeyhold = keydata;
                    let exported = publicKeyhold;
                    const exportedAsString = ab2str(exported);
                    const exportedAsBase64 = window.btoa(exportedAsString);
                    const pemExported = `-----BEGIN PUBLIC KEY-----\n${exportedAsBase64}\n-----END PUBLIC KEY-----`;
                    document.getElementById('public').value = pemExported;
                }
            );
            }

            if (document.getElementById('private').value == "" ) {
                msg = document.getElementById('msg').value;
                window.crypto.subtle.exportKey("pkcs8",key.privateKey).then(
                function (keydata) {
                    privateKeyhold = keydata;
                    const priv = privateKeyhold;
                    const privExportedAsString = ab2str(priv);
                    const privExportedAsBase64 = window.btoa(privExportedAsString);
                    const privPemExported = `-----BEGIN RSA PRIVATE KEY-----\n${privExportedAsBase64}\n-----END RSA PRIVATE KEY-----`;
                    document.getElementById('privJSON').data = key.privateKey;
                    document.getElementById('private').value = privPemExported;
                }
            );
        }})
            window.crypto.subtle.sign({
                    name: "RSA-PSS",saltLength: 128,//the length of the salt
                },//from generateKey or importKey above
                document.getElementById('privJSON').data,getMessageEncoding())
    //ArrayBuffer of data you want to sign
            .then(function(signature) {
                    //returns an ArrayBuffer containing the signature
                    console.dir(ab2str(signature));
                    document.getElementById("cryptmsg").value = window.btoa(ab2str(signature)) ;
                })


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


function asciiToUint8Array(str) {
    var chars = [];
    for (var i = 0; i < str.length; ++i)
        chars.push(str.charCodeAt(i));
    return new Uint8Array(chars);
}

function bytesToHexString(bytes) {
    if (!bytes)
        return null;

    bytes = new Uint8Array(bytes);
    var hexBytes = [];

    for (var i = 0; i < bytes.length; ++i) {
        var byteString = bytes[i].toString(16);
        if (byteString.length < 2)
            byteString = "0" + byteString;
        hexBytes.push(byteString);
    }

    return hexBytes.join("");
}
function getMessageEncoding() {
    const messageBox = document.getElementById('msg');
    let message = messageBox.value;
    let enc = new TextEncoder();
    return enc.encode(message);
}

php:

<?php
include('Crypt/RSA.php');
define('CRYPT_RSA_pkcs15_COMPAT',true);

$pubK = $_POST['public'];
$privK = $_POST['private'];
echo $pubK."<br><br>";
echo $privK."<br><br>";

$sign = ($_POST['cryptmsg']);
$txt = $_POST['msg'];

$rsa = new Crypt_RSA();

$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PSS);
$rsa->setSaltLength(128);
$rsa->setMGFHash("SHA256");
$rsa->setHash("SHA256");

$rsa->loadKey($privK);
$serverSign = $rsa->sign($txt);

$rsa->loadKey($pubK);
echo "text: ".$txt;
echo "<br><br>js sign: <br>".($sign)."<br><br>";
echo "seclib sign: <br>".base64_encode($serverSign);
echo "<br><br>";

$jsTest = $rsa->verify($txt,base64_decode($sign)) ? 'verified' : 'unverified';
$selfTest = $rsa->verify($txt,$serverSign) ? 'verified' : 'unverified';

echo 'js signature: '. $jsTest;
echo'<br> phpseclib signature (same keys): '. $selfTest;
a212346 回答:phpseclib无法验证window.subtlecrypto

在PHP代码中,摘要必须用myRows指定,即用小写字母代替大写字母:

sha256

$rsa->setMGFHash("sha256"); $rsa->setHash("sha256"); 不知道大写名称,因此使用默认摘要phpseclib [1]。通过输出与sha1一起使用的摘要的名称,可以轻松地对此进行测试。

该错误不是很容易找到,如果$rsa->hashName显示错误消息或警告比静默使用默认错误会更好。

作为旁注:在JavaScript代码中,私钥以PKCS8格式导出,但是使用PKCS1格式的页眉和页脚[2]。但是,phpseclib可以容忍这种不一致。

本文链接:https://www.f2er.com/2923598.html

大家都在问