尝试使用 crypto.subtle.decrypt 解密密文(使用 openssl 生成)时出现语法错误

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

我正在尝试使用 crypto.subtle.decrypt 解密密文(使用 openssl 生成)并不断收到以下错误:

SyntaxError: An invalid or illegal string was specified

同样的密文在在线RSAtools和openssl中很容易被解密。我已经尝试了 stackoverflow 中出现的一些示例,例如 hereherehere,但即使是那些密文也失败了。我怀疑我在加密时可能错过了一些选项,但不确定是哪一个。

我使用以下方法生成密钥:

$ openssl genpkey -out private_key.pem -algorithm RSA -pkeyopt rsa_keygen_bits:1024
$ openssl rsa -pubout -in private_key.pem -out public_key.pem
$ cat public_key.pem
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7P6BUs5/P9NbyztqsXvhYHFdX
sQQ5rw6R80MpH6KIgwZohpTLIuZIUjoG/9G+Artv1FHL1uvOPfqlUsj2HtVbM8Cz
E52tB/z/kIyLA6GjKYt+Ok2ZUgWMuHXFBICANaLd93Vm1RNZTcj4k5B/3UT+zZ8j
i30YJjPoLJrtx8VDTQIDAQAB
-----END PUBLIC KEY-----

我正在使用下面的命令来加密明文

$ echo "Rohit Das" | openssl pkeyutl -encrypt -pubin -inkey public_key.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -out pass_1.enc
$ cat pass_1.enc | base64
Bubb/cepSt/BZAoPjjsRtmy0Y/50cwcP6J0GvKavFEfLYzAkMi/JbueGILIWnllnENZM0w133JoV
pPPT9B21hD2p8z2CzuOmYV4BnVV97i0oS0xawJPWdUwc6Vp+JaN9TrEX98FwCtQZHKtViyA8+Bnm
u2LBKl5N/QipKIX+Dnc=

我在以下 JS 函数中使用 crypto.subtle:

function str2ab(str) {
    const bufView = new Uint8Array(str.length);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
      bufView[i] = str.charCodeAt(i);
    }
    return bufView.buffer;
}

function decrypto() {
    let pvtPem = `-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALs/oFSzn8/01vLO
2qxe+FgcV1exBDmvDpHzQykfooiDBmiGlMsi5khSOgb/0b4Cu2/UUcvW6849+qVS
yPYe1VszwLMTna0H/P+QjIsDoaMpi346TZlSBYy4dcUEgIA1ot33dWbVE1lNyPiT
kH/dRP7NnyOLfRgmM+gsmu3HxUNNAgMBAAECgYEApO8ri9BYwbWZrHCWX2Sb/gig
ysZKwYC4JckP7GZIJVS8TU/WOoQ4MZX0NPwbRPJlJeDwV8utE5K2d+9OwrRwGw7n
ZirNolvYSnBeZ8pKRwseQA2fzfCMubZcttjpyb1DfyMXwQj6oCGxuFXPLUWT8/1/
9PkPAWa8uOZhinD/fwUCQQDcxcdCn9rAFLOn1g3EJzSD56GGu6RIrkx8kdBofTYr
nwYnriiX8a//hlRg4BiOv1FdoTHFJi3QAOobX8tiUBK7AkEA2SBxS2TDOj3HJByI
32D0HY1a/O3VBEF4mkRi60HtDYRxL7fmCxebgzFytGxIQr4h+VxFqlABDoDd5vd3
cSS1lwJARm3FumhalYpFIda0f43uP+Il8mBr8U/BUMAHlz3SiSnrAb+abZaJid+l
jV4QF4HLCC6DPRyH4uJXzLHLpSpcPwJARYVVwUYqHGPbd3yLdrqcbznrgEDGi+5K
p1puMdWSCVn2w8imJ7cPXBphF9Pz7yrhxe39gGLNc89fPazO2bNfUQJBALBdr/G3
KYecLkwJeR0okQ8biSr1mAC+VhqlF9JW4pDiw4jrud6R+M4+WjU5nGjxPCfhbEHA
PCahv9z7njXL2qA=
-----END PRIVATE KEY-----`;
    const pemHeader = "-----BEGIN PRIVATE KEY-----";
    const pemFooter = "-----END PRIVATE KEY-----";
    let pvtDer = pvtPem.substring(pemHeader.length, pvtPem.length - pemFooter.length);
    let binaryDer = str2ab(window.atob(pvtDer));
    console.log("binaryDer " + binaryDer);
    window.crypto.subtle.importKey(
        "pkcs8",
        binaryDer,
        {
            name: "RSA-OAEP",
            hash: "SHA-256"
        },
        true,
        ["decrypt"]
    ).then((pvtKey) => {
        console.log("pvtKey " + pvtKey);

        let encryptedData = "Bubb/cepSt/BZAoPjjsRtmy0Y/50cwcP6J0GvKavFEfLYzAkMi/JbueGILIWnllnENZM0w133JoVpPPT9B21hD2p8z2CzuOmYV4BnVV97i0oS0xawJPWdUwc6Vp+JaN9TrEX98FwCtQZHKtViyA8+Bnmu2LBKl5N/QipKIX+Dnc=";
        window.crypto.subtle.decrypt(
            { name: "RSA-OAEP "},
            pvtKey,
            str2ab(window.atob(encryptedData))
        ).then((decryptedData) => {
            console.log("decrypted " + decryptedData + " Rohit Das");
        }).catch((err) => {console.log("decrypt error " + err);});
    }).catch((err) => {console.log("key import error " + err);});
}
javascript cryptography rsa webcrypto-api
1个回答
0
投票

