samlesa 4.7.1 → 4.7.3

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.
package/README.md CHANGED
@@ -154,25 +154,25 @@ const { context: samlResponse } = await idp.createLoginResponse({
154
154
  });
155
155
  ```
156
156
 
157
- ### Artifact Binding Support
158
-
159
- ```typescript
160
- import { ServiceProvider, IdentityProvider } from 'samlesa';
161
-
162
- // Create front-channel artifact login request
163
- const loginRequest = sp.createLoginRequest(idp, 'artifact');
164
-
165
- // Parse ArtifactResolve request on the SP artifact resolution endpoint
166
- const artifactResolve = await sp.parseArtifactResolveRequest(idp, soapXml);
167
-
168
- // Create ArtifactResponse with the resolved SAML message
169
- const artifactResponse = await sp.createArtifactResolveResponse(idp, {
170
- inResponseTo: artifactResolve.extract.request.id,
171
- });
172
-
173
- // Parse artifact-based login response from the ACS endpoint
174
- const responseResult = await sp.parseLoginResponse(idp, 'artifact', request);
175
- ```
157
+ ### Artifact Binding Support
158
+
159
+ ```typescript
160
+ import { ServiceProvider, IdentityProvider } from 'samlesa';
161
+
162
+ // Create front-channel artifact login request
163
+ const loginRequest = sp.createLoginRequest(idp, 'artifact');
164
+
165
+ // Parse ArtifactResolve request on the SP artifact resolution endpoint
166
+ const artifactResolve = await sp.parseArtifactResolveRequest(idp, soapXml);
167
+
168
+ // Create ArtifactResponse with the resolved SAML message
169
+ const artifactResponse = await sp.createArtifactResolveResponse(idp, {
170
+ inResponseTo: artifactResolve.extract.request.id,
171
+ });
172
+
173
+ // Parse artifact-based login response from the ACS endpoint
174
+ const responseResult = await sp.parseLoginResponse(idp, 'artifact', request);
175
+ ```
176
176
 
177
177
  ---
178
178
 
@@ -176,6 +176,7 @@ export const logoutResponseStatusFields = [
176
176
  ];
177
177
  export const loginResponseFields = assertion => [
178
178
  { key: 'conditions', localPath: ['Assertion', 'Conditions'], attributes: ['NotBefore', 'NotOnOrAfter'], shortcut: assertion },
179
+ { key: 'audienceRestrictions', localPath: ['Assertion', 'Conditions', 'AudienceRestriction'], attributes: [], context: true, shortcut: assertion },
179
180
  { key: 'response', localPath: ['Response'], attributes: ['ID', 'IssueInstant', 'Destination', 'InResponseTo', 'Version'] },
180
181
  { key: 'responseIssuer', localPath: ['Response', 'Issuer'], attributes: [] },
181
182
  { key: 'audience', localPath: ['Assertion', 'Conditions', 'AudienceRestriction', 'Audience'], attributes: [], shortcut: assertion },
package/build/src/flow.js CHANGED
@@ -101,6 +101,55 @@ function validateResponseTimes(parserType, extractedProperties, self) {
101
101
  }
102
102
  return null;
103
103
  }
104
+ function normalizeStringList(value) {
105
+ if (Array.isArray(value)) {
106
+ return value.flatMap(item => normalizeStringList(item));
107
+ }
108
+ if (typeof value !== 'string') {
109
+ return [];
110
+ }
111
+ const normalized = value.trim();
112
+ return normalized ? [normalized] : [];
113
+ }
114
+ function collectAudienceValues(extractedProperties) {
115
+ return [
116
+ ...normalizeStringList(extractedProperties?.audience),
117
+ ...normalizeStringList(extractedProperties?.conditions?.audiences),
118
+ ];
119
+ }
120
+ function collectAudienceRestrictionGroups(extractedProperties) {
121
+ const restrictionFragments = normalizeStringList(extractedProperties?.audienceRestrictions);
122
+ if (restrictionFragments.length === 0) {
123
+ const flattenedAudiences = collectAudienceValues(extractedProperties);
124
+ return flattenedAudiences.length > 0 ? [flattenedAudiences] : [];
125
+ }
126
+ return restrictionFragments.map((fragment) => {
127
+ const parsedRestriction = extract(fragment, [{
128
+ key: 'audience',
129
+ localPath: ['AudienceRestriction', 'Audience'],
130
+ attributes: [],
131
+ }]);
132
+ return normalizeStringList(parsedRestriction?.audience);
133
+ });
134
+ }
135
+ function validateAudienceRestriction(parserType, extractedProperties, self) {
136
+ if (parserType !== ParserType.SAMLResponse) {
137
+ return null;
138
+ }
139
+ const expectedAudience = self?.entityMeta?.getEntityID?.();
140
+ if (typeof expectedAudience !== 'string' || expectedAudience.trim().length === 0) {
141
+ return null;
142
+ }
143
+ const audienceRestrictionGroups = collectAudienceRestrictionGroups(extractedProperties);
144
+ if (audienceRestrictionGroups.length === 0 ||
145
+ audienceRestrictionGroups.some(group => group.length === 0)) {
146
+ return self?.entitySetting?.strictSecurity === false ? null : 'ERR_MISSING_AUDIENCE';
147
+ }
148
+ if (!audienceRestrictionGroups.every(group => group.includes(expectedAudience.trim()))) {
149
+ return 'ERR_UNMATCH_AUDIENCE';
150
+ }
151
+ return null;
152
+ }
104
153
  function validateEndpointConstraints(parserType, extractedProperties, self, from) {
105
154
  const requestData = extractedProperties?.request ?? {};
106
155
  const responseData = extractedProperties?.response ?? {};
@@ -170,6 +219,10 @@ function runCommonValidation(parserType, extractedProperties, self, from) {
170
219
  if (timeError) {
171
220
  return timeError;
172
221
  }
222
+ const audienceError = validateAudienceRestriction(parserType, extractedProperties, self);
223
+ if (audienceError) {
224
+ return audienceError;
225
+ }
173
226
  return validateEndpointConstraints(parserType, extractedProperties, self, from);
174
227
  }
175
228
  // proceed the redirect binding flow
@@ -28,6 +28,47 @@ const signatureAlgorithms = algorithms.signature;
28
28
  const digestAlgorithms = algorithms.signatureToDigestMap;
29
29
  const certUse = wording.certUse;
30
30
  const urlParams = wording.urlParams;
31
+ function resolveSignaturePublicKeys(signatureNode, metadata) {
32
+ const certificateNode = toNodeArray(select(".//*[local-name(.)='X509Certificate']", signatureNode));
33
+ const metadataCerts = normalizeCertificates(metadata.getX509Certificate(certUse.signing));
34
+ if (certificateNode.length === 0 && metadataCerts.length === 0) {
35
+ throw new Error('NO_SELECTED_CERTIFICATE');
36
+ }
37
+ if (certificateNode.length !== 0) {
38
+ const x509CertificateData = certificateNode[0].firstChild?.nodeValue || '';
39
+ const x509Certificate = utility.normalizeCerString(x509CertificateData);
40
+ if (metadataCerts.length >= 1 && !metadataCerts.find((cert) => cert.trim() === x509Certificate.trim())) {
41
+ throw new Error('ERROR_UNMATCH_CERTIFICATE_DECLARATION_IN_METADATA');
42
+ }
43
+ return [utility.getPublicKeyPemFromCertificate(x509Certificate).toString()];
44
+ }
45
+ return metadataCerts.map((cert) => utility.getPublicKeyPemFromCertificate(cert).toString());
46
+ }
47
+ function verifyXmlSignatureWithPublicKeys(signatureNode, xmlCandidates, publicKeys, signatureAlgorithm) {
48
+ let lastError = null;
49
+ for (const publicKey of publicKeys) {
50
+ try {
51
+ const sig = new SignedXml();
52
+ sig.publicCert = publicKey;
53
+ if (signatureAlgorithm) {
54
+ sig.signatureAlgorithm = signatureAlgorithm;
55
+ }
56
+ sig.loadSignature(signatureNode);
57
+ for (const xmlCandidate of xmlCandidates) {
58
+ if (sig.checkSignature(xmlCandidate)) {
59
+ return { verified: true, sig };
60
+ }
61
+ }
62
+ }
63
+ catch (error) {
64
+ lastError = error;
65
+ }
66
+ }
67
+ if (lastError && publicKeys.length === 1) {
68
+ throw lastError;
69
+ }
70
+ return { verified: false, sig: null };
71
+ }
31
72
  let conList = [
32
73
  "http://www.w3.org/2001/10/xml-exc-c14n#",
33
74
  "http://www.w3.org/2001/10/xml-exc-c14n#WithComments",
@@ -49,9 +90,9 @@ const libSaml = () => {
49
90
  throw new Error('ERR_UNDEFINED_QUERY_PARAMS');
50
91
  }
51
92
  /**
52
- * 检测是否使用了不安全的SHA1系列签名算法
53
- * @param signatureAlgorithm 签名算法URI
54
- * @returns {Object} 包含是否使用不安全算法和具体算法名称的对象
93
+ * Detect whether an unsafe SHA1-family signature algorithm is used.
94
+ * @param signatureAlgorithm Signature algorithm URI.
95
+ * @returns {Object} Whether an unsafe algorithm is used and its name.
55
96
  */
56
97
  function checkUnsafeSignatureAlgorithm(signatureAlgorithm) {
57
98
  const unsafeAlgorithms = [
@@ -217,16 +258,16 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
217
258
  throw new Error('ERR_UNSUPPORTED_SIGNATURE_ALGORITHM');
218
259
  }
219
260
  function validateAndInflateSamlResponse(urlEncodedResponse) {
220
- // 3. 尝试DEFLATE解压(SAML规范要求使用原始DEFLATE)
261
+ // Try raw DEFLATE first, as required by the SAML binding.
221
262
  let xml = "";
222
263
  let compressed = true;
223
- try { // 1. URL解码
264
+ try { // URL decode.
224
265
  const base64Encoded = decodeURIComponent(urlEncodedResponse);
225
- // 2. Base64解码为Uint8Array
266
+ // Decode Base64 into a Uint8Array.
226
267
  xml = inflateString(base64Encoded);
227
268
  }
228
269
  catch (inflateError) {
229
- // 4. 解压失败,尝试直接解析为未压缩的XML
270
+ // If decompression fails, try parsing as uncompressed XML.
230
271
  try {
231
272
  const base64Encoded = decodeURIComponent(urlEncodedResponse);
232
273
  xml = atob(base64Encoded);
@@ -321,32 +362,32 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
321
362
  */
322
363
  /** For Test */
323
364
  attributeStatementBuilder(attributeData) {
324
- // 构建 XML 元素数组
325
- // 构建 XML 结构
365
+ // Build the XML element array.
366
+ // Build the XML structure.
326
367
  const attributeStatement = {
327
368
  'saml:AttributeStatement': [
328
- // 命名空间声明(在 AttributeStatement 上定义)
369
+ // Namespace declaration on AttributeStatement.
329
370
  {},
330
- // 遍历生成多个 Attribute
371
+ // Generate each Attribute.
331
372
  ...attributeData.map(attr => ({
332
373
  'saml:Attribute ': [
333
- // Attribute 属性
374
+ // Attribute properties.
334
375
  {
335
376
  _attr: {
336
377
  Name: attr.Name,
337
378
  NameFormat: attr.NameFormat
338
379
  }
339
380
  },
340
- // 遍历生成多个 AttributeValue
381
+ // Generate each AttributeValue.
341
382
  ...attr.valueArray.map((valueObj) => ({
342
383
  'saml:AttributeValue ': [
343
- // 数据类型(根据 ValueType
384
+ // Data type based on ValueType.
344
385
  {
345
386
  _attr: attr.ValueType === 1
346
387
  ? { 'xsi:type': 'xs:string' }
347
388
  : {}
348
389
  },
349
- // 值内容
390
+ // Value content.
350
391
  valueObj.value
351
392
  ]
352
393
  }))
@@ -354,7 +395,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
354
395
  }))
355
396
  ]
356
397
  };
357
- // 生成 XML(关闭自动声明头)
398
+ // Generate XML without an automatic declaration.
358
399
  const xmlString = xml([attributeStatement], { declaration: false });
359
400
  if (xmlString.trim() === '<saml:AttributeStatement></saml:AttributeStatement>') {
360
401
  return '';
@@ -392,10 +433,10 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
392
433
  sig.publicCert = this.getKeyInfo(signingCert, signatureConfig).getKey();
393
434
  sig.getKeyInfoContent = this.getKeyInfo(signingCert, signatureConfig).getKeyInfo;
394
435
  sig.privateKey = utility.readPrivateKey(privateKey, privateKeyPass, true);
395
- // 获取目标算法 (即 transformationAlgorithms[1])
436
+ // Read the target canonicalization algorithm.
396
437
  const targetAlgo = transformationAlgorithms[1];
397
- // 逻辑:如果 conList 包含 targetAlgo,则用 targetAlgo;否则用默认值
398
- // 注意:因为 targetAlgo 本身就在 conList 里,所以这里一定会命中 true
438
+ // Use targetAlgo when supported, otherwise use the default.
439
+ // In normal configuration targetAlgo is already in conList.
399
440
  const selectedAlgo = conList.includes(targetAlgo)
400
441
  ? targetAlgo
401
442
  : 'http://www.w3.org/2001/10/xml-exc-c14n#';
@@ -409,20 +450,20 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
409
450
  }
410
451
  return isBase64Output ? utility.base64Encode(sig.getSignedXml()) : sig.getSignedXml();
411
452
  },
412
- // 安全的证书验证函数
453
+ // Certificate validation helper.
413
454
  validateCertificate(certificateBase64, expectedIssuer) {
414
455
  try {
415
456
  const cert = new X509Certificate(Buffer.from(certificateBase64, 'base64'));
416
- // 1. 检查有效期
457
+ // Check certificate validity period.
417
458
  const now = new Date();
418
459
  if (new Date(cert.validFrom) > now || new Date(cert.validTo) < now) {
419
460
  throw new Error('Certificate has expired or is not yet valid');
420
461
  }
421
- // 2. 检查颁发者(如果提供)
462
+ // Check issuer when an expected issuer is provided.
422
463
  if (expectedIssuer && !cert.subject.includes(expectedIssuer)) {
423
464
  throw new Error('Certificate issuer does not match expected value');
424
465
  }
425
- // 3. 检查公钥类型(推荐 RSA EC
466
+ // Check public key type. RSA and EC are preferred.
426
467
  if (!['rsa', 'ec'].includes(cert.publicKey.type.toLowerCase())) {
427
468
  throw new Error('Certificate uses unsupported public key type');
428
469
  }
@@ -441,31 +482,31 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
441
482
  }
442
483
  },
443
484
  /**
444
- * 改进的SAML签名验证函数,支持多种签名和加密组合场景
445
- * @param xml SAML XML内容
446
- * @param opts 验证选项
485
+ * Verify SAML signatures across message, assertion, and encryption combinations.
486
+ * @param xml SAML XML content.
487
+ * @param opts Verification options.
447
488
  * @param self
448
- * @returns 验证结果对象
489
+ * @returns Verification result object.
449
490
  */
450
491
  async verifySignature(xml, opts, self) {
451
- const { dom } = getContext(); // 现在正常了
492
+ const { dom } = getContext();
452
493
  const doc = dom.parseFromString(xml, 'application/xml');
453
494
  const docParser = new DOMParser();
454
- // 优化1: 所有 XPath 路径改为精确匹配 SAML 2.0 标准
495
+ // Use exact SAML 2.0 XPath targets.
455
496
  const messageSignatureXpath = "/*[local-name() = 'Response' or local-name() = 'AuthnRequest' or local-name() = 'LogoutRequest' or local-name() = 'LogoutResponse']/*[local-name() = 'Signature']";
456
497
  const assertionSignatureXpath = "/*[local-name() = 'Response' or local-name() = 'AuthnRequest']/*[local-name() = 'Assertion']/*[local-name() = 'Signature']";
457
498
  const wrappingElementsXPath = "/*[local-name() = 'Response']/*[local-name() = 'Assertion']/*[local-name() = 'Subject']/*[local-name() = 'SubjectConfirmation']/*[local-name() = 'SubjectConfirmationData']//*[local-name() = 'Assertion' or local-name() = 'Signature']";
458
499
  const encryptedAssertionsXPath = "/*[local-name() = 'Response']/*[local-name() = 'EncryptedAssertion']";
459
- // 检测包装攻击
500
+ // Detect wrapping attacks.
460
501
  const wrappingElementNode = toNodeArray(select(wrappingElementsXPath, doc));
461
502
  if (wrappingElementNode.length !== 0) {
462
503
  throw new Error('ERR_POTENTIAL_WRAPPING_ATTACK');
463
504
  }
464
- // 获取各种元素
505
+ // Locate relevant XML elements.
465
506
  const messageSignatureNode = toNodeArray(select(messageSignatureXpath, doc));
466
507
  const assertionSignatureNode = toNodeArray(select(assertionSignatureXpath, doc));
467
508
  const encryptedAssertions = toNodeArray(select(encryptedAssertionsXPath, doc));
468
- // 初始化验证状态
509
+ // Initialize verification state.
469
510
  let isMessageSigned = messageSignatureNode.length > 0;
470
511
  let isAssertionSigned = assertionSignatureNode.length > 0;
471
512
  let encrypted = encryptedAssertions.length > 0;
@@ -475,7 +516,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
475
516
  let status = false;
476
517
  let samlContent = xml;
477
518
  let assertionContent = null;
478
- // 检测SAML消息类型
519
+ // Detect SAML message type.
479
520
  const rootElementName = doc.documentElement.localName;
480
521
  let type = 'Unknown';
481
522
  switch (rootElementName) {
@@ -510,7 +551,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
510
551
  }
511
552
  let hasUnsafeSignatureAlgorithm = false;
512
553
  let unsafeSignatureAlgorithm = '';
513
- // 特殊情况:带未签名断言的未签名SAML响应,应该拒绝
554
+ // Reject unsigned SAML responses that carry unsigned assertions.
514
555
  if (!isMessageSigned && !isAssertionSigned && !encrypted) {
515
556
  return {
516
557
  isMessageSigned,
@@ -527,7 +568,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
527
568
  unsafeSignatureAlgorithm
528
569
  };
529
570
  }
530
- // 优化2: 修复签名算法路径(关键安全修复)
571
+ // Resolve the signature algorithm from the signature node.
531
572
  const getSignatureAlgorithm = (signatureNode) => {
532
573
  const signatureAlgorithm = xpath.select1(".//*[local-name() = 'SignedInfo']/*[local-name() = 'SignatureMethod']/@Algorithm", signatureNode);
533
574
  if (!signatureAlgorithm || !signatureAlgorithm.value) {
@@ -535,7 +576,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
535
576
  }
536
577
  return signatureAlgorithm.value;
537
578
  };
538
- // 处理最外层有签名且断言加密的情况
579
+ // Handle outer message signature with encrypted assertion.
539
580
  if (isMessageSigned && encrypted) {
540
581
  try {
541
582
  const result = await this.decryptAssertionAsync(self, xml, opts);
@@ -550,7 +591,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
550
591
  isAssertionSigned = result?.[2]?.isAssertionSigned || false;
551
592
  const decryptedDoc = dom.parseFromString(samlContent, 'application/xml');
552
593
  const signatureNode = messageSignatureNode[0];
553
- // 修复:使用精确路径获取签名算法
594
+ // Resolve the signature algorithm with an exact path.
554
595
  const signatureAlgorithm = getSignatureAlgorithm(signatureNode);
555
596
  const checkResult = checkUnsafeSignatureAlgorithm(signatureAlgorithm);
556
597
  hasUnsafeSignatureAlgorithm = checkResult.hasUnsafeSignatureAlgorithm;
@@ -558,41 +599,21 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
558
599
  if (checkResult.hasUnsafeSignatureAlgorithm && !resolveAllowLegacySha1(opts, self)) {
559
600
  throw new Error('ERR_UNSAFE_SIGNATURE_ALGORITHM');
560
601
  }
561
- const sig = new SignedXml();
602
+ let publicKeys = [];
562
603
  if (!opts.keyFile && !opts.metadata) {
563
604
  throw new Error('ERR_UNDEFINED_SIGNATURE_VERIFIER_OPTIONS');
564
605
  }
565
606
  if (opts.keyFile) {
566
- sig.publicCert = fs.readFileSync(opts.keyFile);
607
+ publicKeys = [fs.readFileSync(opts.keyFile)];
567
608
  }
568
609
  else if (opts.metadata) {
569
- const certificateNode = select(".//*[local-name() = 'X509Certificate']", signatureNode);
570
- let metadataCert = opts.metadata.getX509Certificate(certUse.signing);
571
- metadataCert = normalizeCertificates(metadataCert);
572
- if (certificateNode.length === 0 && metadataCert.length === 0) {
573
- throw new Error('NO_SELECTED_CERTIFICATE');
574
- }
575
- if (certificateNode.length !== 0) {
576
- const x509CertificateData = certificateNode[0].firstChild.data;
577
- const x509Certificate = utility.normalizeCerString(x509CertificateData);
578
- if (metadataCert.length >= 1 && !metadataCert.find((cert) => cert.trim() === x509Certificate.trim())) {
579
- throw new Error('ERROR_UNMATCH_CERTIFICATE_DECLARATION_IN_METADATA');
580
- }
581
- sig.publicCert = this.getKeyInfo(x509Certificate).getKey();
582
- }
583
- else {
584
- sig.publicCert = this.getKeyInfo(metadataCert[0]).getKey();
585
- }
610
+ publicKeys = resolveSignaturePublicKeys(signatureNode, opts.metadata);
586
611
  }
587
- sig.signatureAlgorithm = opts.signatureAlgorithm;
588
- sig.loadSignature(signatureNode);
589
- // 验证最外层消息签名
590
- MessageSignatureStatus = sig.checkSignature(decryptedDoc.toString());
612
+ // Verify the outer message signature.
613
+ const verifyResult = verifyXmlSignatureWithPublicKeys(signatureNode, [decryptedDoc.toString(), xml], publicKeys, opts.signatureAlgorithm);
614
+ MessageSignatureStatus = verifyResult.verified;
591
615
  if (!MessageSignatureStatus) {
592
- MessageSignatureStatus = sig.checkSignature(xml);
593
- if (!MessageSignatureStatus) {
594
- throw new Error('ERR_FAILED_TO_VERIFY_MESSAGE_SIGNATURE_AFTER_DECRYPTION');
595
- }
616
+ throw new Error('ERR_FAILED_TO_VERIFY_MESSAGE_SIGNATURE_AFTER_DECRYPTION');
596
617
  }
597
618
  if (isAssertionSigned && !AssertionSignatureStatus) {
598
619
  throw new Error('ERR_FAILED_TO_VERIFY_ASSERTION_SIGNATURE_AFTER_DECRYPTION');
@@ -602,92 +623,56 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
602
623
  throw err;
603
624
  }
604
625
  }
605
- // 处理最外层有签名但断言未加密的情况
626
+ // Handle outer message signature without encrypted assertion.
606
627
  else if (isMessageSigned && !encrypted) {
607
628
  const signatureNode = messageSignatureNode[0];
608
- const signatureAlgorithm = getSignatureAlgorithm(signatureNode); // ✅ 修复
629
+ const signatureAlgorithm = getSignatureAlgorithm(signatureNode);
609
630
  const checkResult = checkUnsafeSignatureAlgorithm(signatureAlgorithm);
610
631
  hasUnsafeSignatureAlgorithm = checkResult.hasUnsafeSignatureAlgorithm;
611
632
  unsafeSignatureAlgorithm = checkResult.unsafeSignatureAlgorithm ?? "";
612
633
  if (checkResult.hasUnsafeSignatureAlgorithm && !resolveAllowLegacySha1(opts, self)) {
613
634
  throw new Error('ERR_UNSAFE_SIGNATURE_ALGORITHM');
614
635
  }
615
- const sig = new SignedXml();
636
+ let publicKeys = [];
616
637
  if (!opts.keyFile && !opts.metadata) {
617
638
  throw new Error('ERR_UNDEFINED_SIGNATURE_VERIFIER_OPTIONS');
618
639
  }
619
640
  if (opts.keyFile) {
620
- sig.publicCert = fs.readFileSync(opts.keyFile);
641
+ publicKeys = [fs.readFileSync(opts.keyFile)];
621
642
  }
622
643
  else if (opts.metadata) {
623
- const certificateNode = select(".//*[local-name() = 'X509Certificate']", signatureNode);
624
- let metadataCert = opts.metadata.getX509Certificate(certUse.signing);
625
- metadataCert = normalizeCertificates(metadataCert);
626
- if (certificateNode.length === 0 && metadataCert.length === 0) {
627
- throw new Error('NO_SELECTED_CERTIFICATE');
628
- }
629
- if (certificateNode.length !== 0) {
630
- const x509CertificateData = certificateNode[0].firstChild.data;
631
- const x509Certificate = utility.normalizeCerString(x509CertificateData);
632
- if (metadataCert.length >= 1 && !metadataCert.find((cert) => cert.trim() === x509Certificate.trim())) {
633
- throw new Error('ERROR_UNMATCH_CERTIFICATE_DECLARATION_IN_METADATA');
634
- }
635
- sig.publicCert = this.getKeyInfo(x509Certificate).getKey();
636
- }
637
- else {
638
- sig.publicCert = this.getKeyInfo(metadataCert[0]).getKey();
639
- }
644
+ publicKeys = resolveSignaturePublicKeys(signatureNode, opts.metadata);
640
645
  }
641
- sig.signatureAlgorithm = signatureAlgorithm;
642
- sig.loadSignature(signatureNode);
643
- MessageSignatureStatus = sig.checkSignature(doc.toString());
646
+ MessageSignatureStatus = verifyXmlSignatureWithPublicKeys(signatureNode, [doc.toString()], publicKeys, signatureAlgorithm).verified;
644
647
  if (!MessageSignatureStatus) {
645
648
  throw new Error('ERR_FAILED_TO_VERIFY_MESSAGE_SIGNATURE');
646
649
  }
647
650
  }
648
- // 优化3: 修复断言签名算法路径
651
+ // Verify assertion signatures with exact algorithm resolution.
649
652
  if (isAssertionSigned && !encrypted) {
650
653
  const signatureNode = assertionSignatureNode[0];
651
- const signatureAlgorithm = getSignatureAlgorithm(signatureNode); // ✅ 修复
654
+ const signatureAlgorithm = getSignatureAlgorithm(signatureNode);
652
655
  const checkResult = checkUnsafeSignatureAlgorithm(signatureAlgorithm);
653
656
  hasUnsafeSignatureAlgorithm = checkResult.hasUnsafeSignatureAlgorithm;
654
657
  unsafeSignatureAlgorithm = checkResult.unsafeSignatureAlgorithm ?? "";
655
658
  if (checkResult.hasUnsafeSignatureAlgorithm && !resolveAllowLegacySha1(opts, self)) {
656
659
  throw new Error('ERR_UNSAFE_SIGNATURE_ALGORITHM');
657
660
  }
658
- const sig = new SignedXml();
661
+ let publicKeys = [];
659
662
  if (!opts.keyFile && !opts.metadata) {
660
663
  throw new Error('ERR_UNDEFINED_SIGNATURE_VERIFIER_OPTIONS');
661
664
  }
662
665
  if (opts.keyFile) {
663
- sig.publicCert = fs.readFileSync(opts.keyFile);
666
+ publicKeys = [fs.readFileSync(opts.keyFile)];
664
667
  }
665
668
  else if (opts.metadata) {
666
- const certificateNode = select(".//*[local-name() = 'X509Certificate']", signatureNode);
667
- let metadataCert = opts.metadata.getX509Certificate(certUse.signing);
668
- metadataCert = normalizeCertificates(metadataCert);
669
- if (certificateNode.length === 0 && metadataCert.length === 0) {
670
- throw new Error('NO_SELECTED_CERTIFICATE');
671
- }
672
- if (certificateNode.length !== 0) {
673
- const x509CertificateData = certificateNode[0].firstChild.data;
674
- const x509Certificate = utility.normalizeCerString(x509CertificateData);
675
- if (metadataCert.length >= 1 && !metadataCert.find((cert) => cert.trim() === x509Certificate.trim())) {
676
- throw new Error('ERROR_UNMATCH_CERTIFICATE_DECLARATION_IN_METADATA');
677
- }
678
- sig.publicCert = this.getKeyInfo(x509Certificate).getKey();
679
- }
680
- else {
681
- sig.publicCert = this.getKeyInfo(metadataCert[0]).getKey();
682
- }
669
+ publicKeys = resolveSignaturePublicKeys(signatureNode, opts.metadata);
683
670
  }
684
- sig.signatureAlgorithm = signatureAlgorithm;
685
- sig.loadSignature(signatureNode);
686
- // ✅ 优化4: 修复断言节点获取路径(精确匹配)
671
+ // Locate the assertion node with exact matching.
687
672
  const assertionNode = select("/*[local-name() = 'Response' or local-name() = 'AuthnRequest']/*[local-name() = 'Assertion']", doc)[0];
688
673
  if (assertionNode) {
689
674
  const assertionDoc = dom.parseFromString(assertionNode.toString(), 'application/xml');
690
- AssertionSignatureStatus = sig.checkSignature(assertionDoc.toString());
675
+ AssertionSignatureStatus = verifyXmlSignatureWithPublicKeys(signatureNode, [assertionDoc.toString()], publicKeys, signatureAlgorithm).verified;
691
676
  }
692
677
  else {
693
678
  AssertionSignatureStatus = false;
@@ -696,7 +681,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
696
681
  throw new Error('ERR_FAILED_TO_VERIFY_ASSERTION_SIGNATURE');
697
682
  }
698
683
  }
699
- // 处理仅加密断言的情况
684
+ // Handle encrypted assertion without an outer message signature.
700
685
  if (encrypted && !isMessageSigned) {
701
686
  if (!encryptedAssertions || encryptedAssertions.length === 0) {
702
687
  throw new Error('ERR_UNDEFINED_ENCRYPTED_ASSERTION');
@@ -720,7 +705,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
720
705
  throw new Error('ERR_EXCEPTION_OF_ASSERTION_DECRYPTION');
721
706
  }
722
707
  }
723
- // 优化5: 修复断言内容获取路径(精确匹配)
708
+ // Extract assertion content with exact matching.
724
709
  else if (!encrypted && (isMessageSigned || isAssertionSigned)) {
725
710
  const assertions = toNodeArray(select("/*[local-name() = 'Response' or local-name() = 'AuthnRequest']/*[local-name() = 'Assertion']", doc));
726
711
  if (assertions?.length > 0) {
@@ -728,7 +713,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
728
713
  assertionContent = assertions[0].toString();
729
714
  }
730
715
  }
731
- // 检查整体状态
716
+ // Check aggregate verification status.
732
717
  status = (!isMessageSigned || MessageSignatureStatus) &&
733
718
  (!isAssertionSigned || AssertionSignatureStatus) &&
734
719
  (!encrypted || decrypted);
@@ -751,15 +736,15 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
751
736
  const { dom } = getContext();
752
737
  const doc = dom.parseFromString(xml, 'application/xml');
753
738
  const docParser = new DOMParser();
754
- // SOAP 消息定义 XPath
739
+ // Define XPath expressions for SOAP messages.
755
740
  const artifactResolveXpath = "/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='ArtifactResolve']";
756
741
  const artifactResponseXpath = "/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='ArtifactResponse']";
757
- // 检测 ArtifactResolve ArtifactResponse 的存在
742
+ // Detect ArtifactResolve or ArtifactResponse.
758
743
  // @ts-expect-error
759
744
  const artifactResolveNodes = toNodeArray(select(artifactResolveXpath, doc));
760
745
  // @ts-expect-error
761
746
  const artifactResponseNodes = toNodeArray(select(artifactResponseXpath, doc));
762
- // 根据消息类型选择合适的 XPath
747
+ // Select the base XPath from the SOAP message type.
763
748
  let basePath = "";
764
749
  if (artifactResolveNodes.length > 0) {
765
750
  basePath = "/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='ArtifactResolve']";
@@ -770,12 +755,12 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
770
755
  else {
771
756
  throw new Error('ERR_UNSUPPORTED_SOAP_MESSAGE_TYPE');
772
757
  }
773
- // 基于 SOAP 结构重新定义 XPath
758
+ // Build XPath expressions from the SOAP structure.
774
759
  const messageSignatureXpath = `${basePath}/*[local-name(.)='Signature']`;
775
760
  const assertionSignatureXpath = `${basePath}/*[local-name(.)='Response']/*[local-name(.)='Assertion']/*[local-name(.)='Signature']`;
776
761
  const wrappingElementsXPath = `${basePath}/*[local-name(.)='Response']/*[local-name(.)='Assertion']/*[local-name(.)='Subject']/*[local-name(.)='SubjectConfirmation']/*[local-name(.)='SubjectConfirmationData']//*[local-name(.)='Assertion' or local-name(.)='Signature']`;
777
762
  const encryptedAssertionsXpath = `${basePath}/*[local-name(.)='Response']/*[local-name(.)='EncryptedAssertion']`;
778
- // 包装攻击检测
763
+ // Detect wrapping attacks.
779
764
  // @ts-expect-error
780
765
  const wrappingElementNode = toNodeArray(select(wrappingElementsXPath, doc));
781
766
  if (wrappingElementNode.length !== 0) {
@@ -794,7 +779,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
794
779
  if (assertionSignatureNode.length > 0) {
795
780
  selection = selection.concat(assertionSignatureNode);
796
781
  }
797
- // 处理加密断言的情况
782
+ // Handle encrypted assertions.
798
783
  if (selection.length === 0) {
799
784
  if (encryptedAssertions.length > 0) {
800
785
  if (encryptedAssertions.length > 1) {
@@ -806,54 +791,35 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
806
791
  if (selection.length === 0) {
807
792
  throw new Error('ERR_ZERO_SIGNATURE');
808
793
  }
809
- // 尝试所有签名节点
794
+ // Try each signature node.
810
795
  for (const signatureNode of selection) {
811
- const sig = new SignedXml();
812
- let verified = false;
813
- // 检测不安全的签名算法
796
+ let publicKeys = [];
797
+ // Detect unsafe signature algorithms.
814
798
  const { hasUnsafeSignatureAlgorithm, unsafeSignatureAlgorithm } = checkUnsafeSignatureAlgorithm(opts.signatureAlgorithm || '');
815
799
  if (hasUnsafeSignatureAlgorithm && !resolveAllowLegacySha1(opts)) {
816
800
  throw new Error('ERR_UNSAFE_SIGNATURE_ALGORITHM');
817
801
  }
818
- sig.signatureAlgorithm = opts.signatureAlgorithm;
819
802
  if (!opts.keyFile && !opts.metadata) {
820
803
  throw new Error('ERR_UNDEFINED_SIGNATURE_VERIFIER_OPTIONS');
821
804
  }
822
805
  if (opts.keyFile) {
823
- sig.publicCert = fs.readFileSync(opts.keyFile);
806
+ publicKeys = [fs.readFileSync(opts.keyFile)];
824
807
  }
825
808
  if (opts.metadata) {
826
- const certificateNode = select(".//*[local-name(.)='X509Certificate']", signatureNode);
827
- // 证书处理逻辑
828
- let metadataCert = opts.metadata.getX509Certificate(certUse.signing);
829
- metadataCert = normalizeCertificates(metadataCert);
830
- // 没有证书的情况
831
- if (certificateNode.length === 0 && metadataCert.length === 0) {
832
- throw new Error('NO_SELECTED_CERTIFICATE');
833
- }
834
- if (certificateNode.length !== 0) {
835
- const x509CertificateData = certificateNode[0].firstChild.data;
836
- const x509Certificate = utility.normalizeCerString(x509CertificateData);
837
- if (metadataCert.length >= 1 && !metadataCert.includes(x509Certificate)) {
838
- throw new Error('ERROR_UNMATCH_CERTIFICATE_DECLARATION_IN_METADATA');
839
- }
840
- sig.publicCert = this.getKeyInfo(x509Certificate).getKey();
841
- }
842
- else {
843
- sig.publicCert = this.getKeyInfo(metadataCert[0]).getKey();
844
- }
809
+ publicKeys = resolveSignaturePublicKeys(signatureNode, opts.metadata);
845
810
  }
846
- sig.loadSignature(signatureNode);
847
- verified = sig.checkSignature(xml); // 使用原始XML验证
811
+ const verifyResult = verifyXmlSignatureWithPublicKeys(signatureNode, [xml], publicKeys, opts.signatureAlgorithm);
812
+ const verified = verifyResult.verified;
813
+ const sig = verifyResult.sig;
848
814
  if (!verified) {
849
815
  throw new Error('ERR_FAILED_TO_VERIFY_SIGNATURE');
850
816
  }
851
- if (sig.getSignedReferences().length < 1) {
817
+ if (!sig || sig.getSignedReferences().length < 1) {
852
818
  throw new Error('NO_SIGNATURE_REFERENCES');
853
819
  }
854
820
  const signedVerifiedXML = sig.getSignedReferences()[0];
855
821
  const rootNode = docParser.parseFromString(signedVerifiedXML, 'application/xml').documentElement;
856
- // 处理签名的内容
822
+ // Handle signed content.
857
823
  switch (rootNode?.localName) {
858
824
  case 'Response':
859
825
  // @ts-expect-error
@@ -866,17 +832,17 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
866
832
  if (assertions.length === 1) {
867
833
  return [true, assertions[0].toString(), false, false, hasUnsafeSignatureAlgorithm, unsafeSignatureAlgorithm];
868
834
  }
869
- return [true, null, false, true, hasUnsafeSignatureAlgorithm, unsafeSignatureAlgorithm]; // 签名验证成功但未找到断言
835
+ return [true, null, false, true, hasUnsafeSignatureAlgorithm, unsafeSignatureAlgorithm]; // Signature verified, but no assertion was found.
870
836
  case 'Assertion':
871
837
  return [true, rootNode.toString(), false, false, hasUnsafeSignatureAlgorithm, unsafeSignatureAlgorithm];
872
838
  case 'EncryptedAssertion':
873
839
  return [true, rootNode.toString(), true, false, hasUnsafeSignatureAlgorithm, unsafeSignatureAlgorithm];
874
840
  case 'ArtifactResolve':
875
841
  case 'ArtifactResponse':
876
- // 提取SOAP消息内部的实际内容
842
+ // Extract the actual message inside the SOAP envelope.
877
843
  return [true, rootNode.toString(), false, false, hasUnsafeSignatureAlgorithm, unsafeSignatureAlgorithm];
878
844
  default:
879
- return [true, null, false, true, hasUnsafeSignatureAlgorithm, unsafeSignatureAlgorithm]; // 签名验证成功但未找到可识别的内容
845
+ return [true, null, false, true, hasUnsafeSignatureAlgorithm, unsafeSignatureAlgorithm]; // Signature verified, but no recognized content was found.
880
846
  }
881
847
  }
882
848
  return [false, null, encryptedAssertions.length > 0, false, false, null];
@@ -911,18 +877,18 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
911
877
  };
912
878
  },
913
879
  /**
914
- * SAML 消息签名 (符合 SAML V2.0 绑定规范)
915
- * @param octetString - 要签名的原始数据 (OCTET STRING)
916
- * @param key - PEM 格式私钥
917
- * @param passphrase - 私钥密码 (如果有加密)
918
- * @param isBase64 - 是否返回 base64 编码 (默认 true)
919
- * @param signingAlgorithm - 签名算法 (默认 'rsa-sha256')
920
- * @returns 消息签名
880
+ * Sign a SAML message according to the SAML V2.0 binding specification.
881
+ * @param octetString - Raw data to sign as an OCTET STRING.
882
+ * @param key - Private key in PEM format.
883
+ * @param passphrase - Private key passphrase, when encrypted.
884
+ * @param isBase64 - Whether to return base64 encoding. Defaults to true.
885
+ * @param signingAlgorithm - Signature algorithm. Defaults to rsa-sha256.
886
+ * @returns Message signature.
921
887
  */
