PKIJS 签名和验证不匹配

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

考虑以下代码

    const data = await Deno.readFile("./README.md");
    const certificate = (await loadPEM("./playground/domain.pem"))[0] as Certificate;
    const privateKey = (await loadPEM("./playground/domain-pkcs8-nocrypt.key", "PRIVATE KEY"))[0] as CryptoKey;

    const signedData = await signData(data.buffer, certificate, privateKey);

    // verify same
    const ok = await signedData.verify({
        signer: 0,
        checkChain: true,
        trustedCerts: [certificate],
        data: data.buffer
    })

    console.log(ok); // false :(

    // verify external signed like this
    // openssl cms -sign -signer domain.pem -inkey domain-pkcs8-nocrypt.key -binary -in README.md -outform der -out signature

    const cms = ContentInfo.fromBER(await Deno.readFile("./playground/signature")) as ContentInfo;
    if (cms.contentType !== ContentInfo.SIGNED_DATA)
        throw new Error("CMS is not Signed Data");

    const signedData1 = new SignedData({ schema: cms.content });

    const ok1 = await signedData1.verify({
        signer: 0,
        checkChain: true,
        trustedCerts: [certificate],
        data: data.buffer
    })

    console.log(ok1); // true

在第一部分中,我对数据进行签名,然后根据加载的证书对其进行验证,但失败了

在第二部分中,我使用

openssl
加载生成的签名,其证书和私钥与第一部分中使用的证书和私钥相同,并且对加载的证书的验证正常。 所以,由于两个例子中的验证方法是相同的,我猜我的签名方法有问题。 这是创建签名的代码

export async function signData(data:ArrayBuffer, certificate: Certificate, privateKey: CryptoKey):Promise<SignedData>{
    const cmsSigned = new SignedData({
        encapContentInfo: new EncapsulatedContentInfo({
            eContentType: ContentInfo.DATA,
            //eContent: new ans1js.OctetString({ valueHex: data })
        }),
        signerInfos: [
            new SignerInfo({
                sid: new IssuerAndSerialNumber({
                    issuer: certificate.issuer,
                    serialNumber: certificate.serialNumber
                })
            })
        ],
        certificates: [certificate]
    });

    await cmsSigned.sign(privateKey, 0, "SHA-256", data);
    return cmsSigned;
}

这是我加载证书和密钥的方法:

export async function loadPEM(src:string,
    type: PEMType = "CERTIFICATE" ):Promise<PkiObject[] | CryptoKey[]> {
    const buffer = pvtsutils.BufferSourceConverter.toArrayBuffer(await Deno.readFile(src));
    const binary = pvtsutils.Convert.ToBinary(buffer);
    const bers = decodePEM(binary, type);
    const ret = [];
    switch (type) {
      case "CERTIFICATE":
        return bers.map(ber => Certificate.fromBER(ber) as Certificate);
      case "PRIVATE KEY":
        for( const ber of bers) 
            ret.push(await crypto.importKey("pkcs8", ber, {
                name: "RSA-PSS",
                hash: "SHA-256",
                },
                true,
                ["sign"]));
        return ret;
      case "PUBLIC KEY":
        return bers.map(ber => PublicKeyInfo.fromBER(ber) as PublicKeyInfo);
    }
    
}
javascript typescript cryptojs pki
1个回答
0
投票

好的,问题是导入密钥时使用的算法。 通过使用 RSASSA-PKCS1-v1_5 现在可以工作了:

crypto.importKey("pkcs8", ber, {
        name: "RSASSA-PKCS1-v1_5",
        hash: "SHA-256"
    },
    true,
    ["sign"])
© www.soinside.com 2019 - 2024. All rights reserved.