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();
};

В чём может быть проблема?


Ответы (0 шт):