|
| 1 | +/** |
| 2 | + * XmlValidator - Handles XML signature validation |
| 3 | + * Extracted from SignedXml to separate signing and validation concerns |
| 4 | + */ |
| 5 | + |
| 6 | +import type { NamespacePrefix } from "./types"; |
| 7 | +import { findChilds, findFirst } from "./utils"; |
| 8 | +import * as xmldom from "@xmldom/xmldom"; |
| 9 | + |
| 10 | +// Placeholder interface - full implementation needed |
| 11 | +interface ValidationReference { |
| 12 | + uri: string; |
| 13 | + transforms: ReadonlyArray<string>; |
| 14 | + digestAlgorithm: string; |
| 15 | + digestValue: string; |
| 16 | + inclusiveNamespacesPrefixList: string[]; |
| 17 | + xpath?: string; |
| 18 | + signedReference?: string; |
| 19 | + validationError?: Error; |
| 20 | + ancestorNamespaces?: NamespacePrefix[]; |
| 21 | +} |
| 22 | + |
| 23 | +export interface XmlValidatorOptions { |
| 24 | + idMode?: "wssecurity"; |
| 25 | + idAttribute?: string; |
| 26 | + publicCert?: crypto.KeyLike; |
| 27 | + getCertFromKeyInfo?: (keyInfo?: Node | null) => string | null; |
| 28 | +} |
| 29 | + |
| 30 | +/** |
| 31 | + * XmlValidator validates XML signatures |
| 32 | + * |
| 33 | + * Security: Extracts references ONLY from ds:SignedInfo to prevent wrapping attacks |
| 34 | + */ |
| 35 | +export class XmlValidator { |
| 36 | + private idMode?: "wssecurity"; |
| 37 | + private idAttributes: string[] = ["Id", "ID", "id"]; |
| 38 | + private publicCert?: crypto.KeyLike; |
| 39 | + private getCertFromKeyInfo?: (keyInfo?: Node | null) => string | null; |
| 40 | + |
| 41 | + // Internal state populated by loadSignature |
| 42 | + private signatureNode: Node | null = null; |
| 43 | + private signatureValue = ""; |
| 44 | + private signedInfoNode: Node | null = null; |
| 45 | + private canonicalizationAlgorithm = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; |
| 46 | + private validationReferences: ValidationReference[] = []; |
| 47 | + private signedReferences: string[] = []; |
| 48 | + |
| 49 | + constructor(opts: XmlValidatorOptions = {}) { |
| 50 | + if (opts.idMode) this.idMode = opts.idMode; |
| 51 | + if (opts.idAttribute) this.idAttributes = [opts.idAttribute]; |
| 52 | + if (opts.publicCert) this.publicCert = opts.publicCert; |
| 53 | + if (opts.getCertFromKeyInfo) this.getCertFromKeyInfo = opts.getCertFromKeyInfo; |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * Find all Signature elements (for multi-signature scenarios) |
| 58 | + */ |
| 59 | + findSignatures(doc: Node): Node[] { |
| 60 | + // TODO: Implement - extract from SignedXml |
| 61 | + return []; |
| 62 | + } |
| 63 | + |
| 64 | + /** |
| 65 | + * Load a signature from XML node or string |
| 66 | + * Security: extracts ONLY from ds:Signature/ds:SignedInfo to prevent wrapping |
| 67 | + */ |
| 68 | + loadSignature(signatureNode: Node | string): void { |
| 69 | + // TODO: Implement - extract from SignedXml with PR #493 security enhancements |
| 70 | + throw new Error("Not yet implemented - see PR description for full implementation"); |
| 71 | + } |
| 72 | + |
| 73 | + /** |
| 74 | + * Validate signature against XML document |
| 75 | + */ |
| 76 | + checkSignature(xml: string): boolean { |
| 77 | + // TODO: Implement - extract from SignedXml |
| 78 | + throw new Error("Not yet implemented - see PR description for full implementation"); |
| 79 | + } |
| 80 | + |
| 81 | + /** |
| 82 | + * Get the authenticated canonical XML bytes that passed validation |
| 83 | + * Security: returns ONLY content that was cryptographically verified |
| 84 | + */ |
| 85 | + getSignedReferences(): string[] { |
| 86 | + return [...this.signedReferences]; |
| 87 | + } |
| 88 | +} |
0 commit comments