如何在 ReactJS 中验证 RSA 签名?

How to verify RSA signatures in ReactJS?

我有一个 ReactJS 应用程序,它应该能够使用给定的 RSA public 密钥验证签名,就像 Web Crypto API 它使用 subtle 和 import_key 等。 有谁知道是否存在这样的库或如何使用 Web Crypto API 直接做出反应?我搜索了很多,但找不到适合我的工作示例。也许我错过了什么。

我在@trust/webcrypto库之前试过,用npm安装的。

这是我之前试过的代码:

const crypto = require('@trust/webcrypto');

function base64decode(str) {
    let buffer = Buffer.from(str, 'base64');
    return new Uint8Array(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength));
}

function importRsaPublicKey(pem) {
    const binaryDer = base64decode(pem);
    return crypto.subtle.importKey(
        "pkcs8",
        binaryDer,
        {
            name: "RSA-PSS",
            hash: "SHA-256",
        },
        true,
        ["verify"]
    );
}

RSA public 密钥作为以 ASN.1 DER 格式编码的 base64 字符串给出。 例如:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAimHHeNG9QnA7aMSjefJzMKfP...4XqwIDAQAB

我的第一个问题是正确导入它。 当我有一个工作库时,签名可能已经解决了。

当我尝试上面的代码时,我的 ReactJS 应用程序出现以下错误:Unhandled Rejection (Error): Cannot find module '../algorithms/RSA-PSS'

我搜索了这个问题,似乎我无法在 React 中使用它,这就是为什么我问是否有人知道一个库正在 React 中导入 RSA public 密钥并且是能够验证具有给定签名的签名消息。

我尝试的第二个库是 @peculiar/webcrypto,但它似乎也不起作用。

我试过的代码:

const { Crypto } = require("@peculiar/webcrypto");
const crypto = new Crypto();

function importRsaPublicKey(pem) {
    const binaryDer = base64decode(pem);
    return crypto.subtle.importKey(
        "pkcs8",
        binaryDer,
        {
            name: "RSA-PSS",
            hash: "SHA-256",
        },
        true,
        ["verify"]
    );
}

这会引发以下错误:Unhandled Rejection (Error): Data does not match to PrivateKeyInfo ASN1 schema.

public 密钥肯定是 ASN.1 DER 编码,但它是 public 密钥而不是私钥。我的设置中不需要私钥。

@Topaco 提到要使用 public 密钥,我必须使用 spki 格式。这解决了导入 public 键的问题。 这段代码解决了我的问题。

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 importRsaPublicKey(pem) {

    const binaryDerString = atob(pem);
    const binaryDer = str2ab(binaryDerString);

    return crypto.subtle.importKey(
        "spki",
        binaryDer,
        {
            name: "RSASSA-PKCS1-v1_5",
            hash: "SHA-256",
        },
        true,
        ["verify"]
    );
}

我使用了 RSASSA-PKCS1-v1_5 算法,因为它不需要盐。