解密成功如果:

  • importKey()
    调用中使用
    "SHA-1"
    (而不是
    "SHA-256"
    )。这也意味着发布的密文实际上并不是使用发布的 OpenSSL 语句(对两个摘要应用 SHA-256)生成的。
  • decrypt()
    调用中,空格从算法名称规范中删除(
    "RSA-OAEP"
    而不是
    "RSA-OAEP "

如果两者都已修复,则解密有效:

function str2ab(str) {
    const bufView = new Uint8Array(str.length);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
      bufView[i] = str.charCodeAt(i);
    }
    return bufView.buffer;
}

function decrypto() {
    let pvtPem = `-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALs/oFSzn8/01vLO
2qxe+FgcV1exBDmvDpHzQykfooiDBmiGlMsi5khSOgb/0b4Cu2/UUcvW6849+qVS
yPYe1VszwLMTna0H/P+QjIsDoaMpi346TZlSBYy4dcUEgIA1ot33dWbVE1lNyPiT
kH/dRP7NnyOLfRgmM+gsmu3HxUNNAgMBAAECgYEApO8ri9BYwbWZrHCWX2Sb/gig
ysZKwYC4JckP7GZIJVS8TU/WOoQ4MZX0NPwbRPJlJeDwV8utE5K2d+9OwrRwGw7n
ZirNolvYSnBeZ8pKRwseQA2fzfCMubZcttjpyb1DfyMXwQj6oCGxuFXPLUWT8/1/
9PkPAWa8uOZhinD/fwUCQQDcxcdCn9rAFLOn1g3EJzSD56GGu6RIrkx8kdBofTYr
nwYnriiX8a//hlRg4BiOv1FdoTHFJi3QAOobX8tiUBK7AkEA2SBxS2TDOj3HJByI
32D0HY1a/O3VBEF4mkRi60HtDYRxL7fmCxebgzFytGxIQr4h+VxFqlABDoDd5vd3
cSS1lwJARm3FumhalYpFIda0f43uP+Il8mBr8U/BUMAHlz3SiSnrAb+abZaJid+l
jV4QF4HLCC6DPRyH4uJXzLHLpSpcPwJARYVVwUYqHGPbd3yLdrqcbznrgEDGi+5K
p1puMdWSCVn2w8imJ7cPXBphF9Pz7yrhxe39gGLNc89fPazO2bNfUQJBALBdr/G3
KYecLkwJeR0okQ8biSr1mAC+VhqlF9JW4pDiw4jrud6R+M4+WjU5nGjxPCfhbEHA
PCahv9z7njXL2qA=
-----END PRIVATE KEY-----`;
    const pemHeader = "-----BEGIN PRIVATE KEY-----";
    const pemFooter = "-----END PRIVATE KEY-----";
    let pvtDer = pvtPem.substring(pemHeader.length, pvtPem.length - pemFooter.length);
    let binaryDer = str2ab(window.atob(pvtDer));
    console.log("binaryDer " + binaryDer);
    window.crypto.subtle.importKey(
        "pkcs8",
        binaryDer,
        {
            name: "RSA-OAEP",
            hash: "SHA-1"
        },
        true,
        ["decrypt"]
    ).then((pvtKey) => {
        console.log("pvtKey " + pvtKey);

        let encryptedData = "Bubb/cepSt/BZAoPjjsRtmy0Y/50cwcP6J0GvKavFEfLYzAkMi/JbueGILIWnllnENZM0w133JoVpPPT9B21hD2p8z2CzuOmYV4BnVV97i0oS0xawJPWdUwc6Vp+JaN9TrEX98FwCtQZHKtViyA8+Bnmu2LBKl5N/QipKIX+Dnc=";
        window.crypto.subtle.decrypt(
            { name: "RSA-OAEP"},
            pvtKey,
            str2ab(window.atob(encryptedData))
        ).then((decryptedData) => {
            console.log("decrypted " + new TextDecoder().decode(decryptedData));// + " Rohit Das");
        }).catch((err) => {console.log("decrypt error " + err);});
    }).catch((err) => {console.log("key import error " + err);});
}