922
888
  constructMessageSignature(octetString, key, passphrase, isBase64, signingAlgorithm, securityOptions) {
923
889
  try {
924
890
  const algorithm = getSigningAlgorithm(signingAlgorithm ?? signatureAlgorithms.RSA_SHA256, securityOptions);
925
- const privateKeyPem = utility.readPrivateKey(key, passphrase); // 假设utility对象存在
891
+ const privateKeyPem = utility.readPrivateKey(key, passphrase);
926
892
  const signer = crypto.createSign(algorithm);
927
893
  signer.update(octetString, 'utf8');
928
894
  const signature = signer.sign({
@@ -945,16 +911,32 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
945
911
  * @param {string} verifyAlgorithm algorithm used to verify
946
912
  * @return {boolean} verification result
947
913
  */
948
- verifyMessageSignature(metadata, // 假设metadata对象有getX509Certificate方法
949
- octetString, signature, verifyAlgorithm, securityOptions) {
914
+ verifyMessageSignature(metadata, octetString, signature, verifyAlgorithm, securityOptions) {
950
915
  try {
951
- const signCert = metadata.getX509Certificate('signing'); // 假设certUse.signing是'signing'
916
+ const signCerts = normalizeCertificates(metadata.getX509Certificate('signing'));
952
917
  const algorithm = getSigningAlgorithm(verifyAlgorithm, securityOptions);
953
- const publicKeyPem = utility.getPublicKeyPemFromCertificate(signCert); // 假设utility对象存在
954
- const verifier = crypto.createVerify(algorithm);
955
- verifier.update(octetString, 'utf8');
918
+ if (signCerts.length === 0) {
919
+ throw new Error('ERR_METADATA_MISSING_SIGNING_CERT');
920
+ }
956
921
  const signatureBuffer = typeof signature === 'string' ? Buffer.from(signature, 'base64') : signature;
957
- return verifier.verify(publicKeyPem, signatureBuffer);
922
+ let lastError = null;
923
+ for (const signCert of signCerts) {
924
+ try {
925
+ const publicKeyPem = utility.getPublicKeyPemFromCertificate(signCert);
926
+ const verifier = crypto.createVerify(algorithm);
927
+ verifier.update(octetString, 'utf8');
928
+ if (verifier.verify(publicKeyPem, signatureBuffer)) {
929
+ return true;
930
+ }
931
+ }
932
+ catch (error) {
933
+ lastError = error;
934
+ }
935
+ }
936
+ if (lastError && signCerts.length === 1) {
937
+ throw lastError;
938
+ }
939
+ return false;
958
940
  }
959
941
  catch (error) {
960
942
  console.error('Signature verification failed:', error);
@@ -1005,7 +987,10 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
1005
987
  const rawAssertionNode = assertions[0];
1006
988
  // Perform encryption depends on the setting, default is false
1007
989
  if (sourceEntitySetting.isAssertionEncrypted) {
1008
- let encryptPem = targetEntityMetadata.getX509Certificate(certUse.encrypt);
990
+ let encryptPem = normalizeCertificates(targetEntityMetadata.getX509Certificate(certUse.encrypt))[0];
991
+ if (!encryptPem) {
992
+ throw new Error('ERR_METADATA_MISSING_ENCRYPTION_CERT');
993
+ }
1009
994
  const publicKeyPem = utility.getPublicKeyPemFromCertificate(encryptPem);
1010
995
  xmlenc.encrypt(rawAssertionNode.toString(), {
1011
996
  // use xml-encryption module
@@ -1016,9 +1001,9 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
1016
1001
  keyEncryptionDigest: sourceEntitySetting.keyEncryptionDigest,
1017
1002
  keyEncryptionMgf1: sourceEntitySetting.keyEncryptionMgf1,
1018
1003
  keyEncryptionOAEPParams: sourceEntitySetting.keyEncryptionOAEPParams,
1019
- disallowEncryptionWithInsecureAlgorithm: sourceEntitySetting.disallowEncryptionWithInsecureAlgorithm, // 禁止使用rsa-1_5 tripledes-cbc
1020
- disallowInsecureEncryption: sourceEntitySetting.disallowInsecureEncryption, //禁aes cbc系列加密算法
1021
- disallowInsecureHash: sourceEntitySetting.disallowInsecureHash, //禁止使用不安全的签名hash算法,不包括mgf1
1004
+ disallowEncryptionWithInsecureAlgorithm: sourceEntitySetting.disallowEncryptionWithInsecureAlgorithm, // Disallow rsa-1_5 and tripledes-cbc.
1005
+ disallowInsecureEncryption: sourceEntitySetting.disallowInsecureEncryption, // Disallow AES-CBC encryption algorithms.
1006
+ disallowInsecureHash: sourceEntitySetting.disallowInsecureHash, // Disallow unsafe signature hash algorithms except MGF1.
1022
1007
  warnInsecureAlgorithm: true
1023
1008
  }, (err, res) => {
1024
1009
  if (err) {
@@ -1039,10 +1024,10 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
1039
1024
  });
1040
1025
  },
1041
1026
  /**
1042
- * 同步版本的断言解密函数
1027
+ * Synchronous assertion decryption helper.
1043
1028
  */
1044
1029
  /**
1045
- * 同步版本的断言解密函数,支持解密后验证断言签名
1030
+ * Synchronous assertion decryption helper with post-decryption signature validation.
1046
1031
  */
1047
1032
  async decryptAssertionAsync(here, entireXML, opts) {
1048
1033
  const hereSetting = here.entitySetting;
@@ -1056,16 +1041,16 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
1056
1041
  throw new Error('ERR_MULTIPLE_ASSERTION');
1057
1042
  }
1058
1043
  const encAssertionNode = encryptedAssertions[0];
1059
- // DOM 节点转换为 XML 字符串
1044
+ // Convert the DOM node to an XML string.
1060
1045
  const encAssertionXml = encAssertionNode.toString();
1061
- // 使用 Promise 包装异步解密
1046
+ // Wrap asynchronous decryption in a Promise.
1062
1047
  let decryptedResult;
1063
1048
  try {
1064
1049
  const decryptResult = await xmlenc.decrypt(encAssertionXml, {
1065
1050
  key: utility.readPrivateKey(hereSetting.encPrivateKey, hereSetting.encPrivateKeyPass),
1066
1051
  warnInsecureAlgorithm: true,
1067
1052
  });
1068
- // xmlenc.decrypt 返回 Buffer,需要转换为字符串
1053
+ // xmlenc.decrypt may return Buffer, so convert it to string.
1069
1054
  decryptedResult = typeof decryptResult === 'string' ? decryptResult : decryptResult.toString();
1070
1055
  }
1071
1056
  catch (err) {
@@ -1073,13 +1058,13 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
1073
1058
  }
1074
1059
  let hasUnsafeSignatureAlgorithm = false;
1075
1060
  let unsafeSignatureAlgorithm = "";
1076
- // 解密完成后,检查解密后的断言是否还有签名需要验证
1061
+ // After decryption, check whether the assertion still has a signature to verify.
1077
1062
  const decryptedAssertionDoc = dom.parseFromString(decryptedResult, 'application/xml');
1078
1063
  let AssertionSignatureStatus = false;
1079
- // 检查解密后的断言是否有签名
1064
+ // Check whether the decrypted assertion has a signature.
1080
1065
  const assertionSignatureNode = toNodeArray(select("/*[local-name(.)='Assertion']/*[local-name(.)='Signature']", decryptedAssertionDoc));
1081
1066
  if (assertionSignatureNode.length > 0 && opts) {
1082
- // 解密后的断言有签名,需要验证
1067
+ // Verify the signature on the decrypted assertion.
1083
1068
  const signatureNode = assertionSignatureNode[0];
1084
1069
  const signatureAlgorithm = xpath.select1(".//*[local-name(.)='SignatureMethod']/@Algorithm", signatureNode);
1085
1070
  let checkResult = checkUnsafeSignatureAlgorithm(signatureAlgorithm.value || '');
@@ -1088,50 +1073,32 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
1088
1073
  if (checkResult.hasUnsafeSignatureAlgorithm && !resolveAllowLegacySha1(opts, here)) {
1089
1074
  throw new Error('ERR_UNSAFE_SIGNATURE_ALGORITHM');
1090
1075
  }
1091
- const sig = new SignedXml();
1076
+ let publicKeys = [];
1092
1077
  if (!opts.keyFile && !opts.metadata) {
1093
1078
  throw new Error('ERR_UNDEFINED_SIGNATURE_VERIFIER_OPTIONS');
1094
1079
  }
1095
1080
  if (opts.keyFile) {
1096
- sig.publicCert = fs.readFileSync(opts.keyFile);
1081
+ publicKeys = [fs.readFileSync(opts.keyFile)];
1097
1082
  }
1098
1083
  else if (opts.metadata) {
1099
- const certificateNode = select(".//*[local-name(.)='X509Certificate']", signatureNode);
1100
- let metadataCert = opts.metadata.getX509Certificate(certUse.signing);
1101
- metadataCert = normalizeCertificates(metadataCert);
1102
- if (certificateNode.length === 0 && metadataCert.length === 0) {
1103
- throw new Error('NO_SELECTED_CERTIFICATE');
1104
- }
1105
- if (certificateNode.length !== 0) {
1106
- const x509CertificateData = certificateNode[0].firstChild.data;
1107
- const x509Certificate = utility.normalizeCerString(x509CertificateData);
1108
- if (metadataCert.length >= 1 && !metadataCert.find((cert) => cert.trim() === x509Certificate.trim())) {
1109
- throw new Error('ERROR_UNMATCH_CERTIFICATE_DECLARATION_IN_METADATA');
1110
- }
1111
- sig.publicCert = this.getKeyInfo(x509Certificate).getKey();
1112
- }
1113
- else {
1114
- sig.publicCert = this.getKeyInfo(metadataCert[0]).getKey();
1115
- }
1084
+ publicKeys = resolveSignaturePublicKeys(signatureNode, opts.metadata);
1116
1085
  }
1117
- // 检测不安全的签名算法
1086
+ // Detect unsafe signature algorithms.
1118
1087
  let checkSafeResult = checkUnsafeSignatureAlgorithm(opts.signatureAlgorithm || '');
1119
1088
  hasUnsafeSignatureAlgorithm = checkSafeResult.hasUnsafeSignatureAlgorithm;
1120
1089
  unsafeSignatureAlgorithm = checkSafeResult.unsafeSignatureAlgorithm ?? "";
1121
1090
  if (checkSafeResult.hasUnsafeSignatureAlgorithm && !resolveAllowLegacySha1(opts, here)) {
1122
1091
  throw new Error('ERR_UNSAFE_SIGNATURE_ALGORITHM');
1123
1092
  }
1124
- sig.signatureAlgorithm = opts.signatureAlgorithm;
1125
- sig.loadSignature(signatureNode);
1126
- // 验证解密后断言的签名
1093
+ // Verify the decrypted assertion signature.
1127
1094
  const assertionDocForVerification = dom.parseFromString(decryptedResult, 'application/xml');
1128
- const assertionValid = sig.checkSignature(assertionDocForVerification.toString());
1095
+ const assertionValid = verifyXmlSignatureWithPublicKeys(signatureNode, [assertionDocForVerification.toString()], publicKeys, opts.signatureAlgorithm).verified;
1129
1096
  AssertionSignatureStatus = assertionValid;
1130
1097
  if (!assertionValid) {
1131
1098
  throw new Error('ERR_FAILED_TO_VERIFY_DECRYPTED_ASSERTION_SIGNATURE');
1132
1099
  }
1133
1100
  }
1134
- // 将解密后的断言替换原始文档中的加密断言
1101
+ // Replace the encrypted assertion with the decrypted assertion.
1135
1102
  const rawAssertionDoc = dom.parseFromString(decryptedResult, 'application/xml');
1136
1103
  // @ts-ignore
1137
1104
  doc.documentElement.replaceChild(rawAssertionDoc.documentElement, encAssertionNode);
@@ -1143,19 +1110,19 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
1143
1110
  }];
1144
1111
  },
1145
1112
  /**
1146
- * 解密 SOAP 响应中的加密断言
1147
- * @param self 当前实体(SP IdP
1148
- * @param entireXML 完整的 SOAP XML 响应
1149
- * @returns [解密后的完整 SOAP XML, 解密后的断言 XML]
1113
+ * Decrypt an encrypted assertion in a SOAP response.
1114
+ * @param self Current entity, SP or IdP.
1115
+ * @param entireXML Complete SOAP XML response.
1116
+ * @returns Decrypted full SOAP XML and decrypted assertion XML.
1150
1117
  */
1151
1118
  async decryptAssertionSoap(self, entireXML) {
1152
1119
  let hereSetting = self.entitySetting;
1153
1120
  const { dom } = getContext();
1154
1121
  try {
1155
- // 1. 解析 XML
1122
+ // Parse XML.
1156
1123
  // @ts-ignore
1157
1124
  const doc = dom.parseFromString(entireXML, 'application/xml');
1158
- // 2. 定位加密断言
1125
+ // Locate encrypted assertions.
1159
1126
  const encryptedAssertions = select("/*[local-name()='Envelope']/*[local-name()='Body']" +
1160
1127
  "/*[local-name()='ArtifactResponse']/*[local-name()='Response']" +
1161
1128
  "/*[local-name()='EncryptedAssertion']",
@@ -1165,17 +1132,17 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
1165
1132
  throw new Error('ERR_ENCRYPTED_ASSERTION_NOT_FOUND');
1166
1133
  }
1167
1134
  if (encryptedAssertions.length > 1) {
1168
- console.warn('发现多个加密断言,仅处理第一个');
1135
+ console.warn('Multiple encrypted assertions found; only the first one will be processed');
1169
1136
  }
1170
1137
  const encAssertionNode = encryptedAssertions[0];
1171
- // 3. 准备解密密钥
1138
+ // Prepare the decryption key.
1172
1139
  const privateKey = utility.readPrivateKey(self.entitySetting.encPrivateKey, self.entitySetting.encPrivateKeyPass);
1173
- // 4. 解密断言
1140
+ // Decrypt the assertion.
1174
1141
  const decryptedAssertion = await new Promise((resolve, reject) => {
1175
1142
  xmlenc.decrypt(encAssertionNode.toString(), { key: privateKey,
1176
- disallowInsecureEncryption: hereSetting.disallowInsecureEncryption, //开启会禁止解密使用aes cbc系列加密算法的xml
1177
- disallowDecryptionWithInsecureAlgorithm: hereSetting.disallowDecryptionWithInsecureAlgorithm, //开启会禁止解密使用rsa-1_5 tripledes-cbc加密算法的xml
1178
- disallowInsecureHash: hereSetting.disallowInsecureHash, //开启会禁止解密使用 hsa1系列 hash算法的xml
1143
+ disallowInsecureEncryption: hereSetting.disallowInsecureEncryption, // Disallow AES-CBC encrypted XML.
1144
+ disallowDecryptionWithInsecureAlgorithm: hereSetting.disallowDecryptionWithInsecureAlgorithm, // Disallow rsa-1_5 and tripledes-cbc encrypted XML.
1145
+ disallowInsecureHash: hereSetting.disallowInsecureHash, // Disallow SHA1-family hash algorithms.
1179
1146
  warnInsecureAlgorithm: true,
1180
1147
  }, (err, result) => {
1181
1148
  if (err) {
@@ -1187,18 +1154,18 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
1187
1154
  resolve(typeof result === 'string' ? result : result.toString());
1188
1155
  });
1189
1156
  });
1190
- // 5. 创建解密断言的 DOM
1157
+ // Create a DOM from the decrypted assertion.
1191
1158
  // @ts-ignore
1192
1159
  const decryptedDoc = dom.parseFromString(decryptedAssertion, 'application/xml');
1193
1160
  const decryptedAssertionNode = decryptedDoc.documentElement;
1194
- // 6. 替换加密断言为解密后的断言
1161
+ // Replace the encrypted assertion with the decrypted assertion.
1195
1162
  const parentNode = encAssertionNode.parentNode;
1196
1163
  if (!parentNode) {
1197
1164
  throw new Error('ERR_NO_PARENT_NODE_FOR_ENCRYPTED_ASSERTION');
1198
1165
  }
1199
1166
  // @ts-ignore
1200
1167
  parentNode.replaceChild(decryptedAssertionNode, encAssertionNode);
1201
- // 7. 序列化更新后的文档
1168
+ // Serialize the updated document.
1202
1169
  const updatedSoapXml = doc.toString();
1203
1170
  return [updatedSoapXml, decryptedAssertion];
1204
1171
  }
@@ -17,12 +17,12 @@ function toNodeArray(result) {
17
17
  }
18
18
  const certUse = wording.certUse;
19
19
  const docParser = new DOMParser();
20
- function resolvePublicCertificate(signatureNode, opts) {
20
+ function resolvePublicCertificates(signatureNode, opts) {
21
21
  if (!opts.keyFile && !opts.metadata) {
22
22
  throw new Error('ERR_UNDEFINED_SIGNATURE_VERIFIER_OPTIONS');
23
23
  }
24
24
  if (opts.keyFile) {
25
- return fs.readFileSync(opts.keyFile);
25
+ return [fs.readFileSync(opts.keyFile)];
26
26
  }
27
27
  const certificateNode = toNodeArray(select(".//*[local-name(.)='X509Certificate']", signatureNode));
28
28
  const metadataCerts = normalizeCertificates(opts.metadata.getX509Certificate(certUse.signing));
@@ -35,9 +35,9 @@ function resolvePublicCertificate(signatureNode, opts) {
35
35
  if (metadataCerts.length > 0 && !metadataCerts.includes(x509Certificate)) {
36
36
  throw new Error('ERROR_UNMATCH_CERTIFICATE_DECLARATION_IN_METADATA');
37
37
  }
38
- return libsaml.getKeyInfo(x509Certificate).getKey();
38
+ return [libsaml.getKeyInfo(x509Certificate).getKey()];
39
39
  }
40
- return libsaml.getKeyInfo(metadataCerts[0]).getKey();
40
+ return metadataCerts.map((cert) => libsaml.getKeyInfo(cert).getKey());
41
41
  }
42
42
  function extractResolvedMessage(rootNode) {
43
43
  const resolvedNodes = toNodeArray(select("./*[local-name()='Response' or local-name()='AuthnRequest' or local-name()='LogoutRequest' or local-name()='LogoutResponse']", rootNode));
@@ -48,14 +48,30 @@ function extractResolvedMessage(rootNode) {
48
48
  }
49
49
  function verifySignature(xml, signatureNodes, opts) {
50
50
  for (const signatureNode of signatureNodes) {
51
- const sig = new SignedXml();
52
- sig.publicCert = resolvePublicCertificate(signatureNode, opts);
53
- sig.loadSignature(signatureNode);
54
- const verified = sig.checkSignature(xml);
55
- if (!verified) {
51
+ const publicKeys = resolvePublicCertificates(signatureNode, opts);
52
+ let verifiedSig = null;
53
+ let lastError = null;
54
+ for (const publicKey of publicKeys) {
55
+ try {
56
+ const sig = new SignedXml();
57
+ sig.publicCert = publicKey;
58
+ sig.loadSignature(signatureNode);
59
+ if (sig.checkSignature(xml)) {
60
+ verifiedSig = sig;
61
+ break;
62
+ }
63
+ }
64
+ catch (error) {
65
+ lastError = error;
66
+ }
67
+ }
68
+ if (!verifiedSig) {
69
+ if (lastError && publicKeys.length === 1) {
70
+ throw lastError;
71
+ }
56
72
  throw new Error('ERR_FAILED_TO_VERIFY_SIGNATURE');
57
73
  }
58
- const signedReferences = sig.getSignedReferences();
74
+ const signedReferences = verifiedSig.getSignedReferences();
59
75
  if (signedReferences.length < 1) {
60
76
  throw new Error('NO_SIGNATURE_REFERENCES');
61
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samlesa",
3
- "version": "4.7.1",
3
+ "version": "4.7.3",
4
4
  "description": "High-level API for Single Sign On (SAML 2.0) baseed on samlify ",
5
5
  "main": "build/index.js",
6
6
  "keywords": [
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/extractor.ts"],"names":[],"mappings":"AAMA,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC;IAEnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,MAAM,MAAM,eAAe,GAAG,cAAc,EAAE,CAAC;AA4B/C,eAAO,MAAM,kBAAkB,EAAE,eAsFhC,CAAC;AAKF,eAAO,MAAM,qBAAqB,EAAE,eAsBnC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAsBpC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,eAGvC,CAAC;AAEF,eAAO,MAAM,iCAAiC,EAAE,eAG/C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,eAGxC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,SAAS,EAAE,GAAG,KAAK,eAAe,CAYrE,CAAC;AAqMF,eAAO,MAAM,mBAAmB,EAAE,eAMjC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAIlC,CAAC;AAKF,eAAO,MAAM,iBAAiB,EAAE,eAiI/B,CAAC;AAOF,eAAO,MAAM,gBAAgB,EAAE,eAyL9B,CAAC;AAEF,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,OAiN/D;AASD,eAAO,MAAM,2BAA2B,EAAE,eAkZzC,CAAC;AAIF;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,OAkRrE;AAKD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,OAE5C;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,OAEzC;AAGD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,OAExC;AACD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,OAEjD;AACD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,OAE9C;AACD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,OAErD"}
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/extractor.ts"],"names":[],"mappings":"AAMA,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC;IAEnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,MAAM,MAAM,eAAe,GAAG,cAAc,EAAE,CAAC;AA4B/C,eAAO,MAAM,kBAAkB,EAAE,eAsFhC,CAAC;AAKF,eAAO,MAAM,qBAAqB,EAAE,eAsBnC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAsBpC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,eAGvC,CAAC;AAEF,eAAO,MAAM,iCAAiC,EAAE,eAG/C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,eAGxC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,SAAS,EAAE,GAAG,KAAK,eAAe,CAarE,CAAC;AAqMF,eAAO,MAAM,mBAAmB,EAAE,eAMjC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAIlC,CAAC;AAKF,eAAO,MAAM,iBAAiB,EAAE,eAiI/B,CAAC;AAOF,eAAO,MAAM,gBAAgB,EAAE,eAyL9B,CAAC;AAEF,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,OAiN/D;AASD,eAAO,MAAM,2BAA2B,EAAE,eAkZzC,CAAC;AAIF;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,OAkRrE;AAKD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,OAE5C;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,OAEzC;AAGD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,OAExC;AACD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,OAEjD;AACD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,OAE9C;AACD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,OAErD"}
@@ -1 +1 @@
1
- {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/flow.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,UAAU;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,GAAG,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAynBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA8BhG;AAED,wBAAgB,IAAI,CAAC,OAAO,KAAA,GAAG,OAAO,CAAC,UAAU,CAAC,CA0BjD"}
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/flow.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,UAAU;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,GAAG,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AA4rBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA8BhG;AAED,wBAAgB,IAAI,CAAC,OAAO,KAAA,GAAG,OAAO,CAAC,UAAU,CAAC,CA0BjD"}
@@ -1,9 +1,9 @@
1
1
  import * as crypto from 'node:crypto';
2
2
  import type { MetadataInterface } from './metadata.js';
3
3
  /**
4
- * 生成 SAML Attribute 元素(不带 XML 声明头)
5
- * @param {Array} attributeData - 属性配置数据
6
- * @returns {string} SAML Attribute XML 字符串
4
+ * Generate SAML Attribute elements without an XML declaration.
5
+ * @param {Array} attributeData - Attribute configuration data.
6
+ * @returns {string} SAML Attribute XML string.
7
7
  */
8
8
  export interface SignatureConstructor {
9
9
  rawSamlMessage: string;
@@ -199,11 +199,11 @@ declare const _default: {
199
199
  publicKey?: undefined;
200
200
  };
201
201
  /**
202
- * 改进的SAML签名验证函数,支持多种签名和加密组合场景
203
- * @param xml SAML XML内容
204
- * @param opts 验证选项
202
+ * Verify SAML signatures across message, assertion, and encryption combinations.
203
+ * @param xml SAML XML content.
204
+ * @param opts Verification options.
205
205
  * @param self
206
- * @returns 验证结果对象
206
+ * @returns Verification result object.
207
207
  */
208
208
  verifySignature(xml: string, opts: SignatureVerifierOptions, self: any): Promise<any>;
209
209
  verifySignatureSoap(xml: string, opts: SignatureVerifierOptions): (string | boolean | null)[];
@@ -215,13 +215,13 @@ declare const _default: {
215
215
  */
216
216
  createKeySection(use: KeyUse, certString: string | Buffer): KeyComponent;
217
217
  /**
218
- * SAML 消息签名 (符合 SAML V2.0 绑定规范)
219
- * @param octetString - 要签名的原始数据 (OCTET STRING)
220
- * @param key - PEM 格式私钥
221
- * @param passphrase - 私钥密码 (如果有加密)
222
- * @param isBase64 - 是否返回 base64 编码 (默认 true)
223
- * @param signingAlgorithm - 签名算法 (默认 'rsa-sha256')
224
- * @returns 消息签名
218
+ * Sign a SAML message according to the SAML V2.0 binding specification.
219
+ * @param octetString - Raw data to sign as an OCTET STRING.
220
+ * @param key - Private key in PEM format.
221
+ * @param passphrase - Private key passphrase, when encrypted.
222
+ * @param isBase64 - Whether to return base64 encoding. Defaults to true.
223
+ * @param signingAlgorithm - Signature algorithm. Defaults to rsa-sha256.
224
+ * @returns Message signature.
225
225
  */
226
226
  constructMessageSignature(octetString: string, key: string, passphrase?: string, isBase64?: boolean, signingAlgorithm?: string, securityOptions?: SignatureSecurityOptions): string | Buffer;
227
227
  /**
@@ -251,10 +251,10 @@ declare const _default: {
251
251
  */
252
252
  encryptAssertion(sourceEntity: any, targetEntity: any, xml?: string): Promise<string>;
253
253
  /**
254
- * 同步版本的断言解密函数
254
+ * Synchronous assertion decryption helper.
255
255
  */
256
256
  /**
257
- * 同步版本的断言解密函数,支持解密后验证断言签名
257
+ * Synchronous assertion decryption helper with post-decryption signature validation.
258
258
  */
259
259
  decryptAssertionAsync(here: any, entireXML: string, opts?: SignatureVerifierOptions): Promise<(string | {
260
260
  isAssertionSigned: boolean;
@@ -263,10 +263,10 @@ declare const _default: {
263
263
  unsafeSignatureAlgorithm: string;
264
264
  })[]>;
265
265
  /**
266
- * 解密 SOAP 响应中的加密断言
267
- * @param self 当前实体(SP IdP
268
- * @param entireXML 完整的 SOAP XML 响应
269
- * @returns [解密后的完整 SOAP XML, 解密后的断言 XML]
266
+ * Decrypt an encrypted assertion in a SOAP response.
267
+ * @param self Current entity, SP or IdP.
268
+ * @param entireXML Complete SOAP XML response.
269
+ * @returns Decrypted full SOAP XML and decrypted assertion XML.
270
270
  */
271
271
  decryptAssertionSoap(self: any, entireXML: string): Promise<[string, string]>;
272
272
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"libsaml.d.ts","sourceRoot":"","sources":["../../src/libsaml.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"libsaml.d.ts","sourceRoot":"","sources":["../../src/libsaml.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"libsamlSoap.d.ts","sourceRoot":"","sources":["../../src/libsamlSoap.ts"],"names":[],"mappings":"AAKA,OAAgB,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAiBjE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;IAC7C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAyGD,iBAAe,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAoCpH;;;;AAED,wBAEE"}
1
+ {"version":3,"file":"libsamlSoap.d.ts","sourceRoot":"","sources":["../../src/libsamlSoap.ts"],"names":[],"mappings":"AAKA,OAAgB,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAiBjE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;IAC7C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA4HD,iBAAe,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAoCpH;;;;AAED,wBAEE"}