Javascript: Ошибка при подписи xml файла: Failed to execute 'exportKey' on 'SubtleCrypto': parameter 2 is not of type 'CryptoKey'. Как исправить?
Пытаюсь подписать XML файл с помощью файла сертификата в формате p12. Для подписи использую библиотеку XmlDSigJs и webcrypto-liner.
Но, при подписи появляется ошибка:
Failed to execute 'sign' on 'SubtleCrypto': parameter 2 is not of type 'CryptoKey'.
Вот код модуля, который занимается подписью:
import * as forge from "node-forge";
import * as XmlDSigJs from "../xml-crypto";
import "webcrypto-liner";
import { stringToArrayBuffer } from "./string-to-array-buffer";
import type { RSA } from "../types/rsa";
type SignXMLWithRSAArgs = {
xml: string;
rsa: RSA;
};
type Keys = {
publicKey?: forge.asn1.Asn1;
privateKey?: forge.pki.PrivateKey;
};
const importKey = (keyInfoDerBuff: ArrayBuffer, type: "private" | "public") => {
return window.crypto.subtle.importKey(
type === "private" ? "pkcs8" : "spki",
keyInfoDerBuff,
{ name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" } },
true,
["sign", "verify"]
);
};
const getPrivateKeyBuffer = (privateKey: forge.pki.PrivateKey): ArrayBuffer => {
const rsaPrivateKey = forge.pki.privateKeyToAsn1(privateKey);
const privateKeyInfo = forge.pki.wrapRsaPrivateKey(rsaPrivateKey);
const privateKeyInfoDer = forge.asn1.toDer(privateKeyInfo).getBytes();
return stringToArrayBuffer(privateKeyInfoDer);
};
const getPublicKeyBuffer = (publicKey: forge.asn1.Asn1): ArrayBuffer => {
const publicKeyDer = forge.asn1.toDer(publicKey).getBytes();
return stringToArrayBuffer(publicKeyDer);
};
const getKeys = (pkcs12Der: string, password: string): Keys => {
const keys: Keys = {};
const pkcs12Asn1 = forge.asn1.fromDer(pkcs12Der);
const pkcs12 = forge.pkcs12.pkcs12FromAsn1(pkcs12Asn1, false, password);
for (const safeContent of pkcs12.safeContents) {
for (const safeBag of safeContent.safeBags) {
const isPrivateKey =
safeBag.type === forge.pki.oids.keyBag || safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag;
const isPublicKey = safeBag.type === forge.pki.oids.certBag && safeBag.attributes.localKeyId;
if (isPrivateKey && safeBag.key) {
keys.privateKey = safeBag.key;
}
if (isPublicKey && safeBag.cert) {
keys.publicKey = forge.pki.publicKeyToAsn1(safeBag.cert.publicKey);
}
}
}
return keys;
};
const getCertP12 = (key: string, password: string): string | undefined => {
const pkcs12Der = forge.util.decode64(key);
const asn1 = forge.asn1;
const pkcs12Asn1 = asn1.fromDer(pkcs12Der);
const pkcs12 = forge.pkcs12.pkcs12FromAsn1(pkcs12Asn1, true, password);
for (const safeContent of pkcs12.safeContents) {
for (const safeBag of safeContent.safeBags) {
if (safeBag.type === forge.pki.oids.certBag) {
if (typeof safeBag.asn1 !== "undefined") {
return forge.util.encode64(forge.asn1.toDer(safeBag.asn1).getBytes(), 2048);
}
if (safeBag.cert) {
return forge.util.encode64(forge.asn1.toDer(forge.pki.certificateToAsn1(safeBag.cert)).getBytes(), 2048);
}
}
}
}
};
export const signXMLWithRSA = async ({ xml, rsa }: SignXMLWithRSAArgs) => {
const signedXML = new XmlDSigJs.SignedXml();
const keys = getKeys(rsa.pkcs12Der, rsa.password);
const certP12 = getCertP12(rsa.key, rsa.password);
if (!keys.privateKey || !certP12 || !keys.publicKey) {
return;
}
const algorithm = {
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
};
const privateKeyInfoDerBuff = getPrivateKeyBuffer(keys.privateKey);
const publicKeyInfoDerBuff = getPublicKeyBuffer(keys.publicKey);
const publicCryptoKey = await importKey(publicKeyInfoDerBuff, "public");
const privateCryptoKey = await importKey(privateKeyInfoDerBuff, "private");
const signature = await signedXML.Sign(algorithm, privateCryptoKey, XmlDSigJs.Parse(xml), {
x509: [certP12],
references: [{ uri: "", hash: "SHA-256", transforms: ["enveloped", "exc-c14n-com"] }],
});
return signature.toString();
};
В чём может быть проблема?