decrypto();

这一点通过在线工具解密得到确认。我使用了https://8gwifi.org/rsafunctions.jsp和选项

RSA/NONE/OAEPWithSHA1AndMGF1Padding
RSA/ECB/OAEPWithSHA-1AndMGF1Padding
(为此通过https将密钥格式从PKCS#8转换为PKCS#1:/ /8gwifi.org/pemconvert.jsp 是必要的)。
您使用的网站在我的测试中运行不可靠。


使用发布的 OpenSSL 语句生成的密文(即两个摘要均使用 SHA-256)例如:

Tu8MHqnXCrRHZjKgMJx7CF4b2r6jz1ame7+qCFJ6ZkfgzgJc1qDX5xkyN28vZMzhEiO42iFGEeUoYDA4SH+RFPoGPbM94/IFvZREgpEow0a4scMvaYfKCK76gbb5P3UbEIwcgN+QBtsHCEC/aPJmtPzEl1jUNO94fjUkjrGaKwM=

如果在 WebCrypto 代码中应用 SHA-256,则按预期正确解密:

function str2ab(str) {
    const bufView = new Uint8Array(str.length);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
      bufView[i] = str.charCodeAt(i);
    }
    return bufView.buffer;
}

function decrypto() {
    let pvtPem = `-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALs/oFSzn8/01vLO
2qxe+FgcV1exBDmvDpHzQykfooiDBmiGlMsi5khSOgb/0b4Cu2/UUcvW6849+qVS
yPYe1VszwLMTna0H/P+QjIsDoaMpi346TZlSBYy4dcUEgIA1ot33dWbVE1lNyPiT
kH/dRP7NnyOLfRgmM+gsmu3HxUNNAgMBAAECgYEApO8ri9BYwbWZrHCWX2Sb/gig
ysZKwYC4JckP7GZIJVS8TU/WOoQ4MZX0NPwbRPJlJeDwV8utE5K2d+9OwrRwGw7n
ZirNolvYSnBeZ8pKRwseQA2fzfCMubZcttjpyb1DfyMXwQj6oCGxuFXPLUWT8/1/
9PkPAWa8uOZhinD/fwUCQQDcxcdCn9rAFLOn1g3EJzSD56GGu6RIrkx8kdBofTYr
nwYnriiX8a//hlRg4BiOv1FdoTHFJi3QAOobX8tiUBK7AkEA2SBxS2TDOj3HJByI
32D0HY1a/O3VBEF4mkRi60HtDYRxL7fmCxebgzFytGxIQr4h+VxFqlABDoDd5vd3
cSS1lwJARm3FumhalYpFIda0f43uP+Il8mBr8U/BUMAHlz3SiSnrAb+abZaJid+l
jV4QF4HLCC6DPRyH4uJXzLHLpSpcPwJARYVVwUYqHGPbd3yLdrqcbznrgEDGi+5K
p1puMdWSCVn2w8imJ7cPXBphF9Pz7yrhxe39gGLNc89fPazO2bNfUQJBALBdr/G3
KYecLkwJeR0okQ8biSr1mAC+VhqlF9JW4pDiw4jrud6R+M4+WjU5nGjxPCfhbEHA
PCahv9z7njXL2qA=
-----END PRIVATE KEY-----`;
    const pemHeader = "-----BEGIN PRIVATE KEY-----";
    const pemFooter = "-----END PRIVATE KEY-----";
    let pvtDer = pvtPem.substring(pemHeader.length, pvtPem.length - pemFooter.length);
    let binaryDer = str2ab(window.atob(pvtDer));
    console.log("binaryDer " + binaryDer);
    window.crypto.subtle.importKey(
        "pkcs8",
        binaryDer,
        {
            name: "RSA-OAEP",
            hash: "SHA-256"
        },
        true,
        ["decrypt"]
    ).then((pvtKey) => {
        console.log("pvtKey " + pvtKey);

        let encryptedData = "Tu8MHqnXCrRHZjKgMJx7CF4b2r6jz1ame7+qCFJ6ZkfgzgJc1qDX5xkyN28vZMzhEiO42iFGEeUoYDA4SH+RFPoGPbM94/IFvZREgpEow0a4scMvaYfKCK76gbb5P3UbEIwcgN+QBtsHCEC/aPJmtPzEl1jUNO94fjUkjrGaKwM=";
        window.crypto.subtle.decrypt(
            { name: "RSA-OAEP"},
            pvtKey,
            str2ab(window.atob(encryptedData))
        ).then((decryptedData) => {
            console.log("decrypted " + new TextDecoder().decode(decryptedData));// + " Rohit Das");
        }).catch((err) => {console.log("decrypt error " + err);});
    }).catch((err) => {console.log("key import error " + err);});
}

decrypto();

© www.soinside.com 2019 - 2024. All rights reserved.