pptx-viewer-core 1.2.5 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  import { DOMParser, XMLSerializer } from '@xmldom/xmldom';
2
2
  import { SignedXml } from 'xml-crypto';
3
- import crypto from 'crypto';
3
+ import crypto2 from 'crypto';
4
4
  import path from 'path';
5
5
  import tls from 'tls';
6
- import forge from 'node-forge';
6
+ import forge3 from 'node-forge';
7
7
  import http from 'http';
8
8
  import https from 'https';
9
9
  import fs from 'fs/promises';
@@ -206,6 +206,89 @@ function canonicalizeSignedInfoXml(signedInfoXml) {
206
206
  }
207
207
  return canonicalizeNode(signedInfoDoc.documentElement, "http://www.w3.org/2001/10/xml-exc-c14n#");
208
208
  }
209
+
210
+ // src/signature-node/pem-utils.ts
211
+ function firstPemBlockForLabel(text, label) {
212
+ const begin = `-----BEGIN ${label}-----`;
213
+ const end = `-----END ${label}-----`;
214
+ const beginIndex = text.indexOf(begin);
215
+ if (beginIndex === -1) {
216
+ return void 0;
217
+ }
218
+ const endIndex = text.indexOf(end, beginIndex + begin.length);
219
+ if (endIndex === -1) {
220
+ return void 0;
221
+ }
222
+ return { index: beginIndex, block: text.slice(beginIndex, endIndex + end.length) };
223
+ }
224
+ function extractPemBlocks(text, label) {
225
+ const begin = `-----BEGIN ${label}-----`;
226
+ const end = `-----END ${label}-----`;
227
+ const blocks = [];
228
+ let searchFrom = 0;
229
+ for (; ; ) {
230
+ const beginIndex = text.indexOf(begin, searchFrom);
231
+ if (beginIndex === -1) {
232
+ break;
233
+ }
234
+ const contentStart = beginIndex + begin.length;
235
+ const endIndex = text.indexOf(end, contentStart);
236
+ if (endIndex === -1) {
237
+ break;
238
+ }
239
+ blocks.push(text.slice(beginIndex, endIndex + end.length));
240
+ searchFrom = endIndex + end.length;
241
+ }
242
+ return blocks;
243
+ }
244
+ function extractFirstPemBlock(text, labels) {
245
+ let best;
246
+ for (const label of labels) {
247
+ const found = firstPemBlockForLabel(text, label);
248
+ if (found && (!best || found.index < best.index)) {
249
+ best = found;
250
+ }
251
+ }
252
+ return best?.block;
253
+ }
254
+
255
+ // src/signature-node/timestamp-tag-scanner.ts
256
+ var MAX_TAG_WINDOW = 256;
257
+ var OPEN_TAG_PATTERN = /^<(?:[\w.-]+:)?(?:EncapsulatedTimeStamp|SignatureTimeStamp)\b[^>]*>/i;
258
+ var CLOSE_TAG_PATTERN = /^<\/(?:[\w.-]+:)?(?:EncapsulatedTimeStamp|SignatureTimeStamp)>/i;
259
+ function findCloseTagIndex(xml, fromIndex) {
260
+ let searchFrom = fromIndex;
261
+ for (; ; ) {
262
+ const ltIndex = xml.indexOf("<", searchFrom);
263
+ if (ltIndex === -1) {
264
+ return void 0;
265
+ }
266
+ const window = xml.slice(ltIndex, ltIndex + MAX_TAG_WINDOW);
267
+ if (CLOSE_TAG_PATTERN.test(window)) {
268
+ return ltIndex;
269
+ }
270
+ searchFrom = ltIndex + 1;
271
+ }
272
+ }
273
+ function findTimestampTagContent(xml) {
274
+ let searchFrom = 0;
275
+ for (; ; ) {
276
+ const ltIndex = xml.indexOf("<", searchFrom);
277
+ if (ltIndex === -1) {
278
+ return void 0;
279
+ }
280
+ const window = xml.slice(ltIndex, ltIndex + MAX_TAG_WINDOW);
281
+ const openMatch = OPEN_TAG_PATTERN.exec(window);
282
+ if (openMatch) {
283
+ const contentStart = ltIndex + openMatch[0].length;
284
+ const closeIndex = findCloseTagIndex(xml, contentStart);
285
+ return closeIndex === void 0 ? void 0 : xml.slice(contentStart, closeIndex);
286
+ }
287
+ searchFrom = ltIndex + 1;
288
+ }
289
+ }
290
+
291
+ // src/signature-node/pki-validation.ts
209
292
  function certPemFromBase64(certBase64) {
210
293
  try {
211
294
  const der = Buffer.from(certBase64, "base64");
@@ -226,7 +309,7 @@ ${lines.join("\n")}
226
309
  }
227
310
  function certFingerprintSha256(certPem) {
228
311
  try {
229
- const cert = new crypto.X509Certificate(certPem);
312
+ const cert = new crypto2.X509Certificate(certPem);
230
313
  return cert.fingerprint256.replace(/:/g, "").toLowerCase();
231
314
  } catch {
232
315
  return void 0;
@@ -235,12 +318,173 @@ function certFingerprintSha256(certPem) {
235
318
  function asn1Child(node, index) {
236
319
  return Array.isArray(node.value) ? node.value[index] : void 0;
237
320
  }
321
+ async function evaluateTimestampAuthority(signatureXml) {
322
+ try {
323
+ const content = findTimestampTagContent(signatureXml);
324
+ if (!content?.trim()) {
325
+ return { status: "not-present" };
326
+ }
327
+ const tokenBase64 = content.replace(/\s+/g, "");
328
+ const tokenDer = Buffer.from(tokenBase64, "base64");
329
+ if (tokenDer.length === 0) {
330
+ return { status: "invalid", error: "Empty timestamp token." };
331
+ }
332
+ const asn1 = forge3.asn1.fromDer(forge3.util.createBuffer(tokenDer.toString("binary")));
333
+ const contentType = asn1Child(asn1, 0);
334
+ if (!contentType) {
335
+ return {
336
+ status: "invalid",
337
+ error: "Malformed timestamp token structure."
338
+ };
339
+ }
340
+ return { status: "valid" };
341
+ } catch (err) {
342
+ return {
343
+ status: "error",
344
+ error: `Timestamp evaluation failed: ${String(err)}`
345
+ };
346
+ }
347
+ }
348
+
349
+ // src/signature-node/certificate-utils.ts
350
+ var PRIVATE_KEY_PEM_LABELS = [
351
+ "RSA PRIVATE KEY",
352
+ "EC PRIVATE KEY",
353
+ "ENCRYPTED PRIVATE KEY",
354
+ "PRIVATE KEY"
355
+ ];
356
+ function certificateInfoFromBase64(certBase64) {
357
+ try {
358
+ const certificate = new crypto2.X509Certificate(Buffer.from(certBase64, "base64"));
359
+ return {
360
+ subject: certificate.subject || void 0,
361
+ issuer: certificate.issuer || void 0,
362
+ serialNumber: certificate.serialNumber || void 0,
363
+ validFrom: certificate.validFrom || void 0,
364
+ validTo: certificate.validTo || void 0
365
+ };
366
+ } catch {
367
+ return void 0;
368
+ }
369
+ }
370
+ function validateCertificateChain(certBase64List, additionalRootsPem) {
371
+ if (certBase64List.length === 0) {
372
+ return { status: "not-checked" };
373
+ }
374
+ try {
375
+ const chain = certBase64List.map((value) => {
376
+ const der = forge3.util.decode64(value);
377
+ return forge3.pki.certificateFromAsn1(forge3.asn1.fromDer(der));
378
+ });
379
+ const rootPem = [...tls.rootCertificates, ...additionalRootsPem];
380
+ const caStore = forge3.pki.createCaStore(rootPem);
381
+ const verified = forge3.pki.verifyCertificateChain(caStore, chain);
382
+ return verified ? { status: "trusted" } : {
383
+ status: "untrusted",
384
+ error: "Certificate chain is not trusted."
385
+ };
386
+ } catch (error) {
387
+ return {
388
+ status: "untrusted",
389
+ error: `Certificate trust validation failed: ${String(error)}`
390
+ };
391
+ }
392
+ }
393
+ function signatureAlgorithmToVerifyAlgorithm(signatureMethod) {
394
+ switch (signatureMethod) {
395
+ case "http://www.w3.org/2000/09/xmldsig#rsa-sha1":
396
+ return "RSA-SHA1";
397
+ case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256":
398
+ return "RSA-SHA256";
399
+ case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384":
400
+ return "RSA-SHA384";
401
+ case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512":
402
+ return "RSA-SHA512";
403
+ default:
404
+ return void 0;
405
+ }
406
+ }
407
+ function verifySignatureValue(signatureXml, certBase64List) {
408
+ try {
409
+ const parser = new DOMParser();
410
+ const doc = parser.parseFromString(signatureXml, "text/xml");
411
+ const signatureNode = doc.getElementsByTagNameNS(XMLDSIG_NS, "Signature")[0];
412
+ if (!signatureNode) {
413
+ return "not-checked";
414
+ }
415
+ const certPem = certBase64List.length > 0 ? certPemFromBase64(certBase64List[0]) : void 0;
416
+ if (!certPem) {
417
+ return "not-checked";
418
+ }
419
+ const signedInfoNode = doc.getElementsByTagNameNS(XMLDSIG_NS, "SignedInfo")[0];
420
+ const signatureValueNode = doc.getElementsByTagNameNS(XMLDSIG_NS, "SignatureValue")[0];
421
+ if (!signedInfoNode || !signatureValueNode) {
422
+ return "invalid";
423
+ }
424
+ const canonicalizationMethod = doc.getElementsByTagNameNS(XMLDSIG_NS, "CanonicalizationMethod").item(0)?.getAttribute("Algorithm") ?? "http://www.w3.org/2001/10/xml-exc-c14n#";
425
+ const signatureMethod = doc.getElementsByTagNameNS(XMLDSIG_NS, "SignatureMethod").item(0)?.getAttribute("Algorithm");
426
+ const verifyAlgorithm = signatureAlgorithmToVerifyAlgorithm(signatureMethod ?? void 0);
427
+ if (!verifyAlgorithm) {
428
+ return "invalid";
429
+ }
430
+ const canonicalSignedInfo = canonicalizeNode(signedInfoNode, canonicalizationMethod);
431
+ const signatureValueBase64 = signatureValueNode.textContent?.replace(/\s+/g, "").trim() ?? "";
432
+ if (signatureValueBase64.length === 0) {
433
+ return "invalid";
434
+ }
435
+ const verifier = crypto2.createVerify(verifyAlgorithm);
436
+ verifier.update(Buffer.from(canonicalSignedInfo, "utf8"));
437
+ verifier.end();
438
+ const isValid = verifier.verify(certPem, Buffer.from(signatureValueBase64, "base64"));
439
+ return isValid ? "verified" : "invalid";
440
+ } catch {
441
+ return "invalid";
442
+ }
443
+ }
444
+ function loadSigningMaterialFromBuffer(certificateBuffer, certificatePath, certificatePassword) {
445
+ const extension = path.extname(certificatePath).toLowerCase();
446
+ if (extension === ".pfx" || extension === ".p12") {
447
+ const p12Der = forge3.util.createBuffer(Buffer.from(certificateBuffer).toString("binary"));
448
+ const p12Asn1 = forge3.asn1.fromDer(p12Der);
449
+ const p12 = forge3.pkcs12.pkcs12FromAsn1(p12Asn1, certificatePassword || "");
450
+ const keyBag = p12.getBags({
451
+ bagType: forge3.pki.oids.pkcs8ShroudedKeyBag
452
+ })[forge3.pki.oids.pkcs8ShroudedKeyBag];
453
+ const certBag = p12.getBags({ bagType: forge3.pki.oids.certBag })[forge3.pki.oids.certBag];
454
+ if (!keyBag || keyBag.length === 0 || !keyBag[0]?.key) {
455
+ throw new Error("No private key found in PKCS#12 certificate.");
456
+ }
457
+ if (!certBag || certBag.length === 0 || !certBag[0]?.cert) {
458
+ throw new Error("No certificate found in PKCS#12 certificate.");
459
+ }
460
+ return {
461
+ privateKeyPem: forge3.pki.privateKeyToPem(keyBag[0].key),
462
+ certificatePem: forge3.pki.certificateToPem(certBag[0].cert)
463
+ };
464
+ }
465
+ const pem = Buffer.from(certificateBuffer).toString("utf8");
466
+ const privateKeyPem = extractFirstPemBlock(pem, PRIVATE_KEY_PEM_LABELS);
467
+ const certificatePem = extractFirstPemBlock(pem, ["CERTIFICATE"]);
468
+ if (!privateKeyPem || !certificatePem) {
469
+ throw new Error("PEM certificate must contain both private key and certificate.");
470
+ }
471
+ return {
472
+ privateKeyPem,
473
+ certificatePem
474
+ };
475
+ }
476
+ function pemCertificateToBase64(pem) {
477
+ return pem.replace(/-----BEGIN CERTIFICATE-----/g, "").replace(/-----END CERTIFICATE-----/g, "").replace(/\s+/g, "").trim();
478
+ }
479
+ function asn1Child2(node, index) {
480
+ return Array.isArray(node.value) ? node.value[index] : void 0;
481
+ }
238
482
  function asn1Bytes(node) {
239
483
  return typeof node.value === "string" ? node.value : "";
240
484
  }
241
485
  function extractOcspUrls(certPem) {
242
486
  try {
243
- const cert = new crypto.X509Certificate(certPem);
487
+ const cert = new crypto2.X509Certificate(certPem);
244
488
  const infoAccess = cert.infoAccess;
245
489
  if (!infoAccess) {
246
490
  return [];
@@ -303,45 +547,45 @@ function httpPost(url, body, contentType) {
303
547
  var SHA1_OID = "1.3.14.3.2.26";
304
548
  function buildOcspRequestDer(leafPem, issuerPem) {
305
549
  try {
306
- const leaf = forge.pki.certificateFromPem(leafPem);
307
- const issuer = forge.pki.certificateFromPem(issuerPem);
308
- const issuerNameDer = forge.asn1.toDer(forge.pki.distinguishedNameToAsn1(issuer.subject)).getBytes();
309
- const issuerNameHash = forge.md.sha1.create().update(issuerNameDer).digest().getBytes();
310
- const pubKeyDer = forge.asn1.toDer(forge.pki.publicKeyToAsn1(issuer.publicKey)).getBytes();
311
- const pubKeyAsn1 = forge.asn1.fromDer(pubKeyDer);
312
- const bitString = asn1Child(pubKeyAsn1, 1);
550
+ const leaf = forge3.pki.certificateFromPem(leafPem);
551
+ const issuer = forge3.pki.certificateFromPem(issuerPem);
552
+ const issuerNameDer = forge3.asn1.toDer(forge3.pki.distinguishedNameToAsn1(issuer.subject)).getBytes();
553
+ const issuerNameHash = forge3.md.sha1.create().update(issuerNameDer).digest().getBytes();
554
+ const pubKeyDer = forge3.asn1.toDer(forge3.pki.publicKeyToAsn1(issuer.publicKey)).getBytes();
555
+ const pubKeyAsn1 = forge3.asn1.fromDer(pubKeyDer);
556
+ const bitString = asn1Child2(pubKeyAsn1, 1);
313
557
  const rawKey = bitString ? asn1Bytes(bitString).substring(1) : "";
314
- const issuerKeyHash = forge.md.sha1.create().update(rawKey).digest().getBytes();
315
- const serialBytes = forge.util.hexToBytes(leaf.serialNumber);
316
- const request = forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
317
- forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
318
- forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
319
- forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
320
- forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
321
- forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
322
- forge.asn1.create(
323
- forge.asn1.Class.UNIVERSAL,
324
- forge.asn1.Type.OID,
558
+ const issuerKeyHash = forge3.md.sha1.create().update(rawKey).digest().getBytes();
559
+ const serialBytes = forge3.util.hexToBytes(leaf.serialNumber);
560
+ const request = forge3.asn1.create(forge3.asn1.Class.UNIVERSAL, forge3.asn1.Type.SEQUENCE, true, [
561
+ forge3.asn1.create(forge3.asn1.Class.UNIVERSAL, forge3.asn1.Type.SEQUENCE, true, [
562
+ forge3.asn1.create(forge3.asn1.Class.UNIVERSAL, forge3.asn1.Type.SEQUENCE, true, [
563
+ forge3.asn1.create(forge3.asn1.Class.UNIVERSAL, forge3.asn1.Type.SEQUENCE, true, [
564
+ forge3.asn1.create(forge3.asn1.Class.UNIVERSAL, forge3.asn1.Type.SEQUENCE, true, [
565
+ forge3.asn1.create(forge3.asn1.Class.UNIVERSAL, forge3.asn1.Type.SEQUENCE, true, [
566
+ forge3.asn1.create(
567
+ forge3.asn1.Class.UNIVERSAL,
568
+ forge3.asn1.Type.OID,
325
569
  false,
326
- forge.asn1.oidToDer(SHA1_OID).getBytes()
570
+ forge3.asn1.oidToDer(SHA1_OID).getBytes()
327
571
  ),
328
- forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.NULL, false, "")
572
+ forge3.asn1.create(forge3.asn1.Class.UNIVERSAL, forge3.asn1.Type.NULL, false, "")
329
573
  ]),
330
- forge.asn1.create(
331
- forge.asn1.Class.UNIVERSAL,
332
- forge.asn1.Type.OCTETSTRING,
574
+ forge3.asn1.create(
575
+ forge3.asn1.Class.UNIVERSAL,
576
+ forge3.asn1.Type.OCTETSTRING,
333
577
  false,
334
578
  issuerNameHash
335
579
  ),
336
- forge.asn1.create(
337
- forge.asn1.Class.UNIVERSAL,
338
- forge.asn1.Type.OCTETSTRING,
580
+ forge3.asn1.create(
581
+ forge3.asn1.Class.UNIVERSAL,
582
+ forge3.asn1.Type.OCTETSTRING,
339
583
  false,
340
584
  issuerKeyHash
341
585
  ),
342
- forge.asn1.create(
343
- forge.asn1.Class.UNIVERSAL,
344
- forge.asn1.Type.INTEGER,
586
+ forge3.asn1.create(
587
+ forge3.asn1.Class.UNIVERSAL,
588
+ forge3.asn1.Type.INTEGER,
345
589
  false,
346
590
  serialBytes
347
591
  )
@@ -350,50 +594,50 @@ function buildOcspRequestDer(leafPem, issuerPem) {
350
594
  ])
351
595
  ])
352
596
  ]);
353
- return Buffer.from(forge.asn1.toDer(request).getBytes(), "binary");
597
+ return Buffer.from(forge3.asn1.toDer(request).getBytes(), "binary");
354
598
  } catch {
355
599
  return void 0;
356
600
  }
357
601
  }
358
602
  function parseOcspResponseStatus(data) {
359
603
  try {
360
- const asn1 = forge.asn1.fromDer(forge.util.createBuffer(data.toString("binary")));
361
- const statusNode = asn1Child(asn1, 0);
604
+ const asn1 = forge3.asn1.fromDer(forge3.util.createBuffer(data.toString("binary")));
605
+ const statusNode = asn1Child2(asn1, 0);
362
606
  if (!statusNode || asn1Bytes(statusNode) !== "\0") {
363
607
  return "error";
364
608
  }
365
- const respBytesWrapper = asn1Child(asn1, 1);
609
+ const respBytesWrapper = asn1Child2(asn1, 1);
366
610
  if (!respBytesWrapper) {
367
611
  return "unknown";
368
612
  }
369
- const respBytesSeq = asn1Child(respBytesWrapper, 0);
613
+ const respBytesSeq = asn1Child2(respBytesWrapper, 0);
370
614
  if (!respBytesSeq) {
371
615
  return "unknown";
372
616
  }
373
- const respOctet = asn1Child(respBytesSeq, 1);
617
+ const respOctet = asn1Child2(respBytesSeq, 1);
374
618
  if (!respOctet) {
375
619
  return "unknown";
376
620
  }
377
- const basicResp = forge.asn1.fromDer(forge.util.createBuffer(asn1Bytes(respOctet)));
378
- const tbsData = asn1Child(basicResp, 0);
621
+ const basicResp = forge3.asn1.fromDer(forge3.util.createBuffer(asn1Bytes(respOctet)));
622
+ const tbsData = asn1Child2(basicResp, 0);
379
623
  if (!tbsData) {
380
624
  return "unknown";
381
625
  }
382
- const first = asn1Child(tbsData, 0);
383
- const responsesIdx = first?.tagClass === forge.asn1.Class.CONTEXT_SPECIFIC && first.type === 0 ? 3 : 2;
384
- const responses = asn1Child(tbsData, responsesIdx);
626
+ const first = asn1Child2(tbsData, 0);
627
+ const responsesIdx = first?.tagClass === forge3.asn1.Class.CONTEXT_SPECIFIC && first.type === 0 ? 3 : 2;
628
+ const responses = asn1Child2(tbsData, responsesIdx);
385
629
  if (!responses) {
386
630
  return "unknown";
387
631
  }
388
- const single = asn1Child(responses, 0);
632
+ const single = asn1Child2(responses, 0);
389
633
  if (!single) {
390
634
  return "unknown";
391
635
  }
392
- const certStatus = asn1Child(single, 1);
636
+ const certStatus = asn1Child2(single, 1);
393
637
  if (!certStatus) {
394
638
  return "unknown";
395
639
  }
396
- if (certStatus.tagClass === forge.asn1.Class.CONTEXT_SPECIFIC) {
640
+ if (certStatus.tagClass === forge3.asn1.Class.CONTEXT_SPECIFIC) {
397
641
  if (certStatus.type === 0) {
398
642
  return "good";
399
643
  }
@@ -436,164 +680,8 @@ async function evaluateCertificateRevocation(leafCertPem, issuerCertPem) {
436
680
  checkedCrlUrls
437
681
  };
438
682
  }
439
- var TIMESTAMP_TAG_REGEX = /<(?:[\w.-]+:)?(?:EncapsulatedTimeStamp|SignatureTimeStamp)[^>]*>([\s\S]*?)<\/(?:[\w.-]+:)?(?:EncapsulatedTimeStamp|SignatureTimeStamp)>/i;
440
- async function evaluateTimestampAuthority(signatureXml) {
441
- try {
442
- const match = TIMESTAMP_TAG_REGEX.exec(signatureXml);
443
- if (!match?.[1]?.trim()) {
444
- return { status: "not-present" };
445
- }
446
- const tokenBase64 = match[1].replace(/\s+/g, "");
447
- const tokenDer = Buffer.from(tokenBase64, "base64");
448
- if (tokenDer.length === 0) {
449
- return { status: "invalid", error: "Empty timestamp token." };
450
- }
451
- const asn1 = forge.asn1.fromDer(forge.util.createBuffer(tokenDer.toString("binary")));
452
- const contentType = asn1Child(asn1, 0);
453
- if (!contentType) {
454
- return {
455
- status: "invalid",
456
- error: "Malformed timestamp token structure."
457
- };
458
- }
459
- return { status: "valid" };
460
- } catch (err) {
461
- return {
462
- status: "error",
463
- error: `Timestamp evaluation failed: ${String(err)}`
464
- };
465
- }
466
- }
467
-
468
- // src/signature-node/certificate-utils.ts
469
- function certificateInfoFromBase64(certBase64) {
470
- try {
471
- const certificate = new crypto.X509Certificate(Buffer.from(certBase64, "base64"));
472
- return {
473
- subject: certificate.subject || void 0,
474
- issuer: certificate.issuer || void 0,
475
- serialNumber: certificate.serialNumber || void 0,
476
- validFrom: certificate.validFrom || void 0,
477
- validTo: certificate.validTo || void 0
478
- };
479
- } catch {
480
- return void 0;
481
- }
482
- }
483
- function validateCertificateChain(certBase64List, additionalRootsPem) {
484
- if (certBase64List.length === 0) {
485
- return { status: "not-checked" };
486
- }
487
- try {
488
- const chain = certBase64List.map((value) => {
489
- const der = forge.util.decode64(value);
490
- return forge.pki.certificateFromAsn1(forge.asn1.fromDer(der));
491
- });
492
- const rootPem = [...tls.rootCertificates, ...additionalRootsPem];
493
- const caStore = forge.pki.createCaStore(rootPem);
494
- const verified = forge.pki.verifyCertificateChain(caStore, chain);
495
- return verified ? { status: "trusted" } : {
496
- status: "untrusted",
497
- error: "Certificate chain is not trusted."
498
- };
499
- } catch (error) {
500
- return {
501
- status: "untrusted",
502
- error: `Certificate trust validation failed: ${String(error)}`
503
- };
504
- }
505
- }
506
- function signatureAlgorithmToVerifyAlgorithm(signatureMethod) {
507
- switch (signatureMethod) {
508
- case "http://www.w3.org/2000/09/xmldsig#rsa-sha1":
509
- return "RSA-SHA1";
510
- case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256":
511
- return "RSA-SHA256";
512
- case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384":
513
- return "RSA-SHA384";
514
- case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512":
515
- return "RSA-SHA512";
516
- default:
517
- return void 0;
518
- }
519
- }
520
- function verifySignatureValue(signatureXml, certBase64List) {
521
- try {
522
- const parser = new DOMParser();
523
- const doc = parser.parseFromString(signatureXml, "text/xml");
524
- const signatureNode = doc.getElementsByTagNameNS(XMLDSIG_NS, "Signature")[0];
525
- if (!signatureNode) {
526
- return "not-checked";
527
- }
528
- const certPem = certBase64List.length > 0 ? certPemFromBase64(certBase64List[0]) : void 0;
529
- if (!certPem) {
530
- return "not-checked";
531
- }
532
- const signedInfoNode = doc.getElementsByTagNameNS(XMLDSIG_NS, "SignedInfo")[0];
533
- const signatureValueNode = doc.getElementsByTagNameNS(XMLDSIG_NS, "SignatureValue")[0];
534
- if (!signedInfoNode || !signatureValueNode) {
535
- return "invalid";
536
- }
537
- const canonicalizationMethod = doc.getElementsByTagNameNS(XMLDSIG_NS, "CanonicalizationMethod").item(0)?.getAttribute("Algorithm") ?? "http://www.w3.org/2001/10/xml-exc-c14n#";
538
- const signatureMethod = doc.getElementsByTagNameNS(XMLDSIG_NS, "SignatureMethod").item(0)?.getAttribute("Algorithm");
539
- const verifyAlgorithm = signatureAlgorithmToVerifyAlgorithm(signatureMethod ?? void 0);
540
- if (!verifyAlgorithm) {
541
- return "invalid";
542
- }
543
- const canonicalSignedInfo = canonicalizeNode(signedInfoNode, canonicalizationMethod);
544
- const signatureValueBase64 = signatureValueNode.textContent?.replace(/\s+/g, "").trim() ?? "";
545
- if (signatureValueBase64.length === 0) {
546
- return "invalid";
547
- }
548
- const verifier = crypto.createVerify(verifyAlgorithm);
549
- verifier.update(Buffer.from(canonicalSignedInfo, "utf8"));
550
- verifier.end();
551
- const isValid = verifier.verify(certPem, Buffer.from(signatureValueBase64, "base64"));
552
- return isValid ? "verified" : "invalid";
553
- } catch {
554
- return "invalid";
555
- }
556
- }
557
- function loadSigningMaterialFromBuffer(certificateBuffer, certificatePath, certificatePassword) {
558
- const extension = path.extname(certificatePath).toLowerCase();
559
- if (extension === ".pfx" || extension === ".p12") {
560
- const p12Der = forge.util.createBuffer(Buffer.from(certificateBuffer).toString("binary"));
561
- const p12Asn1 = forge.asn1.fromDer(p12Der);
562
- const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, certificatePassword || "");
563
- const keyBag = p12.getBags({
564
- bagType: forge.pki.oids.pkcs8ShroudedKeyBag
565
- })[forge.pki.oids.pkcs8ShroudedKeyBag];
566
- const certBag = p12.getBags({ bagType: forge.pki.oids.certBag })[forge.pki.oids.certBag];
567
- if (!keyBag || keyBag.length === 0 || !keyBag[0]?.key) {
568
- throw new Error("No private key found in PKCS#12 certificate.");
569
- }
570
- if (!certBag || certBag.length === 0 || !certBag[0]?.cert) {
571
- throw new Error("No certificate found in PKCS#12 certificate.");
572
- }
573
- return {
574
- privateKeyPem: forge.pki.privateKeyToPem(keyBag[0].key),
575
- certificatePem: forge.pki.certificateToPem(certBag[0].cert)
576
- };
577
- }
578
- const pem = Buffer.from(certificateBuffer).toString("utf8");
579
- const privateKeyMatch = pem.match(
580
- /-----BEGIN (?:RSA |EC |ENCRYPTED )?PRIVATE KEY-----[\s\S]+?-----END (?:RSA |EC |ENCRYPTED )?PRIVATE KEY-----/m
581
- );
582
- const certMatch = pem.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/m);
583
- if (!privateKeyMatch || !certMatch) {
584
- throw new Error("PEM certificate must contain both private key and certificate.");
585
- }
586
- return {
587
- privateKeyPem: privateKeyMatch[0],
588
- certificatePem: certMatch[0]
589
- };
590
- }
591
- function pemCertificateToBase64(pem) {
592
- return pem.replace(/-----BEGIN CERTIFICATE-----/g, "").replace(/-----END CERTIFICATE-----/g, "").replace(/\s+/g, "").trim();
593
- }
594
683
  function extractPemCertificatesFromText(text) {
595
- const matches = text.match(/-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g) ?? [];
596
- return matches.map((value) => value.trim()).filter((value) => value.length > 0);
684
+ return extractPemBlocks(text, "CERTIFICATE").map((value) => value.trim()).filter((value) => value.length > 0);
597
685
  }
598
686
  function parseBooleanEnv(envValue) {
599
687
  if (!envValue) {
@@ -734,7 +822,7 @@ function computeDigestBase642(content, digestAlgorithmUri) {
734
822
  if (!hashName) {
735
823
  return void 0;
736
824
  }
737
- return crypto.createHash(hashName).update(Buffer.from(content)).digest("base64");
825
+ return crypto2.createHash(hashName).update(Buffer.from(content)).digest("base64");
738
826
  }
739
827
  async function buildReferenceChecksFromSignatureXml(zip, signatureXml) {
740
828
  const parser = new DOMParser();
@@ -1067,7 +1155,7 @@ async function buildOfficeReferenceList(zip) {
1067
1155
  continue;
1068
1156
  }
1069
1157
  const entryBytes = await entry.async("uint8array");
1070
- const digestValue = crypto.createHash("sha256").update(Buffer.from(entryBytes)).digest("base64");
1158
+ const digestValue = crypto2.createHash("sha256").update(Buffer.from(entryBytes)).digest("base64");
1071
1159
  references.push({
1072
1160
  uri: `/${normalizePartPath(entryPath)}`,
1073
1161
  digestMethod,
@@ -1083,7 +1171,7 @@ function buildOfficeSignatureXml(references, privateKeyPem, certificatePem) {
1083
1171
  ).join("");
1084
1172
  const signedInfoXml = `<SignedInfo xmlns="${XMLDSIG_NS}"><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>${signedInfoReferencesXml}</SignedInfo>`;
1085
1173
  const canonicalSignedInfo = canonicalizeSignedInfoXml(signedInfoXml);
1086
- const signer = crypto.createSign("RSA-SHA256");
1174
+ const signer = crypto2.createSign("RSA-SHA256");
1087
1175
  signer.update(Buffer.from(canonicalSignedInfo, "utf8"));
1088
1176
  signer.end();
1089
1177
  const signatureValueBase64 = signer.sign(privateKeyPem).toString("base64");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-viewer-core",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "PowerPoint PPTX engine: parse, edit, serialize, and convert .pptx files. Framework-agnostic TypeScript SDK.",
5
5
  "keywords": [
6
6
  "angular",