[
  {
    "path": ".eslintignore",
    "content": ""
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"env\": {\n    \"browser\": false,\n    \"node\": true,\n    \"mocha\": true,\n    \"es2020\": true\n  },\n  \"root\": true,\n  \"parser\": \"@typescript-eslint/parser\",\n  \"plugins\": [\"@typescript-eslint\", \"deprecation\"],\n  \"parserOptions\": {\n    \"project\": \"./tsconfig.eslint.json\",\n    \"ext\": \".ts\"\n  },\n  \"extends\": [\n    \"eslint:recommended\",\n    \"plugin:@typescript-eslint/eslint-recommended\",\n    \"plugin:@typescript-eslint/recommended\",\n    \"prettier\"\n  ],\n  \"rules\": {\n    \"no-console\": \"error\",\n    \"no-prototype-builtins\": \"error\",\n    \"one-var\": [\"error\", \"never\"],\n    \"no-duplicate-imports\": \"error\",\n    \"no-use-before-define\": \"error\",\n    \"curly\": \"error\",\n    \"eqeqeq\": [\"error\", \"smart\"],\n    \"no-var\": \"error\",\n    \"prefer-const\": \"error\",\n    \"prefer-template\": \"error\",\n    \"deprecation/deprecation\": \"error\",\n    \"@typescript-eslint/no-non-null-assertion\": \"error\",\n    \"@typescript-eslint/no-unused-vars\": \"error\",\n    \"@typescript-eslint/no-this-alias\": \"error\"\n  }\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Git to autodetect text files and normalise their line endings to LF when they are checked into your repository.\n* text=auto\n\n# git won't try to convert this files\n*.pem -text\n*.der -text\ntest/static/**/*.xml -text\n\n# These files are text and should be normalized (Convert crlf => lf)\n*.gitattributes text\n.gitignore text"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where the package manifests are located.\n# Please see the documentation for all configuration options:\n# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\n\nversion: 2\nupdates:\n  - package-ecosystem: \"npm\" # See documentation for possible values\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"monthly\"\n    # Always increase the version requirement\n    # to match the new version.\n    versioning-strategy: increase\n  - package-ecosystem: \"github-actions\" # See documentation for possible values\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"monthly\"\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: Test Status\non:\n  workflow_dispatch:\n  push:\n    branches: [master]\n  pull_request:\n    branches: [master]\n\njobs:\n  test:\n    name: Test Code\n    env:\n      CI: true\n\n    strategy:\n      matrix:\n        os: [ubuntu-latest]\n        node-version: [16, 18, 20]\n        experimental: [false]\n        include:\n          - os: ubuntu-latest\n            node-version: latest\n            experimental: true\n    runs-on: ${{ matrix.os }}\n    continue-on-error: ${{ matrix.experimental }}\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Use Node.js ${{ matrix.node-version }} on ${{ matrix.os }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm ci\n      - run: npm test\n      - run: npm update\n      - run: npm ci\n      - run: npm test\n      - name: Codecov\n        uses: codecov/codecov-action@v3.1.4\n        with:\n          verbose: true\n\n  lint:\n    name: Lint Code\n    env:\n      CI: true\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: \"lts/*\"\n      - run: |\n          npm ci \n          npm run lint\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: \"CodeQL\"\n\non:\n  push:\n    branches: [master]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [master]\n  schedule:\n    - cron: \"21 12 * * 1\"\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [\"javascript\"]\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]\n        # Learn more:\n        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n\n      # Initializes the CodeQL tools for scanning.\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@v3\n        with:\n          languages: ${{ matrix.language }}\n          # If you wish to specify custom queries, you can do so here or in a config file.\n          # By default, queries listed here will override any specified in a config file.\n          # Prefix the list here with \"+\" to use these queries and those in the config file.\n          # queries: ./path/to/local/query, your-org/your-repo/queries@main\n\n      # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).\n      # If this step fails, then you should remove it and run the build manually (see below)\n      - name: Autobuild\n        uses: github/codeql-action/autobuild@v3\n\n      # ℹ️ Command-line programs to run using the OS shell.\n      # 📚 https://git.io/JvXDl\n\n      # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines\n      #    and modify them (or add more) to build your code if your project\n      #    uses a compiled language\n\n      #- run: |\n      #   make bootstrap\n      #   make release\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@v3\n"
  },
  {
    "path": ".gitignore",
    "content": "lib/\nnode_modules/\np.js\np.txt\n*.svclog\n.DS_Store\n*.*~\n*.swp\nnpm-debug.log\n/test/validators/XmlCryptoJava/target/\n.eslintcache\n.nyc_output/\ncoverage/\n.idea\n"
  },
  {
    "path": ".grenrc.js",
    "content": "module.exports = {\n  dataSource: \"prs\",\n  prefix: \"\",\n  onlyMilestones: false,\n  ignoreTagsWith: [],\n  ignoreLabels: [],\n  tags: \"all\",\n  groupBy: {\n    \"Major Changes\": [\"semver-major\", \"breaking-change\"],\n    \"Minor Changes\": [\"semver-minor\", \"enhancement\", \"new-feature\"],\n    Dependencies: [\"dependencies\"],\n    \"Bug Fixes\": [\"semver-patch\", \"bug\", \"security\"],\n    Documentation: [\"documentation\"],\n    \"Technical Tasks\": [\"chore\"],\n    Other: [\"...\"],\n  },\n  changelogFilename: \"CHANGELOG.md\",\n  username: \"node-saml\",\n  repo: \"xml-crypto\",\n  template: {\n    issue: function (placeholders) {\n      const parts = [\n        \"-\",\n        placeholders.labels,\n        placeholders.name,\n        `[${placeholders.text}](${placeholders.url})`,\n      ];\n      return parts\n        .filter((_) => _)\n        .join(\" \")\n        .replace(\"  \", \" \");\n    },\n    release: function (placeholders) {\n      placeholders.body = placeholders.body.replace(\n        \"*No changelog for this release.*\",\n        \"\\n_No changelog for this release._\",\n      );\n      return `## ${placeholders.release} (${placeholders.date})\\n${placeholders.body}`;\n    },\n    group: function (placeholders) {\n      const iconMap = {\n        Enhancements: \"🚀\",\n        \"Minor Changes\": \"🚀\",\n        \"Bug Fixes\": \"🐛\",\n        Documentation: \"📚\",\n        \"Technical Tasks\": \"⚙️\",\n        \"Major Changes\": \"💣\",\n        Dependencies: \"🔗\",\n      };\n      const icon = iconMap[placeholders.heading] || \"🙈\";\n      return \"\\n### \" + icon + \" \" + placeholders.heading + \"\\n\";\n    },\n  },\n};\n"
  },
  {
    "path": ".markdownlint.json",
    "content": "{\n  \"MD013\": false,\n  \"MD024\": false\n}\n"
  },
  {
    "path": ".mocharc.json",
    "content": "{\n  \"diff\": true,\n  \"extension\": \"spec.ts\",\n  \"package\": \"./package.json\",\n  \"recursive\": true,\n  \"reporter\": \"spec\",\n  \"require\": [\"choma\", \"ts-node/register\"],\n  \"spec\": \"test/*.spec.ts\",\n  \"watch-files\": \"test/*.spec.ts\",\n  \"colors\": true\n}\n"
  },
  {
    "path": ".npmignore",
    "content": "test/\nexample/"
  },
  {
    "path": ".nycrc.json",
    "content": "{\n  \"extends\": \"@istanbuljs/nyc-config-typescript\",\n  \"all\": true,\n  \"check-coverage\": false,\n  \"reporter\": [\"lcov\", \"text\"],\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": ".prettierignore",
    "content": "# Ignore artifacts:\nlib\nnode_modules\npackage-lock.json\n.eslintcache\n.prettierignore\ntest/static/*\ntest/validators/*\n.nyc_output/*\ncoverage/*\n"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"printWidth\": 100\n}\n"
  },
  {
    "path": ".release-it.json",
    "content": "{\n  \"github\": {\n    \"release\": true,\n    \"releaseName\": \"v${version}\"\n  },\n  \"hooks\": {\n    \"after:bump\": \"npm run changelog\"\n  }\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"cSpell.words\": [\n    \"Canonicalization\",\n    \"canonicalize\",\n    \"canonicalized\",\n    \"codecov\",\n    \"feide\",\n    \"HMAC\",\n    \"posteb\",\n    \"preeb\",\n    \"reserialization\",\n    \"stricttextualmsg\",\n    \"wsfederation\",\n    \"wssecurity\",\n    \"xades\"\n  ]\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## 6.0.0 (2024-01-26)\n\n### 💣 Major Changes\n\n- [**breaking-change**] Set `getCertFromKeyInfo` to `noop` [#445](https://github.com/node-saml/xml-crypto/pull/445)\n\n### 🔗 Dependencies\n\n- [**dependencies**] [**github_actions**] Bump github/codeql-action from 2 to 3 [#434](https://github.com/node-saml/xml-crypto/pull/434)\n\n### 📚 Documentation\n\n- [**documentation**] Chore: Update README.md [#432](https://github.com/node-saml/xml-crypto/pull/432)\n\n---\n\n## v5.1.1 (2024-01-17)\n\n### 🐛 Bug Fixes\n\n- [**bug**] fix: template literal [#443](https://github.com/node-saml/xml-crypto/pull/443)\n\n---\n\n## v5.1.0 (2024-01-07)\n\n### 🚀 Minor Changes\n\n- [**enhancement**] Enhance derToPem to support XML pretty-print [#439](https://github.com/node-saml/xml-crypto/pull/439)\n\n### 🔗 Dependencies\n\n- [**dependencies**] [**javascript**] Bump @typescript-eslint/parser from 6.13.0 to 6.18.1 [#442](https://github.com/node-saml/xml-crypto/pull/442)\n- [**dependencies**] [**javascript**] Bump @typescript-eslint/eslint-plugin from 6.13.0 to 6.18.1 [#441](https://github.com/node-saml/xml-crypto/pull/441)\n- [**dependencies**] [**javascript**] Bump follow-redirects from 1.15.3 to 1.15.4 [#440](https://github.com/node-saml/xml-crypto/pull/440)\n- [**dependencies**] [**javascript**] Bump eslint from 8.54.0 to 8.56.0 [#436](https://github.com/node-saml/xml-crypto/pull/436)\n- [**dependencies**] [**javascript**] Bump @types/node from 16.18.65 to 16.18.69 [#435](https://github.com/node-saml/xml-crypto/pull/435)\n- [**dependencies**] [**javascript**] Bump release-it from 16.2.1 to 16.3.0 [#428](https://github.com/node-saml/xml-crypto/pull/428)\n\n---\n\n## v5.0.0 (2023-11-27)\n\n### 💣 Major Changes\n\n- [**breaking-change**] Mark `getKeyInfo()` private as it has no public consumers [#412](https://github.com/node-saml/xml-crypto/pull/412)\n- [**breaking-change**] Remove the default for `getKeyInfoContent` forcing a consumer to choose [#411](https://github.com/node-saml/xml-crypto/pull/411)\n- [**documentation**] [**breaking-change**] Remove default for transformation algorithm [#410](https://github.com/node-saml/xml-crypto/pull/410)\n- [**breaking-change**] Remove default for signature algorithm [#408](https://github.com/node-saml/xml-crypto/pull/408)\n- [**breaking-change**] Remove default for digest algorithm [#406](https://github.com/node-saml/xml-crypto/pull/406)\n- [**breaking-change**] Remove default canonicalization algorithm [#405](https://github.com/node-saml/xml-crypto/pull/405)\n- [**chore**] [**breaking-change**] Improve code clarity; remove unused functions [#397](https://github.com/node-saml/xml-crypto/pull/397)\n- [**breaking-change**] Move validation messages to each reference [#396](https://github.com/node-saml/xml-crypto/pull/396)\n- [**breaking-change**] Make references accessible only via get/set [#395](https://github.com/node-saml/xml-crypto/pull/395)\n- [**chore**] [**breaking-change**] Reduce public interface by making some methods private [#394](https://github.com/node-saml/xml-crypto/pull/394)\n- [**chore**] [**breaking-change**] Update build to support Node@16 [#385](https://github.com/node-saml/xml-crypto/pull/385)\n\n### 🚀 Minor Changes\n\n- [**enhancement**] Add support for directly querying a node to see if it has passed validation [#389](https://github.com/node-saml/xml-crypto/pull/389)\n- [**enhancement**] Add method for checking if element is signed [#368](https://github.com/node-saml/xml-crypto/pull/368)\n\n### 🔗 Dependencies\n\n- [**dependencies**] [**javascript**] Bump @typescript-eslint/eslint-plugin from 5.62.0 to 6.13.0 [#422](https://github.com/node-saml/xml-crypto/pull/422)\n- [**dependencies**] [**javascript**] Bump @prettier/plugin-xml from 3.2.1 to 3.2.2 [#423](https://github.com/node-saml/xml-crypto/pull/423)\n- [**dependencies**] [**javascript**] Bump @types/mocha from 10.0.2 to 10.0.6 [#421](https://github.com/node-saml/xml-crypto/pull/421)\n- [**dependencies**] [**javascript**] Bump @types/chai from 4.3.6 to 4.3.11 [#419](https://github.com/node-saml/xml-crypto/pull/419)\n- [**dependencies**] [**javascript**] Bump prettier from 3.0.3 to 3.1.0 [#418](https://github.com/node-saml/xml-crypto/pull/418)\n- [**dependencies**] [**javascript**] Bump typescript from 5.2.2 to 5.3.2 [#415](https://github.com/node-saml/xml-crypto/pull/415)\n- [**dependencies**] [**javascript**] Bump eslint from 8.51.0 to 8.54.0 [#414](https://github.com/node-saml/xml-crypto/pull/414)\n- [**dependencies**] [**github_actions**] Bump actions/setup-node from 3 to 4 [#413](https://github.com/node-saml/xml-crypto/pull/413)\n- [**dependencies**] [**javascript**] Bump @babel/traverse from 7.22.4 to 7.23.2 [#407](https://github.com/node-saml/xml-crypto/pull/407)\n- [**dependencies**] [**github_actions**] Bump actions/checkout from 3 to 4 [#392](https://github.com/node-saml/xml-crypto/pull/392)\n- [**dependencies**] [**javascript**] Bump eslint-plugin-deprecation from 1.4.1 to 2.0.0 [#390](https://github.com/node-saml/xml-crypto/pull/390)\n- [**dependencies**] [**javascript**] Bump typescript from 5.1.6 to 5.2.2 [#383](https://github.com/node-saml/xml-crypto/pull/383)\n- [**dependencies**] [**javascript**] Bump eslint-config-prettier from 8.8.0 to 9.0.0 [#381](https://github.com/node-saml/xml-crypto/pull/381)\n- [**dependencies**] Update dependencies; move to @xmldom-scoped is-dom-node package [#402](https://github.com/node-saml/xml-crypto/pull/402)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Ensure the X509Certificate tag is properly prefixed [#377](https://github.com/node-saml/xml-crypto/pull/377)\n- [**bug**] Fix transform processing regression [#379](https://github.com/node-saml/xml-crypto/pull/379)\n- [**bug**] Enforce consistent transform processing [#380](https://github.com/node-saml/xml-crypto/pull/380)\n\n### 📚 Documentation\n\n- [**documentation**] Clarify use of <KeyInfo /> in signature validation [#401](https://github.com/node-saml/xml-crypto/pull/401)\n\n### ⚙️ Technical Tasks\n\n- [**chore**] Use is-dom-node for DOM node checking and narrowing [#388](https://github.com/node-saml/xml-crypto/pull/388)\n- [**chore**] Improve and simplify validation logic [#373](https://github.com/node-saml/xml-crypto/pull/373)\n- [**chore**] Add additional type checking [#369](https://github.com/node-saml/xml-crypto/pull/369)\n\n---\n\n## v4.1.0 (2023-07-28)\n\n### 💣 Major Changes\n\n- [**bug**] [**breaking-change**] Fix `pemToDer()` return type [#364](https://github.com/node-saml/xml-crypto/pull/364)\n\n### ⚙️ Technical Tasks\n\n- [**chore**] Improve exported typings [#367](https://github.com/node-saml/xml-crypto/pull/367)\n- [**chore**] Use stricter typing in tests [#366](https://github.com/node-saml/xml-crypto/pull/366)\n- [**chore**] Consistently reference `xmldom` [#365](https://github.com/node-saml/xml-crypto/pull/365)\n- [**chore**] Rename `findChilds()` to `findChildren()` [#363](https://github.com/node-saml/xml-crypto/pull/363)\n\n---\n\n## v4.0.1 (2023-07-22)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Use correct type for options [#360](https://github.com/node-saml/xml-crypto/pull/360)\n- [**bug**] Fix validationErrors type [#361](https://github.com/node-saml/xml-crypto/pull/361)\n\n---\n\n## v4.0.0 (2023-07-21)\n\n### 💣 Major Changes\n\n- [**documentation**] [**breaking-change**] Expand the options, move idmode into options, fix types [#323](https://github.com/node-saml/xml-crypto/pull/323)\n- [**breaking-change**] Refactor classes into their own files [#318](https://github.com/node-saml/xml-crypto/pull/318)\n- [**breaking-change**] Prefer ES6 classes to prototypical inheritance [#316](https://github.com/node-saml/xml-crypto/pull/316)\n- [**breaking-change**] Rename `signingCert` -> `publicCert` and `signingKey` -> `privateKey` [#315](https://github.com/node-saml/xml-crypto/pull/315)\n- [**semver-major**] [**breaking-change**] Add support for <X509Certificate /> in <KeyInfo />; remove `KeyInfoProvider` [#301](https://github.com/node-saml/xml-crypto/pull/301)\n- [**semver-major**] Target an LTS version of Node [#299](https://github.com/node-saml/xml-crypto/pull/299)\n\n### 🚀 Minor Changes\n\n- [**enhancement**] Exports C14nCanonicalization, ExclusiveCanonicalization [#336](https://github.com/node-saml/xml-crypto/pull/336)\n\n### 🔗 Dependencies\n\n- [**dependencies**] [**javascript**] Bump @xmldom/xmldom from 0.8.8 to 0.8.10 [#358](https://github.com/node-saml/xml-crypto/pull/358)\n- [**dependencies**] [**javascript**] Bump @typescript-eslint/eslint-plugin from 5.60.1 to 5.62.0 [#357](https://github.com/node-saml/xml-crypto/pull/357)\n- [**dependencies**] [**javascript**] Bump @prettier/plugin-xml from 2.2.0 to 3.1.1 [#356](https://github.com/node-saml/xml-crypto/pull/356)\n- [**dependencies**] [**javascript**] Bump prettier from 2.8.8 to 3.0.0 [#350](https://github.com/node-saml/xml-crypto/pull/350)\n- [**dependencies**] [**javascript**] Bump release-it from 15.11.0 to 16.1.3 [#352](https://github.com/node-saml/xml-crypto/pull/352)\n- [**dependencies**] [**javascript**] Bump prettier-plugin-packagejson from 2.4.3 to 2.4.5 [#353](https://github.com/node-saml/xml-crypto/pull/353)\n- [**dependencies**] [**javascript**] Bump @typescript-eslint/parser from 5.60.1 to 5.62.0 [#354](https://github.com/node-saml/xml-crypto/pull/354)\n- [**dependencies**] [**javascript**] Bump typescript from 5.1.5 to 5.1.6 [#351](https://github.com/node-saml/xml-crypto/pull/351)\n- [**dependencies**] [**javascript**] Bump word-wrap from 1.2.3 to 1.2.4 [#348](https://github.com/node-saml/xml-crypto/pull/348)\n- [**dependencies**] [**javascript**] Bump eslint from 8.42.0 to 8.45.0 [#344](https://github.com/node-saml/xml-crypto/pull/344)\n- [**dependencies**] Update gren for better support for branches [#340](https://github.com/node-saml/xml-crypto/pull/340)\n- [**dependencies**] [**github_actions**] Bump codecov/codecov-action from 3.1.1 to 3.1.4 [#290](https://github.com/node-saml/xml-crypto/pull/290)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Fix issue in case when namespace has no prefix [#330](https://github.com/node-saml/xml-crypto/pull/330)\n- [**bug**] Use correct path for code coverage reports [#302](https://github.com/node-saml/xml-crypto/pull/302)\n\n### ⚙️ Technical Tasks\n\n- [**chore**] Enforce eslint `no-unused-vars` [#349](https://github.com/node-saml/xml-crypto/pull/349)\n- [**chore**] Enforce eslint `deprecation` [#347](https://github.com/node-saml/xml-crypto/pull/347)\n- [**chore**] Enforce eslint `prefer-template` [#346](https://github.com/node-saml/xml-crypto/pull/346)\n- [**chore**] Enforce eslint `no-this-alias` [#345](https://github.com/node-saml/xml-crypto/pull/345)\n- [**chore**] Convert this project to TypeScript [#325](https://github.com/node-saml/xml-crypto/pull/325)\n- [**chore**] Rename files in preparation for TS migration [#343](https://github.com/node-saml/xml-crypto/pull/343)\n- [**chore**] Don't force `master` branch when generating changelog [#342](https://github.com/node-saml/xml-crypto/pull/342)\n- [**chore**] Enforce eslint `no-unused-vars` [#322](https://github.com/node-saml/xml-crypto/pull/322)\n- [**chore**] Enforce eslint `no-prototype-builtins` [#321](https://github.com/node-saml/xml-crypto/pull/321)\n- [**chore**] Enforce eslint `eqeqeq` rule [#320](https://github.com/node-saml/xml-crypto/pull/320)\n- [**chore**] Update types [#319](https://github.com/node-saml/xml-crypto/pull/319)\n- [**chore**] Adjust code to pass eslint `prefer-const` [#312](https://github.com/node-saml/xml-crypto/pull/312)\n- [**chore**] Adjust code to pass eslint `no-var` [#311](https://github.com/node-saml/xml-crypto/pull/311)\n- [**chore**] Adjust code to pass eslint `curly` [#310](https://github.com/node-saml/xml-crypto/pull/310)\n- [**chore**] Adjust code to pass eslint `one-var` [#309](https://github.com/node-saml/xml-crypto/pull/309)\n- [**chore**] Typings [#295](https://github.com/node-saml/xml-crypto/pull/295)\n- [**chore**] Lint code for new linting rules [#300](https://github.com/node-saml/xml-crypto/pull/300)\n- [**chore**] Make linting rules more strict [#293](https://github.com/node-saml/xml-crypto/pull/293)\n- [**chore**] Replace Nodeunit with Mocha [#294](https://github.com/node-saml/xml-crypto/pull/294)\n\n---\n\n## v3.1.0 (2023-06-05)\n\n### 🚀 Minor Changes\n\n- [**enhancement**] Add support for appending attributes to KeyInfo element [#285](https://github.com/node-saml/xml-crypto/pull/285)\n- [**enhancement**] Use inclusiveNamespacesPrefixList to generate InclusiveNamespaces [#284](https://github.com/node-saml/xml-crypto/pull/284)\n- [**enhancement**] build: add release-it to facilitate builds [#275](https://github.com/node-saml/xml-crypto/pull/275)\n- [**enhancement**] [**documentation**] feat: add type declaration [#277](https://github.com/node-saml/xml-crypto/pull/277)\n- [**enhancement**] make FileKeyInfo extensible for compatibility with TypeScript [#273](https://github.com/node-saml/xml-crypto/pull/273)\n- [**enhancement**] Updated getKeyInfo function with actual implementation [#249](https://github.com/node-saml/xml-crypto/pull/249)\n\n### 🔗 Dependencies\n\n- [**dependencies**] Update dependencies [#296](https://github.com/node-saml/xml-crypto/pull/296)\n- [**dependencies**] Bump minimatch from 3.0.4 to 3.1.2 [#276](https://github.com/node-saml/xml-crypto/pull/276)\n- [**dependencies**] [**javascript**] Bump qs from 6.5.2 to 6.5.3 [#271](https://github.com/node-saml/xml-crypto/pull/271)\n\n### 📚 Documentation\n\n- [**documentation**] [**chore**] Adjust references for `node-saml` organization [#298](https://github.com/node-saml/xml-crypto/pull/298)\n\n### ⚙️ Technical Tasks\n\n- [**chore**] Force CI to run on every PR [#286](https://github.com/node-saml/xml-crypto/pull/286)\n- [**chore**] Format code [#289](https://github.com/node-saml/xml-crypto/pull/289)\n- [**chore**] Lint code [#288](https://github.com/node-saml/xml-crypto/pull/288)\n- [**chore**] Add support for linting [#287](https://github.com/node-saml/xml-crypto/pull/287)\n\n---\n\n## v3.0.1 (2022-10-31)\n\n### 🔗 Dependencies\n\n- [**dependencies**] [**javascript**] Bump ajv and har-validator [#266](https://github.com/node-saml/xml-crypto/pull/266)\n- [**dependencies**] [**javascript**] Bump yargs-parser and tap [#257](https://github.com/node-saml/xml-crypto/pull/257)\n- [**dependencies**] [**javascript**] Bump minimist and tap [#264](https://github.com/node-saml/xml-crypto/pull/264)\n\n---\n\n## v3.0.0 (2022-10-13)\n\n### 🔗 Dependencies\n\n- [**dependencies**] [**javascript**] Bump @xmldom/xmldom from 0.7.0 to 0.8.3 [#261](https://github.com/node-saml/xml-crypto/pull/261)\n- [**dependencies**] [**javascript**] Bump handlebars from 4.0.11 to 4.7.7 [#247](https://github.com/node-saml/xml-crypto/pull/247)\n- [**dependencies**] [**javascript**] Bump lodash from 4.17.10 to 4.17.21 [#248](https://github.com/node-saml/xml-crypto/pull/248)\n- [**dependencies**] [**javascript**] Bump hosted-git-info from 2.6.0 to 2.8.9 [#246](https://github.com/node-saml/xml-crypto/pull/246)\n- [**dependencies**] [**javascript**] Bump ejs from 2.6.1 to 3.1.7 [#244](https://github.com/node-saml/xml-crypto/pull/244)\n- [**dependencies**] [**javascript**] Bump path-parse from 1.0.5 to 1.0.7 [#245](https://github.com/node-saml/xml-crypto/pull/245)\n\n### ⚙️ Technical Tasks\n\n- [**chore**] build(ci): test on later node versions [#251](https://github.com/node-saml/xml-crypto/pull/251)\n\n---\n\n## v2.1.4 (2022-07-08)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Correct behavior for XML canonicalization with namespaces and nested elements [#242](https://github.com/node-saml/xml-crypto/pull/242)\n\n---\n\n## v2.1.3 (2021-08-20)\n\n### 🔗 Dependencies\n\n- [**dependencies**] [**javascript**] [**security**] Update xmldom to 0.7.0 [#236](https://github.com/node-saml/xml-crypto/pull/236)\n- [**dependencies**] [**java**] Bump commons-io from 2.4 to 2.7 in /test/validators/XmlCryptoJava [#229](https://github.com/node-saml/xml-crypto/pull/229)\n\n---\n\n## v2.1.2 (2021-04-19)\n\n_No changelog for this release._\n\n---\n\n## v2.1.1 (2021-03-16)\n\n_No changelog for this release._\n\n---\n\n## v2.1.0 (2021-03-15)\n\n### 🔗 Dependencies\n\n- [**dependencies**] [**javascript**] Bump xmldom from 0.1.27 to 0.5.0 [#225](https://github.com/node-saml/xml-crypto/pull/225)\n- [**dependencies**] [**java**] Bump junit from 4.12 to 4.13.1 in /test/validators/XmlCryptoJava [#217](https://github.com/node-saml/xml-crypto/pull/217)\n\n### 🐛 Bug Fixes\n\n- [**bug**] fix for #201 [#218](https://github.com/node-saml/xml-crypto/pull/218)\n\n### ⚙️ Technical Tasks\n\n- [**chore**] Don't pull the example folder into the module build [#220](https://github.com/node-saml/xml-crypto/pull/220)\n\n---\n\n## v2.0.0 (2020-10-05)\n\n_No changelog for this release._\n\n---\n\n## v1.5.3 (2020-04-14)\n\n### 🚀 Minor Changes\n\n- [**enhancement**] Async response for built in algo sign/verify [#209](https://github.com/node-saml/xml-crypto/pull/209)\n\n---\n\n## v1.5.2 (2020-04-13)\n\n_No changelog for this release._\n\n---\n\n## v1.5.1 (2020-04-13)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Test suites of other projects (mocha) that include v1.5.0 fail [#207](https://github.com/node-saml/xml-crypto/pull/207)\n\n---\n\n## v1.5.0 (2020-04-12)\n\n### 🚀 Minor Changes\n\n- [**enhancement**] Add callback options to sign/verify asynchronously [#206](https://github.com/node-saml/xml-crypto/pull/206)\n\n---\n\n## v1.4.1 (2020-04-03)\n\n### 🔗 Dependencies\n\n- [**dependencies**] Bump js-yaml from 3.12.0 to 3.13.1 [#205](https://github.com/node-saml/xml-crypto/pull/205)\n\n### 🐛 Bug Fixes\n\n- [**bug**] validation instruction typo [#192](https://github.com/node-saml/xml-crypto/pull/192)\n- [**bug**] Fixes line end and white space normalization. [#196](https://github.com/node-saml/xml-crypto/pull/196)\n\n---\n\n## v1.4.0 (2019-04-26)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Fix canon xml being computed differently when signing, than when verifying [#183](https://github.com/node-saml/xml-crypto/pull/183)\n\n---\n\n## v1.3.0 (2019-03-23)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Xml enc c14# inclusivenamespace fixes [#179](https://github.com/node-saml/xml-crypto/pull/179)\n\n---\n\n## v1.2.0 (2019-02-26)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Accept existing xml prefixes to avoid adding to signature [#171](https://github.com/node-saml/xml-crypto/pull/171)\n\n---\n\n## v1.1.4 (2019-02-11)\n\n### 🐛 Bug Fixes\n\n- [**bug**] fix for enveloped signatures [#174](https://github.com/node-saml/xml-crypto/pull/174)\n\n---\n\n## v1.1.3 (2019-02-10)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Update signed-xml.js [#172](https://github.com/node-saml/xml-crypto/pull/172)\n\n---\n\n## v1.1.2 (2019-01-28)\n\n_No changelog for this release._\n\n---\n\n## v1.1.1 (2019-01-01)\n\n_No changelog for this release._\n\n---\n\n## v1.1.0 (2019-01-01)\n\n_No changelog for this release._\n\n---\n\n## v1.0.2 (2018-11-08)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Bugfix: a namespace in the inclusive namespace list should be treated… [#163](https://github.com/node-saml/xml-crypto/pull/163)\n\n---\n\n## v1.0.1 (2018-09-10)\n\n_No changelog for this release._\n\n---\n\n## v1.0.0 (2018-09-10)\n\n### 🔗 Dependencies\n\n- [**dependencies**] Addresses issue #235 by upgrading xmldom version to 0.1.27 [#155](https://github.com/node-saml/xml-crypto/pull/155)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Decode DigestValue for validation [#160](https://github.com/node-saml/xml-crypto/pull/160)\n- [**bug**] Patch for non exclusive c14n [#157](https://github.com/node-saml/xml-crypto/pull/157)\n- [**bug**] Merge changes from datagovsg fork [#161](https://github.com/node-saml/xml-crypto/pull/161)\n\n---\n\n## v0.9.0 (2017-02-26)\n\n_No changelog for this release._\n\n---\n\n## 0.9.0 (2017-02-26)\n\n### 🚀 Minor Changes\n\n- [**enhancement**] Separate namespaces with same prefix but different URI [#117](https://github.com/node-saml/xml-crypto/pull/117)\n\n### 🐛 Bug Fixes\n\n- [**bug**] Implement transform: 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315' [#116](https://github.com/node-saml/xml-crypto/pull/116)\n\n---\n\n## v0.8.5 (2016-12-08)\n\n### 🚀 Minor Changes\n\n- [**enhancement**] Add possible id attribute 'id' [#121](https://github.com/node-saml/xml-crypto/pull/121)\n\n### 📚 Documentation\n\n- [**documentation**] Update license field to npm recommendation [#119](https://github.com/node-saml/xml-crypto/pull/119)\n- [**documentation**] Fix author field format [#120](https://github.com/node-saml/xml-crypto/pull/120)\n- [**documentation**] Remove namespace-breaking reserialization of signature from example in README [#105](https://github.com/node-saml/xml-crypto/pull/105)\n\n---\n\n## v0.8.4 (2016-03-12)\n\n_No changelog for this release._\n\n---\n\n## v0.8.3 (2016-03-06)\n\n_No changelog for this release._\n\n---\n\n## v0.8.2 (2015-12-13)\n\n_No changelog for this release._\n\n---\n\n## v0.8.1 (2015-10-15)\n\n_No changelog for this release._\n\n---\n\n## v0.8.0 (2015-10-03)\n\n_No changelog for this release._\n\n---\n\n## V1 (2013-07-20)\n\n_No changelog for this release._\n"
  },
  {
    "path": "LICENSE",
    "content": "(The MIT License)\n\nCopyright (c) Yaron Naveh <yaronn01@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# xml-crypto\n\n![Build Status](https://github.com/node-saml/xml-crypto/workflows/Test%20Status/badge.svg)\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n[![codecov](https://codecov.io/gh/node-saml/xml-crypto/branch/master/graph/badge.svg?token=PQWCMBWBFB)](https://codecov.io/gh/node-saml/xml-crypto)\n[![DeepScan grade](https://deepscan.io/api/teams/17569/projects/30525/branches/981134/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=17569&pid=30525&bid=981134)\n\n[![NPM](https://nodei.co/npm/xml-crypto.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/xml-crypto)\n\n## Sponsors\n\n![workos](https://github.com/workos.png?size=30) [workos](https://github.com/workos)\n\n![stytchauth](https://github.com/stytchauth.png?size=30) [stytchauth](https://github.com/stytchauth)\n\n## Upgrading\n\nThe `.getReferences()` AND the `.references` APIs are deprecated.\nPlease do not attempt to access them. The content in them should be treated as unsigned.\n\nInstead, we strongly encourage users to migrate to the `.getSignedReferences()` API. See the [Verifying XML document](#verifying-xml-documents) section\nWe understand that this may take a lot of efforts to migrate, feel free to ask for help.\nThis will help prevent future XML signature wrapping attacks.\n\n## Supported Algorithms\n\n### Canonicalization and Transformation Algorithms\n\n- Canonicalization <http://www.w3.org/TR/2001/REC-xml-c14n-20010315>\n- Canonicalization with comments <http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments>\n- Exclusive Canonicalization <http://www.w3.org/2001/10/xml-exc-c14n#>\n- Exclusive Canonicalization with comments <http://www.w3.org/2001/10/xml-exc-c14n#WithComments>\n- Enveloped Signature transform <http://www.w3.org/2000/09/xmldsig#enveloped-signature>\n\n### Hashing Algorithms\n\n- SHA1 digests <http://www.w3.org/2000/09/xmldsig#sha1>\n- SHA256 digests <http://www.w3.org/2001/04/xmlenc#sha256>\n- SHA512 digests <http://www.w3.org/2001/04/xmlenc#sha512>\n\n### Signature Algorithms\n\n- RSA-SHA1 <http://www.w3.org/2000/09/xmldsig#rsa-sha1>\n- RSA-SHA256 <http://www.w3.org/2001/04/xmldsig-more#rsa-sha256>\n- RSA-SHA256 with MGF1 <http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1>\n- RSA-SHA512 <http://www.w3.org/2001/04/xmldsig-more#rsa-sha512>\n\nHMAC-SHA1 is also available but it is disabled by default\n\n- HMAC-SHA1 <http://www.w3.org/2000/09/xmldsig#hmac-sha1>\n\nto enable HMAC-SHA1, call `enableHMAC()` on your instance of `SignedXml`.\n\nThis will enable HMAC and disable digital signature algorithms. Due to key\nconfusion issues, it is risky to have both HMAC-based and public key digital\nsignature algorithms enabled at same time.\n\n[You are able to extend xml-crypto with custom algorithms.](#customizing-algorithms)\n\n## Signing Xml documents\n\nWhen signing a xml document you can pass the following options to the `SignedXml` constructor to customize the signature process:\n\n- `privateKey` - **[required]** a `Buffer` or pem encoded `String` containing your private key\n- `publicCert` - **[optional]** a `Buffer` or pem encoded `String` containing your public key\n- `signatureAlgorithm` - **[required]** one of the supported [signature algorithms](#signature-algorithms). Ex: `sign.signatureAlgorithm = \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\"`\n- `canonicalizationAlgorithm` - **[required]** one of the supported [canonicalization algorithms](#canonicalization-and-transformation-algorithms). Ex: `sign.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#WithComments\"`\n\nUse this code:\n\n```javascript\nvar SignedXml = require(\"xml-crypto\").SignedXml,\n  fs = require(\"fs\");\n\nvar xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\" + \"</library>\";\n\nvar sig = new SignedXml({ privateKey: fs.readFileSync(\"client.pem\") });\nsig.addReference({\n  xpath: \"//*[local-name(.)='book']\",\n  digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n  transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n});\nsig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\nsig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\nsig.computeSignature(xml);\nfs.writeFileSync(\"signed.xml\", sig.getSignedXml());\n```\n\nThe result will be:\n\n```xml\n<library>\n  <book Id=\"_0\">\n    <name>Harry Potter</name>\n  </book>\n  <Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">\n    <SignedInfo>\n      <CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" />\n      <SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\" />\n      <Reference URI=\"#_0\">\n        <Transforms>\n          <Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" />\n        </Transforms>\n        <DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" />\n        <DigestValue>cdiS43aFDQMnb3X8yaIUej3+z9Q=</DigestValue>\n      </Reference>\n    </SignedInfo>\n    <SignatureValue>vhWzpQyIYuncHUZV9W...[long base64 removed]...</SignatureValue>\n  </Signature>\n</library>\n```\n\nNote:\n\nIf you set the `publicCert` and the `getKeyInfoContent` properties, a `<KeyInfo></KeyInfo>` element with the public certificate will be generated in the signature:\n\n```xml\n<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">\n  <SignedInfo>\n    ...[signature info removed]...\n  </SignedInfo>\n  <SignatureValue>vhWzpQyIYuncHUZV9W...[long base64 removed]...</SignatureValue>\n  <KeyInfo>\n    <X509Data>\n      <X509Certificate>MIIGYjCCBJagACCBN...[long base64 removed]...</X509Certificate>\n    </X509Data>\n  </KeyInfo>\n</Signature>\n```\n\nFor `getKeyInfoContent`, a default implementation `SignedXml.getKeyInfoContent` is available.\n\nTo customize this see [customizing algorithms](#customizing-algorithms) for an example.\n\n## Verifying Xml documents\n\nWhen verifying a xml document you can pass the following options to the `SignedXml` constructor to customize the verify process:\n\n- `publicCert` - **[optional]** your certificate as a string, a string of multiple certs in PEM format, or a Buffer\n- `privateKey` - **[optional]** your private key as a string or a Buffer - used for verifying symmetrical signatures (HMAC)\n\nThe certificate that will be used to check the signature will first be determined by calling `this.getCertFromKeyInfo()`, which function you can customize as you see fit. If that returns `null`, then `publicCert` is used. If that is `null`, then `privateKey` is used (for symmetrical signing applications).\n\nExample:\n\n```javascript\nnew SignedXml({\n  publicCert: client_public_pem,\n  getCertFromKeyInfo: () => null,\n});\n```\n\nYou can use any dom parser you want in your code (or none, depending on your usage). This sample uses [xmldom](https://github.com/xmldom/xmldom), so you should install it first:\n\n```shell\nnpm install @xmldom/xmldom\n```\n\nExample:\n\n```javascript\nvar select = require(\"xml-crypto\").xpath,\n  dom = require(\"@xmldom/xmldom\").DOMParser,\n  SignedXml = require(\"xml-crypto\").SignedXml,\n  fs = require(\"fs\");\n\nvar xml = fs.readFileSync(\"signed.xml\").toString();\nvar doc = new dom().parseFromString(xml);\n\n// DO NOT attempt to parse whatever data object you have here in `doc`\n// and then use it to verify the signature. This can lead to security issues.\n// i.e. BAD: parseAssertion(doc),\n// good: see below\n\nvar signature = select(\n  doc,\n  \"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n)[0];\nvar sig = new SignedXml({ publicCert: fs.readFileSync(\"client_public.pem\") });\nsig.loadSignature(signature);\ntry {\n  var res = sig.checkSignature(xml);\n} catch (ex) {\n  console.log(ex);\n}\n```\n\nIn order to protect from some attacks we must check the content we want to use is the one that has been signed:\n\n```javascript\nif (!res) {\n  throw \"Invalid Signature\";\n}\n// good: The XML Signature has been verified, meaning some subset of XML is verified.\nvar signedBytes = sig.getSignedReferences();\n\nvar authenticatedDoc = new dom().parseFromString(signedBytes[0]); // Take the first signed reference\n// It is now safe to load SAML, obtain the assertion XML, or do whatever else is needed.\n// Be sure to only use authenticated data.\nlet signedAssertionNode = extractAssertion(authenticatedDoc);\nlet parsedAssertion = parseAssertion(signedAssertionNode);\n\nreturn parsedAssertion; // This the correctly verified signed Assertion\n\n// BAD example: DO not use the .getReferences() API.\n```\n\nNote:\n\nThe xml-crypto api requires you to supply it separately the xml signature (\"&lt;Signature&gt;...&lt;/Signature&gt;\", in loadSignature) and the signed xml (in checkSignature). The signed xml may or may not contain the signature in it, but you are still required to supply the signature separately.\n\n### Caring for Implicit transform\n\nIf you fail to verify signed XML, then one possible cause is that there are some hidden implicit transforms(#).  \n(#) Normalizing XML document to be verified. i.e. remove extra space within a tag, sorting attributes, importing namespace declared in ancestor nodes, etc.\n\nThe reason for these implicit transform might come from [complex xml signature specification](https://www.w3.org/TR/2002/REC-xmldsig-core-20020212),\nwhich makes XML developers confused and then leads to incorrect implementation for signing XML document.\n\nIf you keep failing verification, it is worth trying to guess such a hidden transform and specify it to the option as below:\n\n```javascript\nvar options = {\n  implicitTransforms: [\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"],\n  publicCert: fs.readFileSync(\"client_public.pem\"),\n};\nvar sig = new SignedXml(options);\nsig.loadSignature(signature);\nvar res = sig.checkSignature(xml);\n```\n\nYou might find it difficult to guess such transforms, but there are typical transforms you can try.\n\n- <http://www.w3.org/TR/2001/REC-xml-c14n-20010315>\n- <http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments>\n- <http://www.w3.org/2001/10/xml-exc-c14n#>\n- <http://www.w3.org/2001/10/xml-exc-c14n#WithComments>\n\n## API\n\n### xpath\n\nSee [xpath.js](https://github.com/yaronn/xpath.js) for usage. Note that this is actually using\n[another library](https://github.com/goto100/xpath) as the underlying implementation.\n\n### SignedXml\n\nThe `SignedXml` constructor provides an abstraction for sign and verify xml documents. The object is constructed using `new SignedXml(options?: SignedXmlOptions)` where the possible options are:\n\n- `idMode` - default `null` - if the value of `wssecurity` is passed it will create/validate id's with the ws-security namespace.\n- `idAttribute` - string - default `Id` or `ID` or `id` - the name of the attribute that contains the id of the element\n- `privateKey` - string or Buffer - default `null` - the private key to use for signing\n- `publicCert` - string or Buffer - default `null` - the public certificate to use for verifying\n- `signatureAlgorithm` - string - the signature algorithm to use\n- `canonicalizationAlgorithm` - string - default `undefined` - the canonicalization algorithm to use\n- `inclusiveNamespacesPrefixList` - string - default `null` - a list of namespace prefixes to include during canonicalization\n- `implicitTransforms` - string[] - default `[]` - a list of implicit transforms to use during verification\n- `keyInfoAttributes` - object - default `{}` - a hash of attributes and values `attrName: value` to add to the KeyInfo node\n- `getKeyInfoContent` - function - default `SignedXml.getKeyInfoContent` - a function that returns the content of the KeyInfo node\n- `getCertFromKeyInfo` - function - default `noop` - a function that returns the certificate from the `<KeyInfo />` node\n\n#### API\n\nA `SignedXml` object provides the following methods:\n\nTo sign xml documents:\n\n- `addReference({ xpath, transforms, digestAlgorithm, id, type })` - adds a reference to a xml element where:\n  - `xpath` - a string containing a XPath expression referencing a xml element\n  - `transforms` - an array of [transform algorithms](#canonicalization-and-transformation-algorithms), the referenced element will be transformed for each value in the array\n  - `digestAlgorithm` - one of the supported [hashing algorithms](#hashing-algorithms)\n  - `id` - an optional `Id` attribute to add to the reference element\n  - `type` - the optional `Type` attribute to add to the reference element (represented as a URI)\n- `computeSignature(xml, [options])` - compute the signature of the given xml where:\n  - `xml` - a string containing a xml document\n  - `options` - an object with the following properties:\n    - `prefix` - adds this value as a prefix for the generated signature tags\n    - `attrs` - a hash of attributes and values `attrName: value` to add to the signature root node\n    - `location` - customize the location of the signature, pass an object with a `reference` key which should contain a XPath expression to a reference node, an `action` key which should contain one of the following values: `append`, `prepend`, `before`, `after`\n    - `existingPrefixes` - A hash of prefixes and namespaces `prefix: namespace` that shouldn't be in the signature because they already exist in the xml\n- `getSignedXml()` - returns the original xml document with the signature in it, **must be called only after `computeSignature`**\n- `getSignatureXml()` - returns just the signature part, **must be called only after `computeSignature`**\n- `getOriginalXmlWithIds()` - returns the original xml with Id attributes added on relevant elements (required for validation), **must be called only after `computeSignature`**\n\nTo verify xml documents:\n\n- `loadSignature(signatureXml)` - loads the signature where:\n  - `signatureXml` - a string or node object (like an [xmldom](https://github.com/xmldom/xmldom) node) containing the xml representation of the signature\n- `checkSignature(xml)` - validates the given xml document and returns `true` if the validation was successful\n\n## Customizing Algorithms\n\nThe following sample shows how to sign a message using custom algorithms.\n\nFirst import some modules:\n\n```javascript\nvar SignedXml = require(\"xml-crypto\").SignedXml,\n  fs = require(\"fs\");\n```\n\nNow define the extension point you want to implement. You can choose one or more.\n\nTo determine the inclusion and contents of a `<KeyInfo />` element, the function\n`this.getKeyInfoContent()` is called. There is a default implementation of this. If you wish to change\nthis implementation, provide your own function assigned to the property `this.getKeyInfoContent`. If you prefer to use the default implementation, assign `SignedXml.getKeyInfoContent` to `this.getKeyInfoContent` If\nthere are no attributes and no contents to the `<KeyInfo />` element, it won't be included in the\ngenerated XML.\n\nTo specify custom attributes on `<KeyInfo />`, add the properties to the `.keyInfoAttributes` property.\n\nA custom hash algorithm is used to calculate digests. Implement it if you want a hash other than the built-in methods.\n\n```javascript\nfunction MyDigest() {\n  this.getHash = function (xml) {\n    return \"the base64 hash representation of the given xml string\";\n  };\n\n  this.getAlgorithmName = function () {\n    return \"http://myDigestAlgorithm\";\n  };\n}\n```\n\nA custom signing algorithm.\n\n```javascript\nfunction MySignatureAlgorithm() {\n  /*sign the given SignedInfo using the key. return base64 signature value*/\n  this.getSignature = function (signedInfo, privateKey) {\n    return \"signature of signedInfo as base64...\";\n  };\n\n  this.getAlgorithmName = function () {\n    return \"http://mySigningAlgorithm\";\n  };\n}\n```\n\nCustom transformation algorithm.\n\n```javascript\nfunction MyTransformation() {\n  /*given a node (from the xmldom module) return its canonical representation (as string)*/\n  this.process = function (node) {\n    //you should apply your transformation before returning\n    return node.toString();\n  };\n\n  this.getAlgorithmName = function () {\n    return \"http://myTransformation\";\n  };\n}\n```\n\nCustom canonicalization is actually the same as custom transformation. It is applied on the SignedInfo rather than on references.\n\n```javascript\nfunction MyCanonicalization() {\n  /*given a node (from the xmldom module) return its canonical representation (as string)*/\n  this.process = function (node) {\n    //you should apply your transformation before returning\n    return \"< x/>\";\n  };\n\n  this.getAlgorithmName = function () {\n    return \"http://myCanonicalization\";\n  };\n}\n```\n\nNow you need to register the new algorithms:\n\n```javascript\n/*register all the custom algorithms*/\n\nsignedXml.CanonicalizationAlgorithms[\"http://MyTransformation\"] = MyTransformation;\nsignedXml.CanonicalizationAlgorithms[\"http://MyCanonicalization\"] = MyCanonicalization;\nsignedXml.HashAlgorithms[\"http://myDigestAlgorithm\"] = MyDigest;\nsignedXml.SignatureAlgorithms[\"http://mySigningAlgorithm\"] = MySignatureAlgorithm;\n```\n\nNow do the signing. Note how we configure the signature to use the above algorithms:\n\n```javascript\nfunction signXml(xml, xpath, key, dest) {\n  var options = {\n    publicCert: fs.readFileSync(\"my_public_cert.pem\", \"latin1\"),\n    privateKey: fs.readFileSync(key),\n    /*configure the signature object to use the custom algorithms*/\n    signatureAlgorithm: \"http://mySignatureAlgorithm\",\n    canonicalizationAlgorithm: \"http://MyCanonicalization\",\n  };\n\n  var sig = new SignedXml(options);\n\n  sig.addReference({\n    xpath: \"//*[local-name(.)='x']\",\n    transforms: [\"http://MyTransformation\"],\n    digestAlgorithm: \"http://myDigestAlgorithm\",\n  });\n\n  sig.addReference({\n    xpath,\n    transforms: [\"http://MyTransformation\"],\n    digestAlgorithm: \"http://myDigestAlgorithm\",\n  });\n  sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n  sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n  sig.computeSignature(xml);\n  fs.writeFileSync(dest, sig.getSignedXml());\n}\n\nvar xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\";\n(\"</library>\");\n\nsignXml(xml, \"//*[local-name(.)='book']\", \"client.pem\", \"result.xml\");\n```\n\nYou can always look at the actual code as a sample.\n\n## Asynchronous signing and verification\n\nIf the private key is not stored locally, and you wish to use a signing server or Hardware Security Module (HSM) to sign documents, you can create a custom signing algorithm that uses an asynchronous callback.\n\n```javascript\nfunction AsyncSignatureAlgorithm() {\n  this.getSignature = function (signedInfo, privateKey, callback) {\n    var signer = crypto.createSign(\"RSA-SHA1\");\n    signer.update(signedInfo);\n    var res = signer.sign(privateKey, \"base64\");\n    //Do some asynchronous things here\n    callback(null, res);\n  };\n  this.getAlgorithmName = function () {\n    return \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n  };\n}\n\nvar sig = new SignedXml({ signatureAlgorithm: \"http://asyncSignatureAlgorithm\" });\nsig.SignatureAlgorithms[\"http://asyncSignatureAlgorithm\"] = AsyncSignatureAlgorithm;\nsig.signatureAlgorithm = \"http://asyncSignatureAlgorithm\";\nsig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\nsig.computeSignature(xml, opts, function (err) {\n  var signedResponse = sig.getSignedXml();\n});\n```\n\nThe function `sig.checkSignature` may also use a callback if asynchronous verification is needed.\n\n## X.509 / Key formats\n\nXml-Crypto internally relies on node's crypto module. This means pem encoded certificates are supported. So to sign an xml use key.pem that looks like this (only the beginning of the key content is shown):\n\n```text\n-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0...\n-----END PRIVATE KEY-----\n```\n\nAnd for verification use key_public.pem:\n\n```text\n-----BEGIN CERTIFICATE-----\nMIIBxDCCAW6gAwIBAgIQxUSX...\n-----END CERTIFICATE-----\n```\n\n### Converting .pfx certificates to pem\n\nIf you have .pfx certificates you can convert them to .pem using [openssl](http://www.openssl.org/):\n\n```shell\nopenssl pkcs12 -in c:\\certs\\yourcert.pfx -out c:\\certs\\cag.pem\n```\n\nThen you could use the result as is for the purpose of signing. For the purpose of validation open the resulting .pem with a text editor and copy from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE----- (including) to a new text file and save it as .pem.\n\n## Examples\n\n### how to sign a root node (_coming soon_)\n\n### how to add a prefix for the signature\n\nUse the `prefix` option when calling `computeSignature` to add a prefix to the signature.\n\n```javascript\nvar SignedXml = require(\"xml-crypto\").SignedXml,\n  fs = require(\"fs\");\n\nvar xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\" + \"</library>\";\n\nvar sig = new SignedXml({ privateKey: fs.readFileSync(\"client.pem\") });\nsig.addReference({\n  xpath: \"//*[local-name(.)='book']\",\n  digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n  transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n});\nsig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\nsig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\nsig.computeSignature(xml, {\n  prefix: \"ds\",\n});\n```\n\n### how to specify the location of the signature\n\nUse the `location` option when calling `computeSignature` to move the signature around.\nSet `action` to one of the following:\n\n- append(default) - append to the end of the xml document\n- prepend - prepend to the xml document\n- before - prepend to a specific node (use the `referenceNode` property)\n- after - append to specific node (use the `referenceNode` property)\n\n```javascript\nconst SignedXml = require(\"xml-crypto\").SignedXml;\nconst fs = require(\"fs\");\n\nconst xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\" + \"</library>\";\n\nconst sig = new SignedXml({ privateKey: fs.readFileSync(\"client.pem\") });\nsig.addReference({\n  xpath: \"//*[local-name(.)='book']\",\n  digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n  transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n});\nsig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\nsig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\nsig.computeSignature(xml, {\n  location: { reference: \"//*[local-name(.)='book']\", action: \"after\" }, // This will place the signature after the book element\n});\n```\n\n### How to add custom Objects to the signature\n\nUse the `objects` option when creating a SignedXml instance to add custom Objects to the signature.\n\n```javascript\nconst SignedXml = require(\"xml-crypto\").SignedXml;\nconst fs = require(\"fs\");\n\nconst xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\" + \"</library>\";\n\nconst sig = new SignedXml({\n  privateKey: fs.readFileSync(\"client.pem\"),\n  canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n  signatureAlgorithm: \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\",\n  objects: [\n    {\n      content: \"<TestObject>Test data in Object</TestObject>\",\n      attributes: {\n        Id: \"Object1\",\n        MimeType: \"text/xml\",\n      },\n    },\n  ],\n});\n\n// Add a reference to the Object element\nsig.addReference({\n  xpath: \"//*[@Id='Object1']\",\n  digestAlgorithm: \"http://www.w3.org/2001/04/xmlenc#sha256\",\n  transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n});\n\nsig.computeSignature(xml);\nfs.writeFileSync(\"signed.xml\", sig.getSignedXml());\n```\n\n### more examples (_coming soon_)\n\n## Development\n\nThe testing framework we use is [Mocha](https://github.com/mochajs/mocha) with [Chai](https://github.com/chaijs/chai) as the assertion framework.\n\nTo run tests use:\n\n```shell\nnpm test\n```\n\n## Sponsors\n\n![Short-io logo](https://github.com/Short-io.png?size=30) [Short-io](https://github.com/Short-io)\n\n![RideAmigosCorp logo](https://github.com/RideAmigosCorp.png?size=30) [RideAmigosCorp](https://github.com/RideAmigosCorp)\n\n## License\n\nThis project is licensed under the [MIT License](http://opensource.org/licenses/MIT). See the [LICENSE](LICENSE) file for more info.\n"
  },
  {
    "path": "example/client.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL4vpoH3H3byehjj\n7RAGxefGRATiq4mXtzc9Q91W7uT0DTaFEbjzVch9aGsNjmLs4QHsoZbuoUmi0st4\nx5z9SQpTAKC/dW8muzacT3E7dJJYh03MAO6RiH4LG34VRTq1SQN6qDt2rCK85eG4\n5NHI4jceptZNu6Zot1zyO5/PYuFpAgMBAAECgYAhspeyF3M/xB7WIixy1oBiXMLY\nisESFAumgfhwU2LotkVRD6rgNl1QtMe3kCNWa9pCWQcYkxeI0IzA+JmFu2shVvoR\noL7eV4VCe1Af33z24E46+cY5grxNhHt/LyCnZKcitvCcrzXExUc5n6KngX0mMKgk\nW7skZDwsnKzhyUV8wQJBAN2bQMeASQVOqdfqBdFgC/NPnKY2cuDi6h659QN1l+kg\nX3ywdZ7KKftJo1G9l45SN9YpkyEd9zEO6PMFaufJvZUCQQDbtAWxk0i8BT3UTNWC\nT/9bUQROPcGZagwwnRFByX7gpmfkf1ImIvbWVXSpX68/IjbjSkTw1nj/Yj1NwFZ0\nnxeFAkEAzPhRpXVBlPgaXkvlz7AfvY+wW4hXHyyi0YK8XdPBi25XA5SPZiylQfjt\nZ6iN6qSfYqYXoPT/c0/QJR+orvVJNQJBANhRPNXljVTK2GDCseoXd/ZiI5ohxg+W\nUaA/1fDvQsRQM7TQA4NXI7BO/YmSk4rW1jIeOxjiIspY4MFAIh+7UL0CQFL6zTg6\nwfeMlEZzvgqwCGoLuvTnqtvyg45z7pfcrg2cHdgCXIy9kErcjwGiu6BOevEA1qTW\nRk+bv0tknWvcz/s=\n-----END PRIVATE KEY-----"
  },
  {
    "path": "example/client_public.pem",
    "content": "-----BEGIN CERTIFICATE-----\r\nMIIBxDCCAW6gAwIBAgIQxUSXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BAQQFADAW\r\nMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ3NTlaFw0zOTEyMzEy\r\nMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0Q2xpZW50MIGfMA0GCSqG\r\nSIb3DQEBAQUAA4GNADCBiQKBgQC+L6aB9x928noY4+0QBsXnxkQE4quJl7c3PUPd\r\nVu7k9A02hRG481XIfWhrDY5i7OEB7KGW7qFJotLLeMec/UkKUwCgv3VvJrs2nE9x\r\nO3SSWIdNzADukYh+Cxt+FUU6tUkDeqg7dqwivOXhuOTRyOI3HqbWTbumaLdc8juf\r\nz2LhaQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEU\r\nMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcN\r\nAQEEBQADQQAfIbnMPVYkNNfX1tG1F+qfLhHwJdfDUZuPyRPucWF5qkh6sSdWVBY5\r\nsT/txBnVJGziyO8DPYdu2fPMER8ajJfl\r\n-----END CERTIFICATE-----"
  },
  {
    "path": "example/example.js",
    "content": "/* eslint-disable no-console */\n\nconst select = require(\"xml-crypto\").xpath;\nconst dom = require(\"@xmldom/xmldom\").DOMParser;\nconst SignedXml = require(\"xml-crypto\").SignedXml;\nconst fs = require(\"fs\");\n\nfunction signXml(xml, xpath, key, dest) {\n  const sig = new SignedXml();\n  sig.privateKey = fs.readFileSync(key);\n  sig.addReference(xpath);\n  sig.computeSignature(xml);\n  fs.writeFileSync(dest, sig.getSignedXml());\n}\n\nfunction validateXml(xml, key) {\n  const doc = new dom().parseFromString(xml);\n  const signature = select(\n    \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n    doc,\n  )[0];\n  const sig = new SignedXml();\n  sig.publicCert = key;\n  sig.loadSignature(signature.toString());\n  const res = sig.checkSignature(xml);\n  if (!res) {\n    console.log(sig.validationErrors);\n  }\n  return res;\n}\n\nconst xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\" + \"</library>\";\n\n//sign an xml document\nsignXml(xml, \"//*[local-name(.)='book']\", \"client.pem\", \"result.xml\");\n\nconsole.log(\"xml signed successfully\");\n\nconst signedXml = fs.readFileSync(\"result.xml\").toString();\nconsole.log(\"validating signature...\");\n\n//validate an xml document\nif (validateXml(signedXml, \"client_public.pem\")) {\n  console.log(\"signature is valid\");\n} else {\n  console.log(\"signature not valid\");\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"xml-crypto\",\n  \"version\": \"6.0.0\",\n  \"private\": false,\n  \"description\": \"Xml digital signature and encryption library for Node.js\",\n  \"keywords\": [\n    \"xml\",\n    \"digital signature\",\n    \"xml encryption\",\n    \"x.509 certificate\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/node-saml/xml-crypto.git\"\n  },\n  \"license\": \"MIT\",\n  \"author\": \"Yaron Naveh <yaronn01@gmail.com> (http://webservices20.blogspot.com/)\",\n  \"contributors\": [\n    \"LoneRifle <LoneRifle@users.noreply.github.com>\",\n    \"Chris Barth <chrisjbarth@hotmail.com>\"\n  ],\n  \"main\": \"./lib\",\n  \"files\": [\n    \"lib\",\n    \"LICENSE\",\n    \"README.md\"\n  ],\n  \"scripts\": {\n    \"build\": \"npx tsc\",\n    \"changelog\": \"gren changelog --override --generate\",\n    \"lint\": \"eslint \\\"{src,test}/*.ts\\\" --cache && npm run prettier-check\",\n    \"lint:fix\": \"eslint --fix \\\"{src,test}/*.ts\\\" && npm run prettier-format\",\n    \"prepare\": \"tsc\",\n    \"prettier-check\": \"prettier --config .prettierrc.json --check .\",\n    \"prettier-format\": \"prettier --config .prettierrc.json --write .\",\n    \"prerelease\": \"git clean -xfd && npm ci && npm test\",\n    \"release\": \"release-it\",\n    \"test\": \"nyc mocha\"\n  },\n  \"dependencies\": {\n    \"@xmldom/is-dom-node\": \"^1.0.1\",\n    \"@xmldom/xmldom\": \"^0.8.10\",\n    \"xpath\": \"^0.0.33\"\n  },\n  \"devDependencies\": {\n    \"@cjbarth/github-release-notes\": \"^4.2.0\",\n    \"@istanbuljs/nyc-config-typescript\": \"^1.0.2\",\n    \"@prettier/plugin-xml\": \"^3.2.2\",\n    \"@types/chai\": \"^4.3.11\",\n    \"@types/mocha\": \"^10.0.6\",\n    \"@types/node\": \"^16.18.69\",\n    \"@typescript-eslint/eslint-plugin\": \"^6.18.1\",\n    \"@typescript-eslint/parser\": \"^6.18.1\",\n    \"chai\": \"^4.3.10\",\n    \"choma\": \"^1.2.1\",\n    \"ejs\": \"^3.1.9\",\n    \"eslint\": \"^8.56.0\",\n    \"eslint-config-prettier\": \"^9.0.0\",\n    \"eslint-plugin-deprecation\": \"^2.0.0\",\n    \"lcov\": \"^1.16.0\",\n    \"mocha\": \"^10.2.0\",\n    \"nyc\": \"^15.1.0\",\n    \"prettier\": \"^3.1.0\",\n    \"prettier-plugin-packagejson\": \"^2.4.6\",\n    \"release-it\": \"^16.3.0\",\n    \"source-map-support\": \"^0.5.21\",\n    \"ts-node\": \"^10.9.1\",\n    \"typescript\": \"^5.3.2\"\n  },\n  \"engines\": {\n    \"node\": \">=16\"\n  }\n}\n"
  },
  {
    "path": "src/c14n-canonicalization.ts",
    "content": "import type {\n  CanonicalizationOrTransformationAlgorithm,\n  CanonicalizationOrTransformationAlgorithmProcessOptions,\n  NamespacePrefix,\n  RenderedNamespace,\n} from \"./types\";\nimport * as utils from \"./utils\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\nexport class C14nCanonicalization implements CanonicalizationOrTransformationAlgorithm {\n  protected includeComments = false;\n\n  constructor() {\n    this.includeComments = false;\n  }\n\n  attrCompare(a, b) {\n    if (!a.namespaceURI && b.namespaceURI) {\n      return -1;\n    }\n    if (!b.namespaceURI && a.namespaceURI) {\n      return 1;\n    }\n\n    const left = a.namespaceURI + a.localName;\n    const right = b.namespaceURI + b.localName;\n\n    if (left === right) {\n      return 0;\n    } else if (left < right) {\n      return -1;\n    } else {\n      return 1;\n    }\n  }\n\n  nsCompare(a, b) {\n    const attr1 = a.prefix;\n    const attr2 = b.prefix;\n    if (attr1 === attr2) {\n      return 0;\n    }\n    return attr1.localeCompare(attr2);\n  }\n\n  renderAttrs(node) {\n    let i;\n    let attr;\n    const attrListToRender: Attr[] = [];\n\n    if (isDomNode.isCommentNode(node)) {\n      return this.renderComment(node);\n    }\n\n    if (node.attributes) {\n      for (i = 0; i < node.attributes.length; ++i) {\n        attr = node.attributes[i];\n        //ignore namespace definition attributes\n        if (attr.name.indexOf(\"xmlns\") === 0) {\n          continue;\n        }\n        attrListToRender.push(attr);\n      }\n    }\n\n    attrListToRender.sort(this.attrCompare);\n\n    const res = attrListToRender.map((attr) => {\n      return ` ${attr.name}=\"${utils.encodeSpecialCharactersInAttribute(attr.value)}\"`;\n    });\n\n    return res.join(\"\");\n  }\n\n  /**\n   * Create the string of all namespace declarations that should appear on this element\n   *\n   * @param node The node we now render\n   * @param prefixesInScope The prefixes defined on this node parents which are a part of the output set\n   * @param defaultNs The current default namespace\n   * @param defaultNsForPrefix\n   * @param ancestorNamespaces Import ancestor namespaces if it is specified\n   * @api private\n   */\n  renderNs(\n    node: Element,\n    prefixesInScope: string[],\n    defaultNs: string,\n    defaultNsForPrefix: string,\n    ancestorNamespaces: NamespacePrefix[],\n  ): RenderedNamespace {\n    let i;\n    let attr;\n    const res: string[] = [];\n    let newDefaultNs = defaultNs;\n    const nsListToRender: { prefix: string; namespaceURI: string }[] = [];\n    const currNs = node.namespaceURI || \"\";\n\n    //handle the namespace of the node itself\n    if (node.prefix) {\n      if (prefixesInScope.indexOf(node.prefix) === -1) {\n        nsListToRender.push({\n          prefix: node.prefix,\n          namespaceURI: node.namespaceURI || defaultNsForPrefix[node.prefix],\n        });\n        prefixesInScope.push(node.prefix);\n      }\n    } else if (defaultNs !== currNs) {\n      //new default ns\n      newDefaultNs = node.namespaceURI || \"\";\n      res.push(' xmlns=\"', newDefaultNs, '\"');\n    }\n\n    //handle the attributes namespace\n    if (node.attributes) {\n      for (i = 0; i < node.attributes.length; ++i) {\n        attr = node.attributes[i];\n\n        //handle all prefixed attributes that are included in the prefix list and where\n        //the prefix is not defined already. New prefixes can only be defined by `xmlns:`.\n        if (attr.prefix === \"xmlns\" && prefixesInScope.indexOf(attr.localName) === -1) {\n          nsListToRender.push({ prefix: attr.localName, namespaceURI: attr.value });\n          prefixesInScope.push(attr.localName);\n        }\n\n        //handle all prefixed attributes that are not xmlns definitions and where\n        //the prefix is not defined already\n        if (\n          attr.prefix &&\n          prefixesInScope.indexOf(attr.prefix) === -1 &&\n          attr.prefix !== \"xmlns\" &&\n          attr.prefix !== \"xml\"\n        ) {\n          nsListToRender.push({ prefix: attr.prefix, namespaceURI: attr.namespaceURI });\n          prefixesInScope.push(attr.prefix);\n        }\n      }\n    }\n\n    if (utils.isArrayHasLength(ancestorNamespaces)) {\n      // Remove namespaces which are already present in nsListToRender\n      for (const ancestorNamespace of ancestorNamespaces) {\n        let alreadyListed = false;\n        for (const nsToRender of nsListToRender) {\n          if (\n            nsToRender.prefix === ancestorNamespace.prefix &&\n            nsToRender.namespaceURI === ancestorNamespace.namespaceURI\n          ) {\n            alreadyListed = true;\n          }\n        }\n\n        if (!alreadyListed) {\n          nsListToRender.push(ancestorNamespace);\n        }\n      }\n    }\n\n    nsListToRender.sort(this.nsCompare);\n\n    //render namespaces\n    res.push(\n      ...nsListToRender.map((attr) => {\n        if (attr.prefix) {\n          return ` xmlns:${attr.prefix}=\"${attr.namespaceURI}\"`;\n        }\n        return ` xmlns=\"${attr.namespaceURI}\"`;\n      }),\n    );\n\n    return { rendered: res.join(\"\"), newDefaultNs };\n  }\n\n  /**\n   * @param node Node\n   */\n  processInner(node, prefixesInScope, defaultNs, defaultNsForPrefix, ancestorNamespaces) {\n    if (isDomNode.isCommentNode(node)) {\n      return this.renderComment(node);\n    }\n    if (node.data) {\n      return utils.encodeSpecialCharactersInText(node.data);\n    }\n\n    if (isDomNode.isElementNode(node)) {\n      let i;\n      let pfxCopy;\n      const ns = this.renderNs(\n        node,\n        prefixesInScope,\n        defaultNs,\n        defaultNsForPrefix,\n        ancestorNamespaces,\n      );\n      const res = [\"<\", node.tagName, ns.rendered, this.renderAttrs(node), \">\"];\n\n      for (i = 0; i < node.childNodes.length; ++i) {\n        pfxCopy = prefixesInScope.slice(0);\n        res.push(\n          this.processInner(node.childNodes[i], pfxCopy, ns.newDefaultNs, defaultNsForPrefix, []),\n        );\n      }\n\n      res.push(\"</\", node.tagName, \">\");\n      return res.join(\"\");\n    }\n\n    throw new Error(`Unable to canonicalize node type: ${node.nodeType}`);\n  }\n\n  // Thanks to deoxxa/xml-c14n for comment renderer\n  renderComment(node: Comment) {\n    if (!this.includeComments) {\n      return \"\";\n    }\n\n    const isOutsideDocument = node.ownerDocument === node.parentNode;\n    let isBeforeDocument = false;\n    let isAfterDocument = false;\n\n    if (isOutsideDocument) {\n      let nextNode: ChildNode | null = node;\n      let previousNode: ChildNode | null = node;\n\n      while (nextNode !== null) {\n        if (nextNode === node.ownerDocument.documentElement) {\n          isBeforeDocument = true;\n          break;\n        }\n\n        nextNode = nextNode.nextSibling;\n      }\n\n      while (previousNode !== null) {\n        if (previousNode === node.ownerDocument.documentElement) {\n          isAfterDocument = true;\n          break;\n        }\n\n        previousNode = previousNode.previousSibling;\n      }\n    }\n\n    const afterDocument = isAfterDocument ? \"\\n\" : \"\";\n    const beforeDocument = isBeforeDocument ? \"\\n\" : \"\";\n    const encodedText = utils.encodeSpecialCharactersInText(node.data);\n\n    return `${afterDocument}<!--${encodedText}-->${beforeDocument}`;\n  }\n\n  /**\n   * Perform canonicalization of the given node\n   *\n   * @param node\n   * @api public\n   */\n  process(node: Node, options: CanonicalizationOrTransformationAlgorithmProcessOptions): string {\n    options = options || {};\n    const defaultNs = options.defaultNs || \"\";\n    const defaultNsForPrefix = options.defaultNsForPrefix || {};\n    const ancestorNamespaces = options.ancestorNamespaces || [];\n\n    const prefixesInScope: string[] = [];\n    for (let i = 0; i < ancestorNamespaces.length; i++) {\n      prefixesInScope.push(ancestorNamespaces[i].prefix);\n    }\n\n    const res = this.processInner(\n      node,\n      prefixesInScope,\n      defaultNs,\n      defaultNsForPrefix,\n      ancestorNamespaces,\n    );\n    return res;\n  }\n\n  getAlgorithmName() {\n    return \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\";\n  }\n}\n\n/**\n * Add c14n#WithComments here (very simple subclass)\n */\nexport class C14nCanonicalizationWithComments extends C14nCanonicalization {\n  constructor() {\n    super();\n    this.includeComments = true;\n  }\n\n  getAlgorithmName() {\n    return \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\";\n  }\n}\n"
  },
  {
    "path": "src/enveloped-signature.ts",
    "content": "import * as xpath from \"xpath\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\nimport type {\n  CanonicalizationOrTransformationAlgorithm,\n  CanonicalizationOrTransformationAlgorithmProcessOptions,\n  CanonicalizationOrTransformAlgorithmType,\n} from \"./types\";\n\nexport class EnvelopedSignature implements CanonicalizationOrTransformationAlgorithm {\n  protected includeComments = false;\n\n  constructor() {\n    this.includeComments = false;\n  }\n\n  process(node: Node, options: CanonicalizationOrTransformationAlgorithmProcessOptions): Node {\n    if (null == options.signatureNode) {\n      const signature = xpath.select1(\n        \"./*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n        node,\n      );\n      if (isDomNode.isNodeLike(signature) && signature.parentNode) {\n        signature.parentNode.removeChild(signature);\n      }\n      return node;\n    }\n    const signatureNode = options.signatureNode;\n    const expectedSignatureValue = xpath.select1(\n      \".//*[local-name(.)='SignatureValue']/text()\",\n      signatureNode,\n    );\n    if (isDomNode.isTextNode(expectedSignatureValue)) {\n      const expectedSignatureValueData = expectedSignatureValue.data;\n\n      const signatures = xpath.select(\n        \".//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n        node,\n      );\n      for (const nodeSignature of Array.isArray(signatures) ? signatures : []) {\n        const signatureValue = xpath.select1(\n          \".//*[local-name(.)='SignatureValue']/text()\",\n          nodeSignature,\n        );\n        if (isDomNode.isTextNode(signatureValue)) {\n          const signatureValueData = signatureValue.data;\n          if (expectedSignatureValueData === signatureValueData) {\n            if (nodeSignature.parentNode) {\n              nodeSignature.parentNode.removeChild(nodeSignature);\n            }\n          }\n        }\n      }\n    }\n    return node;\n  }\n\n  getAlgorithmName(): CanonicalizationOrTransformAlgorithmType {\n    return \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\";\n  }\n}\n"
  },
  {
    "path": "src/exclusive-canonicalization.ts",
    "content": "import type {\n  CanonicalizationOrTransformationAlgorithm,\n  CanonicalizationOrTransformationAlgorithmProcessOptions,\n  NamespacePrefix,\n} from \"./types\";\nimport * as utils from \"./utils\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\nfunction isPrefixInScope(prefixesInScope, prefix, namespaceURI) {\n  let ret = false;\n  prefixesInScope.forEach(function (pf) {\n    if (pf.prefix === prefix && pf.namespaceURI === namespaceURI) {\n      ret = true;\n    }\n  });\n\n  return ret;\n}\n\nexport class ExclusiveCanonicalization implements CanonicalizationOrTransformationAlgorithm {\n  protected includeComments = false;\n\n  constructor() {\n    this.includeComments = false;\n  }\n\n  attrCompare(a, b) {\n    if (!a.namespaceURI && b.namespaceURI) {\n      return -1;\n    }\n    if (!b.namespaceURI && a.namespaceURI) {\n      return 1;\n    }\n\n    const left = a.namespaceURI + a.localName;\n    const right = b.namespaceURI + b.localName;\n\n    if (left === right) {\n      return 0;\n    } else if (left < right) {\n      return -1;\n    } else {\n      return 1;\n    }\n  }\n\n  nsCompare(a, b) {\n    const attr1 = a.prefix;\n    const attr2 = b.prefix;\n    if (attr1 === attr2) {\n      return 0;\n    }\n    return attr1.localeCompare(attr2);\n  }\n\n  renderAttrs(node) {\n    let i;\n    let attr;\n    const res: string[] = [];\n    const attrListToRender: Attr[] = [];\n\n    if (isDomNode.isCommentNode(node)) {\n      return this.renderComment(node);\n    }\n\n    if (node.attributes) {\n      for (i = 0; i < node.attributes.length; ++i) {\n        attr = node.attributes[i];\n        //ignore namespace definition attributes\n        if (attr.name.indexOf(\"xmlns\") === 0) {\n          continue;\n        }\n        attrListToRender.push(attr);\n      }\n    }\n\n    attrListToRender.sort(this.attrCompare);\n\n    for (attr of attrListToRender) {\n      res.push(\" \", attr.name, '=\"', utils.encodeSpecialCharactersInAttribute(attr.value), '\"');\n    }\n\n    return res.join(\"\");\n  }\n\n  /**\n   * Create the string of all namespace declarations that should appear on this element\n   *\n   * @param {Node} node. The node we now render\n   * @param {Array} prefixesInScope. The prefixes defined on this node\n   *                parents which are a part of the output set\n   * @param {String} defaultNs. The current default namespace\n   * @return {String}\n   * @api private\n   */\n  renderNs(\n    node,\n    prefixesInScope,\n    defaultNs,\n    defaultNsForPrefix,\n    inclusiveNamespacesPrefixList: string[],\n  ) {\n    let i;\n    let attr;\n    const res: string[] = [];\n    let newDefaultNs = defaultNs;\n    const nsListToRender: NamespacePrefix[] = [];\n    const currNs = node.namespaceURI || \"\";\n\n    //handle the namespaceof the node itself\n    if (node.prefix) {\n      if (\n        !isPrefixInScope(\n          prefixesInScope,\n          node.prefix,\n          node.namespaceURI || defaultNsForPrefix[node.prefix],\n        )\n      ) {\n        nsListToRender.push({\n          prefix: node.prefix,\n          namespaceURI: node.namespaceURI || defaultNsForPrefix[node.prefix],\n        });\n        prefixesInScope.push({\n          prefix: node.prefix,\n          namespaceURI: node.namespaceURI || defaultNsForPrefix[node.prefix],\n        });\n      }\n    } else if (defaultNs !== currNs) {\n      //new default ns\n      newDefaultNs = node.namespaceURI;\n      res.push(' xmlns=\"', newDefaultNs, '\"');\n    }\n\n    //handle the attributes namespace\n    if (node.attributes) {\n      for (i = 0; i < node.attributes.length; ++i) {\n        attr = node.attributes[i];\n\n        //handle all prefixed attributes that are included in the prefix list and where\n        //the prefix is not defined already\n        if (\n          attr.prefix &&\n          !isPrefixInScope(prefixesInScope, attr.localName, attr.value) &&\n          inclusiveNamespacesPrefixList.indexOf(attr.localName) >= 0\n        ) {\n          nsListToRender.push({ prefix: attr.localName, namespaceURI: attr.value });\n          prefixesInScope.push({ prefix: attr.localName, namespaceURI: attr.value });\n        }\n\n        //handle all prefixed attributes that are not xmlns definitions and where\n        //the prefix is not defined already\n        if (\n          attr.prefix &&\n          !isPrefixInScope(prefixesInScope, attr.prefix, attr.namespaceURI) &&\n          attr.prefix !== \"xmlns\" &&\n          attr.prefix !== \"xml\"\n        ) {\n          nsListToRender.push({ prefix: attr.prefix, namespaceURI: attr.namespaceURI });\n          prefixesInScope.push({ prefix: attr.prefix, namespaceURI: attr.namespaceURI });\n        }\n      }\n    }\n\n    nsListToRender.sort(this.nsCompare);\n\n    //render namespaces\n    for (const p of nsListToRender) {\n      res.push(\" xmlns:\", p.prefix, '=\"', p.namespaceURI, '\"');\n    }\n\n    return { rendered: res.join(\"\"), newDefaultNs: newDefaultNs };\n  }\n\n  /**\n   * @param node Node\n   */\n  processInner(\n    node,\n    prefixesInScope,\n    defaultNs,\n    defaultNsForPrefix,\n    inclusiveNamespacesPrefixList: string[],\n  ) {\n    if (isDomNode.isCommentNode(node)) {\n      return this.renderComment(node);\n    }\n    if (node.data) {\n      return utils.encodeSpecialCharactersInText(node.data);\n    }\n\n    if (isDomNode.isElementNode(node)) {\n      let i;\n      let pfxCopy;\n      const ns = this.renderNs(\n        node,\n        prefixesInScope,\n        defaultNs,\n        defaultNsForPrefix,\n        inclusiveNamespacesPrefixList,\n      );\n      const res = [\"<\", node.tagName, ns.rendered, this.renderAttrs(node), \">\"];\n\n      for (i = 0; i < node.childNodes.length; ++i) {\n        pfxCopy = prefixesInScope.slice(0);\n        res.push(\n          this.processInner(\n            node.childNodes[i],\n            pfxCopy,\n            ns.newDefaultNs,\n            defaultNsForPrefix,\n            inclusiveNamespacesPrefixList,\n          ),\n        );\n      }\n\n      res.push(\"</\", node.tagName, \">\");\n      return res.join(\"\");\n    }\n\n    throw new Error(`Unable to exclusive canonicalize node type: ${node.nodeType}`);\n  }\n\n  // Thanks to deoxxa/xml-c14n for comment renderer\n  renderComment(node: Comment) {\n    if (!this.includeComments) {\n      return \"\";\n    }\n\n    const isOutsideDocument = node.ownerDocument === node.parentNode;\n    let isBeforeDocument = false;\n    let isAfterDocument = false;\n\n    if (isOutsideDocument) {\n      let nextNode: ChildNode | null = node;\n      let previousNode: ChildNode | null = node;\n\n      while (nextNode != null) {\n        if (nextNode === node.ownerDocument.documentElement) {\n          isBeforeDocument = true;\n          break;\n        }\n\n        nextNode = nextNode.nextSibling;\n      }\n\n      while (previousNode != null) {\n        if (previousNode === node.ownerDocument.documentElement) {\n          isAfterDocument = true;\n          break;\n        }\n\n        previousNode = previousNode.previousSibling;\n      }\n    }\n\n    const afterDocument = isAfterDocument ? \"\\n\" : \"\";\n    const beforeDocument = isBeforeDocument ? \"\\n\" : \"\";\n    const encodedText = utils.encodeSpecialCharactersInText(node.data);\n\n    return `${afterDocument}<!--${encodedText}-->${beforeDocument}`;\n  }\n\n  /**\n   * Perform canonicalization of the given element node\n   *\n   * @api public\n   */\n  process(elem: Element, options: CanonicalizationOrTransformationAlgorithmProcessOptions): string {\n    options = options || {};\n    let inclusiveNamespacesPrefixList = options.inclusiveNamespacesPrefixList || [];\n    const defaultNs = options.defaultNs || \"\";\n    const defaultNsForPrefix = options.defaultNsForPrefix || {};\n    const ancestorNamespaces = options.ancestorNamespaces || [];\n\n    /**\n     * If the inclusiveNamespacesPrefixList has not been explicitly provided then look it up in CanonicalizationMethod/InclusiveNamespaces\n     */\n    if (!utils.isArrayHasLength(inclusiveNamespacesPrefixList)) {\n      const CanonicalizationMethod = utils.findChildren(elem, \"CanonicalizationMethod\");\n      if (CanonicalizationMethod.length !== 0) {\n        const inclusiveNamespaces = utils.findChildren(\n          CanonicalizationMethod[0],\n          \"InclusiveNamespaces\",\n        );\n        if (inclusiveNamespaces.length !== 0) {\n          inclusiveNamespacesPrefixList = (\n            inclusiveNamespaces[0].getAttribute(\"PrefixList\") || \"\"\n          ).split(\" \");\n        }\n      }\n    }\n\n    /**\n     * If you have a PrefixList then use it and the ancestors to add the necessary namespaces\n     */\n    if (utils.isArrayHasLength(inclusiveNamespacesPrefixList)) {\n      inclusiveNamespacesPrefixList.forEach(function (prefix) {\n        if (ancestorNamespaces) {\n          ancestorNamespaces.forEach(function (ancestorNamespace) {\n            if (prefix === ancestorNamespace.prefix) {\n              elem.setAttributeNS(\n                \"http://www.w3.org/2000/xmlns/\",\n                `xmlns:${prefix}`,\n                ancestorNamespace.namespaceURI,\n              );\n            }\n          });\n        }\n      });\n    }\n\n    const res = this.processInner(\n      elem,\n      [],\n      defaultNs,\n      defaultNsForPrefix,\n      inclusiveNamespacesPrefixList,\n    );\n    return res;\n  }\n\n  getAlgorithmName() {\n    return \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n  }\n}\n\nexport class ExclusiveCanonicalizationWithComments extends ExclusiveCanonicalization {\n  constructor() {\n    super();\n    this.includeComments = true;\n  }\n\n  getAlgorithmName() {\n    return \"http://www.w3.org/2001/10/xml-exc-c14n#WithComments\";\n  }\n}\n"
  },
  {
    "path": "src/hash-algorithms.ts",
    "content": "import * as crypto from \"crypto\";\nimport type { HashAlgorithm } from \"./types\";\n\nexport class Sha1 implements HashAlgorithm {\n  getHash = function (xml) {\n    const shasum = crypto.createHash(\"sha1\");\n    shasum.update(xml, \"utf8\");\n    const res = shasum.digest(\"base64\");\n    return res;\n  };\n\n  getAlgorithmName = function () {\n    return \"http://www.w3.org/2000/09/xmldsig#sha1\";\n  };\n}\n\nexport class Sha256 implements HashAlgorithm {\n  getHash = function (xml) {\n    const shasum = crypto.createHash(\"sha256\");\n    shasum.update(xml, \"utf8\");\n    const res = shasum.digest(\"base64\");\n    return res;\n  };\n\n  getAlgorithmName = function () {\n    return \"http://www.w3.org/2001/04/xmlenc#sha256\";\n  };\n}\n\nexport class Sha512 implements HashAlgorithm {\n  getHash = function (xml) {\n    const shasum = crypto.createHash(\"sha512\");\n    shasum.update(xml, \"utf8\");\n    const res = shasum.digest(\"base64\");\n    return res;\n  };\n\n  getAlgorithmName = function () {\n    return \"http://www.w3.org/2001/04/xmlenc#sha512\";\n  };\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "export { C14nCanonicalization, C14nCanonicalizationWithComments } from \"./c14n-canonicalization\";\nexport {\n  ExclusiveCanonicalization,\n  ExclusiveCanonicalizationWithComments,\n} from \"./exclusive-canonicalization\";\nexport { SignedXml } from \"./signed-xml\";\nexport * from \"./types\";\nexport * from \"./utils\";\n"
  },
  {
    "path": "src/signature-algorithms.ts",
    "content": "import * as crypto from \"crypto\";\nimport { type SignatureAlgorithm, createOptionalCallbackFunction } from \"./types\";\n\nexport class RsaSha1 implements SignatureAlgorithm {\n  getSignature = createOptionalCallbackFunction(\n    (signedInfo: crypto.BinaryLike, privateKey: crypto.KeyLike): string => {\n      const signer = crypto.createSign(\"RSA-SHA1\");\n      signer.update(signedInfo);\n      const res = signer.sign(privateKey, \"base64\");\n\n      return res;\n    },\n  );\n\n  verifySignature = createOptionalCallbackFunction(\n    (material: string, key: crypto.KeyLike, signatureValue: string): boolean => {\n      const verifier = crypto.createVerify(\"RSA-SHA1\");\n      verifier.update(material);\n      const res = verifier.verify(key, signatureValue, \"base64\");\n\n      return res;\n    },\n  );\n\n  getAlgorithmName = () => {\n    return \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n  };\n}\n\nexport class RsaSha256 implements SignatureAlgorithm {\n  getSignature = createOptionalCallbackFunction(\n    (signedInfo: crypto.BinaryLike, privateKey: crypto.KeyLike): string => {\n      const signer = crypto.createSign(\"RSA-SHA256\");\n      signer.update(signedInfo);\n      const res = signer.sign(privateKey, \"base64\");\n\n      return res;\n    },\n  );\n\n  verifySignature = createOptionalCallbackFunction(\n    (material: string, key: crypto.KeyLike, signatureValue: string): boolean => {\n      const verifier = crypto.createVerify(\"RSA-SHA256\");\n      verifier.update(material);\n      const res = verifier.verify(key, signatureValue, \"base64\");\n\n      return res;\n    },\n  );\n\n  getAlgorithmName = () => {\n    return \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\";\n  };\n}\n\nexport class RsaSha256Mgf1 implements SignatureAlgorithm {\n  getSignature = createOptionalCallbackFunction(\n    (signedInfo: crypto.BinaryLike, privateKey: crypto.KeyLike): string => {\n      if (!(typeof privateKey === \"string\" || Buffer.isBuffer(privateKey))) {\n        throw new Error(\"keys must be strings or buffers\");\n      }\n      const signer = crypto.createSign(\"RSA-SHA256\");\n      signer.update(signedInfo);\n      const res = signer.sign(\n        {\n          key: privateKey,\n          padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n          saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST,\n        },\n        \"base64\",\n      );\n\n      return res;\n    },\n  );\n\n  verifySignature = createOptionalCallbackFunction(\n    (material: string, key: crypto.KeyLike, signatureValue: string): boolean => {\n      if (!(typeof key === \"string\" || Buffer.isBuffer(key))) {\n        throw new Error(\"keys must be strings or buffers\");\n      }\n      const verifier = crypto.createVerify(\"RSA-SHA256\");\n      verifier.update(material);\n      const res = verifier.verify(\n        {\n          key: key,\n          padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n          saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST,\n        },\n        signatureValue,\n        \"base64\",\n      );\n\n      return res;\n    },\n  );\n\n  getAlgorithmName = () => {\n    return \"http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1\";\n  };\n}\n\nexport class RsaSha512 implements SignatureAlgorithm {\n  getSignature = createOptionalCallbackFunction(\n    (signedInfo: crypto.BinaryLike, privateKey: crypto.KeyLike): string => {\n      const signer = crypto.createSign(\"RSA-SHA512\");\n      signer.update(signedInfo);\n      const res = signer.sign(privateKey, \"base64\");\n\n      return res;\n    },\n  );\n\n  verifySignature = createOptionalCallbackFunction(\n    (material: string, key: crypto.KeyLike, signatureValue: string): boolean => {\n      const verifier = crypto.createVerify(\"RSA-SHA512\");\n      verifier.update(material);\n      const res = verifier.verify(key, signatureValue, \"base64\");\n\n      return res;\n    },\n  );\n\n  getAlgorithmName = () => {\n    return \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512\";\n  };\n}\n\nexport class HmacSha1 implements SignatureAlgorithm {\n  getSignature = createOptionalCallbackFunction(\n    (signedInfo: crypto.BinaryLike, privateKey: crypto.KeyLike): string => {\n      const signer = crypto.createHmac(\"SHA1\", privateKey);\n      signer.update(signedInfo);\n      const res = signer.digest(\"base64\");\n\n      return res;\n    },\n  );\n\n  verifySignature = createOptionalCallbackFunction(\n    (material: string, key: crypto.KeyLike, signatureValue: string): boolean => {\n      const verifier = crypto.createHmac(\"SHA1\", key);\n      verifier.update(material);\n      const res = verifier.digest(\"base64\");\n\n      // Use constant-time comparison to prevent timing attacks (CWE-208)\n      // See: https://github.com/node-saml/xml-crypto/issues/522\n      try {\n        return crypto.timingSafeEqual(\n          Buffer.from(res, \"base64\"),\n          Buffer.from(signatureValue, \"base64\"),\n        );\n      } catch (e) {\n        // timingSafeEqual throws if buffer lengths don't match\n        return false;\n      }\n    },\n  );\n\n  getAlgorithmName = () => {\n    return \"http://www.w3.org/2000/09/xmldsig#hmac-sha1\";\n  };\n}\n"
  },
  {
    "path": "src/signed-xml.ts",
    "content": "import type {\n  CanonicalizationAlgorithmType,\n  CanonicalizationOrTransformAlgorithmType,\n  CanonicalizationOrTransformationAlgorithm,\n  CanonicalizationOrTransformationAlgorithmProcessOptions,\n  ComputeSignatureOptions,\n  ErrorFirstCallback,\n  GetKeyInfoContentArgs,\n  HashAlgorithm,\n  HashAlgorithmType,\n  ObjectAttributes,\n  Reference,\n  SignatureAlgorithm,\n  SignatureAlgorithmType,\n  SignedXmlOptions,\n} from \"./types\";\n\nimport * as isDomNode from \"@xmldom/is-dom-node\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as crypto from \"crypto\";\nimport { deprecate } from \"util\";\nimport * as xpath from \"xpath\";\nimport * as c14n from \"./c14n-canonicalization\";\nimport * as envelopedSignatures from \"./enveloped-signature\";\nimport * as execC14n from \"./exclusive-canonicalization\";\nimport * as hashAlgorithms from \"./hash-algorithms\";\nimport * as signatureAlgorithms from \"./signature-algorithms\";\nimport * as utils from \"./utils\";\n\nexport class SignedXml {\n  idMode?: \"wssecurity\";\n  idAttributes: string[];\n  /**\n   * A {@link Buffer} or pem encoded {@link String} containing your private key\n   */\n  privateKey?: crypto.KeyLike;\n  publicCert?: crypto.KeyLike;\n  /**\n   * One of the supported signature algorithms.\n   * @see {@link SignatureAlgorithmType}\n   */\n  signatureAlgorithm?: SignatureAlgorithmType = undefined;\n  /**\n   * Rules used to convert an XML document into its canonical form.\n   */\n  canonicalizationAlgorithm?: CanonicalizationAlgorithmType = undefined;\n  /**\n   * It specifies a list of namespace prefixes that should be considered \"inclusive\" during the canonicalization process.\n   */\n  inclusiveNamespacesPrefixList: string[] = [];\n  namespaceResolver: XPathNSResolver = {\n    lookupNamespaceURI: function (/* prefix */) {\n      throw new Error(\"Not implemented\");\n    },\n  };\n  implicitTransforms: ReadonlyArray<CanonicalizationOrTransformAlgorithmType> = [];\n  keyInfoAttributes: { [attrName: string]: string } = {};\n  getKeyInfoContent = SignedXml.getKeyInfoContent;\n  getCertFromKeyInfo = SignedXml.getCertFromKeyInfo;\n  objects?: Array<{ content: string; attributes?: ObjectAttributes }>;\n\n  // Internal state\n  private id = 0;\n  private signedXml = \"\";\n  private signatureXml = \"\";\n  private signatureNode: Node | null = null;\n  private signatureValue = \"\";\n  private originalXmlWithIds = \"\";\n  private keyInfo: Node | null = null;\n\n  /**\n   * Contains the references that were signed.\n   * @see {@link Reference}\n   */\n  private references: Reference[] = [];\n\n  /**\n   * Contains the canonicalized XML of the references that were validly signed.\n   *\n   * This populates with the canonical XML of the reference only after\n   * verifying the signature is cryptographically authentic.\n   */\n  private signedReferences: string[] = [];\n\n  /**\n   *  To add a new transformation algorithm create a new class that implements the {@link TransformationAlgorithm} interface, and register it here. More info: {@link https://github.com/node-saml/xml-crypto#customizing-algorithms|Customizing Algorithms}\n   */\n  CanonicalizationAlgorithms: Record<\n    CanonicalizationOrTransformAlgorithmType,\n    new () => CanonicalizationOrTransformationAlgorithm\n  > = {\n    \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\": c14n.C14nCanonicalization,\n    \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\":\n      c14n.C14nCanonicalizationWithComments,\n    \"http://www.w3.org/2001/10/xml-exc-c14n#\": execC14n.ExclusiveCanonicalization,\n    \"http://www.w3.org/2001/10/xml-exc-c14n#WithComments\":\n      execC14n.ExclusiveCanonicalizationWithComments,\n    \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\": envelopedSignatures.EnvelopedSignature,\n  };\n\n  // TODO: In v7.x we may consider deprecating sha1\n\n  /**\n   * To add a new hash algorithm create a new class that implements the {@link HashAlgorithm} interface, and register it here. More info: {@link https://github.com/node-saml/xml-crypto#customizing-algorithms|Customizing Algorithms}\n   */\n  HashAlgorithms: Record<HashAlgorithmType, new () => HashAlgorithm> = {\n    \"http://www.w3.org/2000/09/xmldsig#sha1\": hashAlgorithms.Sha1,\n    \"http://www.w3.org/2001/04/xmlenc#sha256\": hashAlgorithms.Sha256,\n    \"http://www.w3.org/2001/04/xmlenc#sha512\": hashAlgorithms.Sha512,\n  };\n\n  // TODO: In v7.x we may consider deprecating sha1\n\n  /**\n   * To add a new signature algorithm create a new class that implements the {@link SignatureAlgorithm} interface, and register it here. More info: {@link https://github.com/node-saml/xml-crypto#customizing-algorithms|Customizing Algorithms}\n   */\n  SignatureAlgorithms: Record<SignatureAlgorithmType, new () => SignatureAlgorithm> = {\n    \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\": signatureAlgorithms.RsaSha1,\n    \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\": signatureAlgorithms.RsaSha256,\n    \"http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1\": signatureAlgorithms.RsaSha256Mgf1,\n    \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512\": signatureAlgorithms.RsaSha512,\n    // Disabled by default due to key confusion concerns.\n    // 'http://www.w3.org/2000/09/xmldsig#hmac-sha1': SignatureAlgorithms.HmacSha1\n  };\n\n  static defaultNsForPrefix = {\n    ds: \"http://www.w3.org/2000/09/xmldsig#\",\n  };\n\n  static noop = () => null;\n\n  /**\n   * The SignedXml constructor provides an abstraction for sign and verify xml documents. The object is constructed using\n   * @param options {@link SignedXmlOptions}\n   */\n  constructor(options: SignedXmlOptions = {}) {\n    const {\n      idMode,\n      idAttribute,\n      privateKey,\n      publicCert,\n      signatureAlgorithm,\n      canonicalizationAlgorithm,\n      inclusiveNamespacesPrefixList,\n      implicitTransforms,\n      keyInfoAttributes,\n      getKeyInfoContent,\n      getCertFromKeyInfo,\n      objects,\n    } = options;\n\n    // Options\n    this.idMode = idMode;\n    this.idAttributes = [\"Id\", \"ID\", \"id\"];\n    if (idAttribute) {\n      this.idAttributes.unshift(idAttribute);\n    }\n    this.privateKey = privateKey;\n    this.publicCert = publicCert;\n    this.signatureAlgorithm = signatureAlgorithm ?? this.signatureAlgorithm;\n    this.canonicalizationAlgorithm = canonicalizationAlgorithm;\n    if (typeof inclusiveNamespacesPrefixList === \"string\") {\n      this.inclusiveNamespacesPrefixList = inclusiveNamespacesPrefixList.split(\" \");\n    } else if (utils.isArrayHasLength(inclusiveNamespacesPrefixList)) {\n      this.inclusiveNamespacesPrefixList = inclusiveNamespacesPrefixList;\n    }\n    this.implicitTransforms = implicitTransforms ?? this.implicitTransforms;\n    this.keyInfoAttributes = keyInfoAttributes ?? this.keyInfoAttributes;\n    this.getKeyInfoContent = getKeyInfoContent ?? this.getKeyInfoContent;\n    this.getCertFromKeyInfo = getCertFromKeyInfo ?? SignedXml.noop;\n    this.objects = objects;\n    this.CanonicalizationAlgorithms;\n    this.HashAlgorithms;\n    this.SignatureAlgorithms;\n  }\n\n  /**\n   * Due to key-confusion issues, it's risky to have both hmac\n   * and digital signature algorithms enabled at the same time.\n   * This enables HMAC and disables other signing algorithms.\n   */\n  enableHMAC(): void {\n    this.SignatureAlgorithms = {\n      \"http://www.w3.org/2000/09/xmldsig#hmac-sha1\": signatureAlgorithms.HmacSha1,\n    };\n    this.getKeyInfoContent = SignedXml.noop;\n  }\n\n  /**\n   * Builds the contents of a KeyInfo element as an XML string.\n   *\n   * For example, if the value of the prefix argument is 'foo', then\n   * the resultant XML string will be \"<foo:X509Data></foo:X509Data>\"\n   *\n   * @return an XML string representation of the contents of a KeyInfo element, or `null` if no `KeyInfo` element should be included\n   */\n  static getKeyInfoContent({ publicCert, prefix }: GetKeyInfoContentArgs): string | null {\n    if (publicCert == null) {\n      return null;\n    }\n\n    prefix = prefix ? `${prefix}:` : \"\";\n\n    let x509Certs = \"\";\n    if (Buffer.isBuffer(publicCert)) {\n      publicCert = publicCert.toString(\"latin1\");\n    }\n\n    let publicCertMatches: string[] = [];\n    if (typeof publicCert === \"string\") {\n      publicCertMatches = publicCert.match(utils.EXTRACT_X509_CERTS) || [];\n    }\n\n    if (publicCertMatches.length > 0) {\n      x509Certs = publicCertMatches\n        .map(\n          (c) =>\n            `<${prefix}X509Certificate>${utils\n              .pemToDer(c)\n              .toString(\"base64\")}</${prefix}X509Certificate>`,\n        )\n        .join(\"\");\n    }\n\n    return `<${prefix}X509Data>${x509Certs}</${prefix}X509Data>`;\n  }\n\n  /**\n   * Returns the value of the signing certificate based on the contents of the\n   * specified KeyInfo.\n   *\n   * @param keyInfo KeyInfo element (@see https://www.w3.org/TR/2008/REC-xmldsig-core-20080610/#sec-X509Data)\n   * @return the signing certificate as a string in PEM format\n   */\n  static getCertFromKeyInfo(keyInfo?: Node | null): string | null {\n    if (keyInfo != null) {\n      const cert = xpath.select1(\".//*[local-name(.)='X509Certificate']\", keyInfo);\n      if (isDomNode.isNodeLike(cert)) {\n        return utils.derToPem(cert.textContent ?? \"\", \"CERTIFICATE\");\n      }\n    }\n\n    return null;\n  }\n\n  /**\n   * Validates the signature of the provided XML document synchronously using the configured key info provider.\n   *\n   * @param xml The XML document containing the signature to be validated.\n   * @returns `true` if the signature is valid\n   * @throws Error if no key info resolver is provided.\n   */\n  checkSignature(xml: string): boolean;\n  /**\n   * Validates the signature of the provided XML document synchronously using the configured key info provider.\n   *\n   * @param xml The XML document containing the signature to be validated.\n   * @param callback Callback function to handle the validation result asynchronously.\n   * @throws Error if the last parameter is provided and is not a function, or if no key info resolver is provided.\n   */\n  checkSignature(xml: string, callback: (error: Error | null, isValid?: boolean) => void): void;\n  checkSignature(\n    xml: string,\n    callback?: (error: Error | null, isValid?: boolean) => void,\n  ): unknown {\n    if (callback != null && typeof callback !== \"function\") {\n      throw new Error(\"Last parameter must be a callback function\");\n    }\n\n    this.signedXml = xml;\n\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n\n    // Reset the references as only references from our re-parsed signedInfo node can be trusted\n    this.references = [];\n\n    const unverifiedSignedInfoCanon = this.getCanonSignedInfoXml(doc);\n    if (!unverifiedSignedInfoCanon) {\n      if (callback) {\n        callback(new Error(\"Canonical signed info cannot be empty\"), false);\n        return;\n      }\n\n      throw new Error(\"Canonical signed info cannot be empty\");\n    }\n\n    // unsigned, verify later to keep with consistent callback behavior\n    const parsedUnverifiedSignedInfo = new xmldom.DOMParser().parseFromString(\n      unverifiedSignedInfoCanon,\n      \"text/xml\",\n    );\n\n    const unverifiedSignedInfoDoc = parsedUnverifiedSignedInfo.documentElement;\n    if (!unverifiedSignedInfoDoc) {\n      if (callback) {\n        callback(new Error(\"Could not parse unverifiedSignedInfoCanon into a document\"), false);\n        return;\n      }\n\n      throw new Error(\"Could not parse unverifiedSignedInfoCanon into a document\");\n    }\n\n    const references = utils.findChildren(unverifiedSignedInfoDoc, \"Reference\");\n    if (!utils.isArrayHasLength(references)) {\n      if (callback) {\n        callback(new Error(\"could not find any Reference elements\"), false);\n        return;\n      }\n\n      throw new Error(\"could not find any Reference elements\");\n    }\n\n    // TODO: In a future release we'd like to load the Signature and its References at the same time,\n    // however, in the `.loadSignature()` method we don't have the entire document,\n    // which we need to to keep the inclusive namespaces\n    for (const reference of references) {\n      this.loadReference(reference);\n    }\n\n    /* eslint-disable-next-line deprecation/deprecation */\n    if (!this.getReferences().every((ref) => this.validateReference(ref, doc))) {\n      /* Trustworthiness can only be determined if SignedInfo's (which holds References' DigestValue(s)\n         which were validated at this stage) signature is valid. Execution does not proceed to validate\n         signature phase thus each References' DigestValue must be considered to be untrusted (attacker\n         might have injected any data with new new references and/or recalculated new DigestValue for\n         altered Reference(s)). Returning any content via `signedReferences` would give false sense of\n         trustworthiness if/when SignedInfo's (which holds references' DigestValues) signature is not\n         valid(ated). Put simply: if one fails, they are all not trustworthy.\n      */\n      this.signedReferences = [];\n      this.references.forEach((ref) => {\n        ref.signedReference = undefined;\n      });\n      // TODO: add this breaking change here later on for even more security: `this.references = [];`\n\n      if (callback) {\n        callback(new Error(\"Could not validate all references\"), false);\n        return;\n      }\n\n      // We return false because some references validated, but not all\n      // We should actually be throwing an error here, but that would be a breaking change\n      // See https://www.w3.org/TR/xmldsig-core/#sec-CoreValidation\n      return false;\n    }\n\n    // (Stage B authentication step, show that the `signedInfoCanon` is signed)\n\n    // First find the key & signature algorithm, these should match\n    // Stage B: Take the signature algorithm and key and verify the `SignatureValue` against the canonicalized `SignedInfo`\n    const signer = this.findSignatureAlgorithm(this.signatureAlgorithm);\n    const key = this.getCertFromKeyInfo(this.keyInfo) || this.publicCert || this.privateKey;\n    if (key == null) {\n      throw new Error(\"KeyInfo or publicCert or privateKey is required to validate signature\");\n    }\n\n    // Check the signature verification to know whether to reset signature value or not.\n    const sigRes = signer.verifySignature(unverifiedSignedInfoCanon, key, this.signatureValue);\n    if (sigRes === true) {\n      if (callback) {\n        callback(null, true);\n      } else {\n        return true;\n      }\n    } else {\n      // Ideally, we would start by verifying the `signedInfoCanon` first,\n      // but that may cause some breaking changes, so we'll handle that in v7.x.\n      // If we were validating `signedInfoCanon` first, we wouldn't have to reset this array.\n      this.signedReferences = [];\n      this.references.forEach((ref) => {\n        ref.signedReference = undefined;\n      });\n      // TODO: add this breaking change here later on for even more security: `this.references = [];`\n\n      if (callback) {\n        callback(\n          new Error(`invalid signature: the signature value ${this.signatureValue} is incorrect`),\n        );\n        return; // return early\n      } else {\n        throw new Error(\n          `invalid signature: the signature value ${this.signatureValue} is incorrect`,\n        );\n      }\n    }\n  }\n\n  private getCanonSignedInfoXml(doc: Document) {\n    if (this.signatureNode == null) {\n      throw new Error(\"No signature found.\");\n    }\n    if (typeof this.canonicalizationAlgorithm !== \"string\") {\n      throw new Error(\"Missing canonicalizationAlgorithm when trying to get signed info for XML\");\n    }\n\n    const signedInfo = utils.findChildren(this.signatureNode, \"SignedInfo\");\n    if (signedInfo.length === 0) {\n      throw new Error(\"could not find SignedInfo element in the message\");\n    }\n    if (signedInfo.length > 1) {\n      throw new Error(\n        \"could not get canonicalized signed info for a signature that contains multiple SignedInfo nodes\",\n      );\n    }\n\n    if (\n      this.canonicalizationAlgorithm === \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\" ||\n      this.canonicalizationAlgorithm ===\n        \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"\n    ) {\n      if (!doc || typeof doc !== \"object\") {\n        throw new Error(\n          \"When canonicalization method is non-exclusive, whole xml dom must be provided as an argument\",\n        );\n      }\n    }\n\n    /**\n     * Search for ancestor namespaces before canonicalization.\n     */\n    const ancestorNamespaces = utils.findAncestorNs(doc, \"//*[local-name()='SignedInfo']\");\n\n    const c14nOptions = {\n      ancestorNamespaces: ancestorNamespaces,\n    };\n\n    return this.getCanonXml([this.canonicalizationAlgorithm], signedInfo[0], c14nOptions);\n  }\n\n  private getCanonReferenceXml(doc: Document, ref: Reference, node: Node) {\n    /**\n     * Search for ancestor namespaces before canonicalization.\n     */\n    if (Array.isArray(ref.transforms)) {\n      ref.ancestorNamespaces = utils.findAncestorNs(doc, ref.xpath, this.namespaceResolver);\n    }\n\n    const c14nOptions = {\n      inclusiveNamespacesPrefixList: ref.inclusiveNamespacesPrefixList,\n      ancestorNamespaces: ref.ancestorNamespaces,\n    };\n\n    return this.getCanonXml(ref.transforms, node, c14nOptions);\n  }\n\n  private calculateSignatureValue(doc: Document, callback?: ErrorFirstCallback<string>) {\n    const signedInfoCanon = this.getCanonSignedInfoXml(doc);\n    const signer = this.findSignatureAlgorithm(this.signatureAlgorithm);\n    if (this.privateKey == null) {\n      throw new Error(\"Private key is required to compute signature\");\n    }\n    if (typeof callback === \"function\") {\n      signer.getSignature(signedInfoCanon, this.privateKey, callback);\n    } else {\n      this.signatureValue = signer.getSignature(signedInfoCanon, this.privateKey);\n    }\n  }\n\n  private findSignatureAlgorithm(name?: SignatureAlgorithmType) {\n    if (name == null) {\n      throw new Error(\"signatureAlgorithm is required\");\n    }\n    const algo = this.SignatureAlgorithms[name];\n    if (algo) {\n      return new algo();\n    } else {\n      throw new Error(`signature algorithm '${name}' is not supported`);\n    }\n  }\n\n  private findCanonicalizationAlgorithm(name: CanonicalizationOrTransformAlgorithmType) {\n    if (name != null) {\n      const algo = this.CanonicalizationAlgorithms[name];\n      if (algo) {\n        return new algo();\n      }\n    }\n\n    throw new Error(`canonicalization algorithm '${name}' is not supported`);\n  }\n\n  private findHashAlgorithm(name: HashAlgorithmType) {\n    const algo = this.HashAlgorithms[name];\n    if (algo) {\n      return new algo();\n    } else {\n      throw new Error(`hash algorithm '${name}' is not supported`);\n    }\n  }\n\n  validateElementAgainstReferences(elemOrXpath: Element | string, doc: Document): Reference {\n    let elem: Element;\n    if (typeof elemOrXpath === \"string\") {\n      const firstElem = xpath.select1(elemOrXpath, doc);\n      isDomNode.assertIsElementNode(firstElem);\n      elem = firstElem;\n    } else {\n      elem = elemOrXpath;\n    }\n\n    /* eslint-disable-next-line deprecation/deprecation */\n    for (const ref of this.getReferences()) {\n      const uri = ref.uri?.[0] === \"#\" ? ref.uri.substring(1) : ref.uri;\n\n      for (const attr of this.idAttributes) {\n        const elemId = elem.getAttribute(attr);\n        if (uri === elemId) {\n          ref.xpath = `//*[@*[local-name(.)='${attr}']='${uri}']`;\n          break; // found the correct element, no need to check further\n        }\n      }\n\n      const canonXml = this.getCanonReferenceXml(doc, ref, elem);\n      const hash = this.findHashAlgorithm(ref.digestAlgorithm);\n      const digest = hash.getHash(canonXml);\n\n      if (utils.validateDigestValue(digest, ref.digestValue)) {\n        return ref;\n      }\n    }\n\n    throw new Error(\"No references passed validation\");\n  }\n\n  private validateReference(ref: Reference, doc: Document) {\n    const uri = ref.uri?.[0] === \"#\" ? ref.uri.substring(1) : ref.uri;\n    let elem: xpath.SelectSingleReturnType = null;\n\n    if (uri === \"\") {\n      elem = xpath.select1(\"//*\", doc);\n    } else if (uri?.indexOf(\"'\") !== -1) {\n      // xpath injection\n      throw new Error(\"Cannot validate a uri with quotes inside it\");\n    } else {\n      let num_elements_for_id = 0;\n      for (const attr of this.idAttributes) {\n        const tmp_elemXpath = `//*[@*[local-name(.)='${attr}']='${uri}']`;\n        const tmp_elem = xpath.select(tmp_elemXpath, doc);\n        if (utils.isArrayHasLength(tmp_elem)) {\n          num_elements_for_id += tmp_elem.length;\n\n          if (num_elements_for_id > 1) {\n            throw new Error(\n              \"Cannot validate a document which contains multiple elements with the \" +\n                \"same value for the ID / Id / Id attributes, in order to prevent \" +\n                \"signature wrapping attack.\",\n            );\n          }\n\n          elem = tmp_elem[0];\n          ref.xpath = tmp_elemXpath;\n        }\n      }\n    }\n\n    ref.getValidatedNode = deprecate((xpathSelector?: string) => {\n      xpathSelector = xpathSelector || ref.xpath;\n      if (typeof xpathSelector !== \"string\" || ref.validationError != null) {\n        return null;\n      }\n      const selectedValue = xpath.select1(xpathSelector, doc);\n      return isDomNode.isNodeLike(selectedValue) ? selectedValue : null;\n    }, \"`ref.getValidatedNode()` is deprecated and insecure. Use `ref.signedReference` or `this.getSignedReferences()` instead.\");\n\n    if (!isDomNode.isNodeLike(elem)) {\n      const validationError = new Error(\n        `invalid signature: the signature references an element with uri ${ref.uri} but could not find such element in the xml`,\n      );\n      ref.validationError = validationError;\n      return false;\n    }\n\n    const canonXml = this.getCanonReferenceXml(doc, ref, elem);\n    const hash = this.findHashAlgorithm(ref.digestAlgorithm);\n    const digest = hash.getHash(canonXml);\n\n    if (!utils.validateDigestValue(digest, ref.digestValue)) {\n      const validationError = new Error(\n        `invalid signature: for uri ${ref.uri} calculated digest is ${digest} but the xml to validate supplies digest ${ref.digestValue}`,\n      );\n      ref.validationError = validationError;\n\n      return false;\n    }\n    // This step can only be done after we have verified the `signedInfo`.\n    // We verified that they have same hash,\n    // thus the `canonXml` and _only_ the `canonXml` can be trusted.\n    // Append this to `signedReferences`.\n    this.signedReferences.push(canonXml);\n    ref.signedReference = canonXml;\n\n    return true;\n  }\n\n  findSignatures(doc: Node): Node[] {\n    const nodes = xpath.select(\n      \"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n\n    return isDomNode.isArrayOfNodes(nodes) ? nodes : [];\n  }\n\n  /**\n   * Loads the signature information from the provided XML node or string.\n   *\n   * @param signatureNode The XML node or string representing the signature.\n   */\n  loadSignature(signatureNode: Node | string): void {\n    if (typeof signatureNode === \"string\") {\n      this.signatureNode = signatureNode = new xmldom.DOMParser().parseFromString(signatureNode);\n    } else {\n      this.signatureNode = signatureNode;\n    }\n\n    this.signatureXml = signatureNode.toString();\n\n    const node = xpath.select1(\n      \".//*[local-name(.)='CanonicalizationMethod']/@Algorithm\",\n      signatureNode,\n    );\n    if (!isDomNode.isNodeLike(node)) {\n      throw new Error(\"could not find CanonicalizationMethod/@Algorithm element\");\n    }\n\n    if (isDomNode.isAttributeNode(node)) {\n      this.canonicalizationAlgorithm = node.value as CanonicalizationAlgorithmType;\n    }\n\n    const signatureAlgorithm = xpath.select1(\n      \".//*[local-name(.)='SignatureMethod']/@Algorithm\",\n      signatureNode,\n    );\n\n    if (isDomNode.isAttributeNode(signatureAlgorithm)) {\n      this.signatureAlgorithm = signatureAlgorithm.value as SignatureAlgorithmType;\n    }\n\n    const signedInfoNodes = utils.findChildren(this.signatureNode, \"SignedInfo\");\n    if (!utils.isArrayHasLength(signedInfoNodes)) {\n      throw new Error(\"no signed info node found\");\n    }\n    if (signedInfoNodes.length > 1) {\n      throw new Error(\"could not load signature that contains multiple SignedInfo nodes\");\n    }\n\n    // Try to operate on the c14n version of `signedInfo`. This forces the initial `getReferences()`\n    // API call to always return references that are loaded under the canonical `SignedInfo`\n    // in the case that the client access the `.references` **before** signature verification.\n\n    // Ensure canonicalization algorithm is exclusive, otherwise we'd need the entire document\n    let canonicalizationAlgorithmForSignedInfo = this.canonicalizationAlgorithm;\n    if (\n      !canonicalizationAlgorithmForSignedInfo ||\n      canonicalizationAlgorithmForSignedInfo ===\n        \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\" ||\n      canonicalizationAlgorithmForSignedInfo ===\n        \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"\n    ) {\n      canonicalizationAlgorithmForSignedInfo = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    }\n\n    const temporaryCanonSignedInfo = this.getCanonXml(\n      [canonicalizationAlgorithmForSignedInfo],\n      signedInfoNodes[0],\n    );\n    const temporaryCanonSignedInfoXml = new xmldom.DOMParser().parseFromString(\n      temporaryCanonSignedInfo,\n      \"text/xml\",\n    );\n    const signedInfoDoc = temporaryCanonSignedInfoXml.documentElement;\n\n    this.references = [];\n    const references = utils.findChildren(signedInfoDoc, \"Reference\");\n\n    if (!utils.isArrayHasLength(references)) {\n      throw new Error(\"could not find any Reference elements\");\n    }\n\n    for (const reference of references) {\n      this.loadReference(reference);\n    }\n\n    const signatureValue = xpath.select1(\n      \".//*[local-name(.)='SignatureValue']/text()\",\n      signatureNode,\n    );\n\n    if (isDomNode.isTextNode(signatureValue)) {\n      this.signatureValue = signatureValue.data.replace(/\\r?\\n/g, \"\");\n    }\n\n    const keyInfo = xpath.select1(\".//*[local-name(.)='KeyInfo']\", signatureNode);\n\n    if (isDomNode.isNodeLike(keyInfo)) {\n      this.keyInfo = keyInfo;\n    }\n  }\n\n  /**\n   * Load the reference xml node to a model\n   *\n   */\n  private loadReference(refNode: Node) {\n    let nodes = utils.findChildren(refNode, \"DigestMethod\");\n    if (nodes.length === 0) {\n      throw new Error(`could not find DigestMethod in reference ${refNode.toString()}`);\n    }\n    const digestAlgoNode = nodes[0];\n\n    const attr = utils.findAttr(digestAlgoNode, \"Algorithm\");\n    if (!attr) {\n      throw new Error(`could not find Algorithm attribute in node ${digestAlgoNode.toString()}`);\n    }\n    const digestAlgo = attr.value;\n\n    nodes = utils.findChildren(refNode, \"DigestValue\");\n    if (nodes.length === 0) {\n      throw new Error(`could not find DigestValue node in reference ${refNode.toString()}`);\n    }\n\n    if (nodes.length > 1) {\n      throw new Error(\n        `could not load reference for a node that contains multiple DigestValue nodes: ${refNode.toString()}`,\n      );\n    }\n    const digestValue = nodes[0].textContent;\n    if (!digestValue) {\n      throw new Error(`could not find the value of DigestValue in ${refNode.toString()}`);\n    }\n\n    const transforms: string[] = [];\n    let inclusiveNamespacesPrefixList: string[] = [];\n    nodes = utils.findChildren(refNode, \"Transforms\");\n    if (nodes.length !== 0) {\n      const transformsNode = nodes[0];\n      const transformsAll = utils.findChildren(transformsNode, \"Transform\");\n      for (const transform of transformsAll) {\n        const transformAttr = utils.findAttr(transform, \"Algorithm\");\n\n        if (transformAttr) {\n          transforms.push(transformAttr.value);\n        }\n      }\n\n      // This is a little strange, we are looking for children of the last child of `transformsNode`\n      const inclusiveNamespaces = utils.findChildren(\n        transformsAll[transformsAll.length - 1],\n        \"InclusiveNamespaces\",\n      );\n      if (utils.isArrayHasLength(inclusiveNamespaces)) {\n        // Should really only be one prefix list, but maybe there's some circumstances where more than one to let's handle it\n        inclusiveNamespacesPrefixList = inclusiveNamespaces\n          .flatMap((namespace) => (namespace.getAttribute(\"PrefixList\") ?? \"\").split(\" \"))\n          .filter((value) => value.length > 0);\n      }\n    }\n\n    if (utils.isArrayHasLength(this.implicitTransforms)) {\n      this.implicitTransforms.forEach(function (t) {\n        transforms.push(t);\n      });\n    }\n\n    /**\n     * DigestMethods take an octet stream rather than a node set. If the output of the last transform is a node set, we\n     * need to canonicalize the node set to an octet stream using non-exclusive canonicalization. If there are no\n     * transforms, we need to canonicalize because URI dereferencing for a same-document reference will return a node-set.\n     * @see:\n     * https://www.w3.org/TR/xmldsig-core1/#sec-DigestMethod\n     * https://www.w3.org/TR/xmldsig-core1/#sec-ReferenceProcessingModel\n     * https://www.w3.org/TR/xmldsig-core1/#sec-Same-Document\n     */\n    if (\n      transforms.length === 0 ||\n      transforms[transforms.length - 1] === \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"\n    ) {\n      transforms.push(\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\");\n    }\n    const refUri = isDomNode.isElementNode(refNode)\n      ? refNode.getAttribute(\"URI\") || undefined\n      : undefined;\n\n    this.addReference({\n      transforms,\n      digestAlgorithm: digestAlgo,\n      uri: refUri,\n      digestValue,\n      inclusiveNamespacesPrefixList,\n      isEmptyUri: false,\n    });\n  }\n\n  /**\n   * Adds a reference to the signature.\n   *\n   * @param xpath The XPath expression to select the XML nodes to be referenced.\n   * @param transforms An array of transform algorithms to be applied to the selected nodes.\n   * @param digestAlgorithm The digest algorithm to use for computing the digest value.\n   * @param uri The URI identifier for the reference. If empty, an empty URI will be used.\n   * @param digestValue The expected digest value for the reference.\n   * @param inclusiveNamespacesPrefixList The prefix list for inclusive namespace canonicalization.\n   * @param isEmptyUri Indicates whether the URI is empty. Defaults to `false`.\n   * @param id An optional `Id` attribute for the reference.\n   * @param type An optional `Type` attribute for the reference.\n   */\n  addReference({\n    xpath,\n    transforms,\n    digestAlgorithm,\n    uri = \"\",\n    digestValue,\n    inclusiveNamespacesPrefixList = [],\n    isEmptyUri = false,\n    id = undefined,\n    type = undefined,\n  }: Partial<Reference> & Pick<Reference, \"xpath\">): void {\n    if (digestAlgorithm == null) {\n      throw new Error(\"digestAlgorithm is required\");\n    }\n\n    if (!utils.isArrayHasLength(transforms)) {\n      throw new Error(\"transforms must contain at least one transform algorithm\");\n    }\n\n    this.references.push({\n      xpath,\n      transforms,\n      digestAlgorithm,\n      uri,\n      digestValue,\n      inclusiveNamespacesPrefixList,\n      isEmptyUri,\n      id,\n      type,\n      getValidatedNode: () => {\n        throw new Error(\n          \"Reference has not been validated yet; Did you call `sig.checkSignature()`?\",\n        );\n      },\n    });\n  }\n\n  /**\n   * Returns the list of references.\n   */\n  getReferences() {\n    // TODO: Refactor once `getValidatedNode` is removed\n    /* Once we completely remove the deprecated `getValidatedNode()` method,\n    we can change this to return a clone to prevent accidental mutations,\n    e.g.:\n    return [...this.references];\n    */\n\n    return this.references;\n  }\n\n  getSignedReferences() {\n    return [...this.signedReferences];\n  }\n\n  /**\n   * Compute the signature of the given XML (using the already defined settings).\n   *\n   * @param xml The XML to compute the signature for.\n   * @param callback A callback function to handle the signature computation asynchronously.\n   * @returns void\n   * @throws TypeError If the xml can not be parsed.\n   */\n  computeSignature(xml: string): void;\n\n  /**\n   * Compute the signature of the given XML (using the already defined settings).\n   *\n   * @param xml The XML to compute the signature for.\n   * @param callback A callback function to handle the signature computation asynchronously.\n   * @returns void\n   * @throws TypeError If the xml can not be parsed.\n   */\n  computeSignature(xml: string, callback: ErrorFirstCallback<SignedXml>): void;\n\n  /**\n   * Compute the signature of the given XML (using the already defined settings).\n   *\n   * @param xml The XML to compute the signature for.\n   * @param opts An object containing options for the signature computation.\n   * @returns If no callback is provided, returns `this` (the instance of SignedXml).\n   * @throws TypeError If the xml can not be parsed, or Error if there were invalid options passed.\n   */\n  computeSignature(xml: string, options: ComputeSignatureOptions): void;\n\n  /**\n   * Compute the signature of the given XML (using the already defined settings).\n   *\n   * @param xml The XML to compute the signature for.\n   * @param opts An object containing options for the signature computation.\n   * @param callback A callback function to handle the signature computation asynchronously.\n   * @returns void\n   * @throws TypeError If the xml can not be parsed, or Error if there were invalid options passed.\n   */\n  computeSignature(\n    xml: string,\n    options: ComputeSignatureOptions,\n    callback: ErrorFirstCallback<SignedXml>,\n  ): void;\n\n  computeSignature(\n    xml: string,\n    options?: ComputeSignatureOptions | ErrorFirstCallback<SignedXml>,\n    callbackParam?: ErrorFirstCallback<SignedXml>,\n  ): void {\n    let callback: ErrorFirstCallback<SignedXml>;\n    if (typeof options === \"function\" && callbackParam == null) {\n      callback = options as ErrorFirstCallback<SignedXml>;\n      options = {} as ComputeSignatureOptions;\n    } else {\n      callback = callbackParam as ErrorFirstCallback<SignedXml>;\n      options = (options ?? {}) as ComputeSignatureOptions;\n    }\n\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    let xmlNsAttr = \"xmlns\";\n    const signatureAttrs: string[] = [];\n    let currentPrefix: string;\n\n    const validActions = [\"append\", \"prepend\", \"before\", \"after\"];\n\n    const prefix = options.prefix;\n    const attrs = options.attrs || {};\n    const location = options.location || {};\n    const existingPrefixes = options.existingPrefixes || {};\n\n    this.namespaceResolver = {\n      lookupNamespaceURI: function (prefix) {\n        return prefix ? existingPrefixes[prefix] : null;\n      },\n    };\n\n    // defaults to the root node\n    location.reference = location.reference || \"/*\";\n    // defaults to append action\n    location.action = location.action || \"append\";\n\n    if (validActions.indexOf(location.action) === -1) {\n      const err = new Error(\n        `location.action option has an invalid action: ${\n          location.action\n        }, must be any of the following values: ${validActions.join(\", \")}`,\n      );\n      if (!callback) {\n        throw err;\n      } else {\n        callback(err);\n        return;\n      }\n    }\n\n    // Add IDs for all non-self references upfront\n    for (const ref of this.getReferences()) {\n      if (ref.isEmptyUri) {\n        continue;\n      } // No specific nodes to ID for empty URI\n\n      const nodes = xpath.selectWithResolver(\n        ref.xpath ?? \"\",\n        doc,\n        this.namespaceResolver,\n      ) as Element[];\n      for (const node of nodes) {\n        isDomNode.assertIsElementNode(node);\n        this.ensureHasId(node);\n      }\n    }\n\n    // Capture original with IDs (no sig yet)\n    this.originalXmlWithIds = doc.toString();\n\n    // automatic insertion of `:`\n    if (prefix) {\n      xmlNsAttr += `:${prefix}`;\n      currentPrefix = `${prefix}:`;\n    } else {\n      currentPrefix = \"\";\n    }\n\n    Object.keys(attrs).forEach(function (name) {\n      if (name !== \"xmlns\" && name !== xmlNsAttr) {\n        signatureAttrs.push(`${name}=\"${attrs[name]}\"`);\n      }\n    });\n\n    // add the xml namespace attribute\n    signatureAttrs.push(`${xmlNsAttr}=\"http://www.w3.org/2000/09/xmldsig#\"`);\n\n    let signatureXml = `<${currentPrefix}Signature ${signatureAttrs.join(\" \")}>`;\n\n    signatureXml += this.createSignedInfo(doc, prefix);\n    signatureXml += this.getKeyInfo(prefix);\n    signatureXml += this.getObjects(prefix);\n    signatureXml += `</${currentPrefix}Signature>`;\n\n    let existingPrefixesString = \"\";\n    Object.keys(existingPrefixes).forEach(function (key) {\n      existingPrefixesString += `xmlns:${key}=\"${existingPrefixes[key]}\" `;\n    });\n\n    // A trick to remove the namespaces that already exist in the xml\n    // This only works if the prefix and namespace match with those in the xml\n    const dummySignatureWrapper = `<Dummy ${existingPrefixesString}>${signatureXml}</Dummy>`;\n    const nodeXml = new xmldom.DOMParser().parseFromString(dummySignatureWrapper);\n\n    // Because we are using a dummy wrapper hack described above, we know there will be a `firstChild`\n    // and that it will be an `Element` node.\n    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n    const signatureElem = nodeXml.documentElement.firstChild! as Element;\n\n    const referenceNode = xpath.select1(location.reference, doc);\n\n    if (!isDomNode.isNodeLike(referenceNode)) {\n      const err2 = new Error(\n        `the following xpath cannot be used because it was not found: ${location.reference}`,\n      );\n      if (!callback) {\n        throw err2;\n      } else {\n        callback(err2);\n        return;\n      }\n    }\n\n    if (location.action === \"append\") {\n      referenceNode.appendChild(signatureElem);\n    } else if (location.action === \"prepend\") {\n      referenceNode.insertBefore(signatureElem, referenceNode.firstChild);\n    } else if (location.action === \"before\") {\n      if (referenceNode.parentNode == null) {\n        throw new Error(\n          \"`location.reference` refers to the root node (by default), so we can't insert `before`\",\n        );\n      }\n      referenceNode.parentNode.insertBefore(signatureElem, referenceNode);\n    } else if (location.action === \"after\") {\n      if (referenceNode.parentNode == null) {\n        throw new Error(\n          \"`location.reference` refers to the root node (by default), so we can't insert `after`\",\n        );\n      }\n      referenceNode.parentNode.insertBefore(signatureElem, referenceNode.nextSibling);\n    }\n\n    // Now add all references (including any to the signature itself)\n    this.addAllReferences(doc, signatureElem, prefix);\n\n    this.signatureNode = signatureElem;\n    const signedInfoNodes = utils.findChildren(this.signatureNode, \"SignedInfo\");\n    if (signedInfoNodes.length === 0) {\n      const err3 = new Error(\"could not find SignedInfo element in the message\");\n      if (!callback) {\n        throw err3;\n      } else {\n        callback(err3);\n        return;\n      }\n    }\n    const signedInfoNode = signedInfoNodes[0];\n\n    if (typeof callback === \"function\") {\n      // Asynchronous flow\n      this.calculateSignatureValue(doc, (err, signature) => {\n        if (err) {\n          callback(err);\n        } else {\n          this.signatureValue = signature || \"\";\n          signatureElem.insertBefore(this.createSignature(prefix), signedInfoNode.nextSibling);\n          this.signatureXml = signatureElem.toString();\n          this.signedXml = doc.toString();\n          callback(null, this);\n        }\n      });\n    } else {\n      // Synchronous flow\n      this.calculateSignatureValue(doc);\n      signatureElem.insertBefore(this.createSignature(prefix), signedInfoNode.nextSibling);\n      this.signatureXml = signatureElem.toString();\n      this.signedXml = doc.toString();\n    }\n  }\n\n  /**\n   * Adds all references to the SignedInfo after the signature placeholder is inserted.\n   */\n  private addAllReferences(doc: Document, signatureElem: Element, prefix?: string): void {\n    if (!utils.isArrayHasLength(this.references)) {\n      return;\n    }\n\n    const currentPrefix = prefix ? `${prefix}:` : \"\";\n    const signatureNamespace = \"http://www.w3.org/2000/09/xmldsig#\";\n\n    // Find the SignedInfo element to append to\n    const signedInfoNode = xpath.select1(`./*[local-name(.)='SignedInfo']`, signatureElem);\n    isDomNode.assertIsElementNode(signedInfoNode); // Type-safe assertion\n\n    // Signature document is technically the same document as the one we are signing,\n    // but we will extract it here for clarity (and also make it support detached signatures in the future)\n    const signatureDoc = signatureElem.ownerDocument;\n\n    // Process each reference\n    for (const ref of this.getReferences()) {\n      const nodes = xpath.selectWithResolver(ref.xpath ?? \"\", doc, this.namespaceResolver);\n\n      if (!utils.isArrayHasLength(nodes)) {\n        throw new Error(\n          `the following xpath cannot be signed because it was not found: ${ref.xpath}`,\n        );\n      }\n\n      // Process the reference\n      for (const node of nodes) {\n        isDomNode.assertIsElementNode(node);\n\n        // Must not be a reference to Signature, SignedInfo, or a child of SignedInfo\n        if (\n          node === signatureElem ||\n          node === signedInfoNode ||\n          utils.isDescendantOf(node, signedInfoNode)\n        ) {\n          throw new Error(\n            `Cannot sign a reference to the Signature or SignedInfo element itself: ${ref.xpath}`,\n          );\n        }\n\n        // Compute the target URI (ID already ensured earlier, extract it)\n        let targetUri: string;\n        if (ref.isEmptyUri) {\n          targetUri = \"\";\n        } else {\n          const id = this.ensureHasId(node);\n          ref.uri = id;\n          targetUri = `#${id}`;\n        }\n\n        // Create the reference element directly using DOM methods to avoid namespace issues\n        const referenceElem = signatureDoc.createElementNS(\n          signatureNamespace,\n          `${currentPrefix}Reference`,\n        );\n        referenceElem.setAttribute(\"URI\", targetUri);\n\n        if (ref.id) {\n          referenceElem.setAttribute(\"Id\", ref.id);\n        }\n\n        if (ref.type) {\n          referenceElem.setAttribute(\"Type\", ref.type);\n        }\n\n        const transformsElem = signatureDoc.createElementNS(\n          signatureNamespace,\n          `${currentPrefix}Transforms`,\n        );\n\n        for (const trans of ref.transforms || []) {\n          const transform = this.findCanonicalizationAlgorithm(trans);\n          const transformElem = signatureDoc.createElementNS(\n            signatureNamespace,\n            `${currentPrefix}Transform`,\n          );\n          transformElem.setAttribute(\"Algorithm\", transform.getAlgorithmName());\n\n          if (utils.isArrayHasLength(ref.inclusiveNamespacesPrefixList)) {\n            const inclusiveNamespacesElem = signatureDoc.createElementNS(\n              transform.getAlgorithmName(),\n              \"InclusiveNamespaces\",\n            );\n            inclusiveNamespacesElem.setAttribute(\n              \"PrefixList\",\n              ref.inclusiveNamespacesPrefixList.join(\" \"),\n            );\n            transformElem.appendChild(inclusiveNamespacesElem);\n          }\n\n          transformsElem.appendChild(transformElem);\n        }\n\n        // Get the canonicalized XML\n        const canonXml = this.getCanonReferenceXml(doc, ref, node);\n\n        // Get the digest algorithm and compute the digest value\n        const digestAlgorithm = this.findHashAlgorithm(ref.digestAlgorithm);\n\n        const digestMethodElem = signatureDoc.createElementNS(\n          signatureNamespace,\n          `${currentPrefix}DigestMethod`,\n        );\n        digestMethodElem.setAttribute(\"Algorithm\", digestAlgorithm.getAlgorithmName());\n\n        const digestValueElem = signatureDoc.createElementNS(\n          signatureNamespace,\n          `${currentPrefix}DigestValue`,\n        );\n        digestValueElem.textContent = digestAlgorithm.getHash(canonXml);\n\n        referenceElem.appendChild(transformsElem);\n        referenceElem.appendChild(digestMethodElem);\n        referenceElem.appendChild(digestValueElem);\n\n        // Append the reference element to SignedInfo\n        signedInfoNode.appendChild(referenceElem);\n      }\n    }\n  }\n\n  private getKeyInfo(prefix) {\n    const currentPrefix = prefix ? `${prefix}:` : \"\";\n\n    let keyInfoAttrs = \"\";\n    if (this.keyInfoAttributes) {\n      Object.keys(this.keyInfoAttributes).forEach((name) => {\n        keyInfoAttrs += ` ${name}=\"${this.keyInfoAttributes[name]}\"`;\n      });\n    }\n\n    const keyInfoContent = this.getKeyInfoContent({ publicCert: this.publicCert, prefix });\n    if (keyInfoAttrs || keyInfoContent) {\n      return `<${currentPrefix}KeyInfo${keyInfoAttrs}>${keyInfoContent}</${currentPrefix}KeyInfo>`;\n    }\n\n    return \"\";\n  }\n\n  /**\n   * Creates XML for Object elements to be included in the signature\n   *\n   * @param prefix Optional namespace prefix\n   * @returns XML string with Object elements or empty string if none\n   */\n  private getObjects(prefix?: string) {\n    const currentPrefix = prefix ? `${prefix}:` : \"\";\n\n    if (!this.objects || this.objects.length === 0) {\n      return \"\";\n    }\n\n    let result = \"\";\n\n    for (const obj of this.objects) {\n      let objectAttrs = \"\";\n      if (obj.attributes) {\n        Object.keys(obj.attributes).forEach((name) => {\n          const value = obj.attributes?.[name];\n          if (value !== undefined) {\n            objectAttrs += ` ${name}=\"${value}\"`;\n          }\n        });\n      }\n\n      result += `<${currentPrefix}Object${objectAttrs}>${obj.content}</${currentPrefix}Object>`;\n    }\n\n    return result;\n  }\n\n  getCanonXml(\n    transforms: Reference[\"transforms\"],\n    node: Node,\n    options: CanonicalizationOrTransformationAlgorithmProcessOptions = {},\n  ) {\n    options.defaultNsForPrefix = options.defaultNsForPrefix ?? SignedXml.defaultNsForPrefix;\n    options.signatureNode = this.signatureNode;\n\n    const canonXml = node.cloneNode(true); // Deep clone\n    let transformedXml: Node | string = canonXml;\n\n    transforms.forEach((transformName) => {\n      if (isDomNode.isNodeLike(transformedXml)) {\n        // If, after processing, `transformedNode` is a string, we can't do anymore transforms on it\n        const transform = this.findCanonicalizationAlgorithm(transformName);\n        transformedXml = transform.process(transformedXml, options);\n      }\n      //TODO: currently transform.process may return either Node or String value (enveloped transformation returns Node, exclusive-canonicalization returns String).\n      //This either needs to be more explicit in the API, or all should return the same.\n      //exclusive-canonicalization returns String since it builds the Xml by hand. If it had used xmldom it would incorrectly minimize empty tags\n      //to <x/> instead of <x></x> and also incorrectly handle some delicate line break issues.\n      //enveloped transformation returns Node since if it would return String consider this case:\n      //<x xmlns:p='ns'><p:y/></x>\n      //if only y is the node to sign then a string would be <p:y/> without the definition of the p namespace. probably xmldom toString() should have added it.\n    });\n\n    return transformedXml.toString();\n  }\n\n  /**\n   * Ensure an element has Id attribute. If not create it with unique value.\n   * Work with both normal and wssecurity Id flavour\n   */\n  private ensureHasId(node) {\n    let attr;\n\n    if (this.idMode === \"wssecurity\") {\n      attr = utils.findAttr(\n        node,\n        \"Id\",\n        \"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\",\n      );\n    } else {\n      this.idAttributes.some((idAttribute) => {\n        attr = utils.findAttr(node, idAttribute);\n        return !!attr; // This will break the loop as soon as a truthy attr is found.\n      });\n    }\n\n    if (attr) {\n      return attr.value;\n    }\n\n    //add the attribute\n    const id = `_${this.id++}`;\n\n    if (this.idMode === \"wssecurity\") {\n      node.setAttributeNS(\n        \"http://www.w3.org/2000/xmlns/\",\n        \"xmlns:wsu\",\n        \"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\",\n      );\n      node.setAttributeNS(\n        \"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\",\n        \"wsu:Id\",\n        id,\n      );\n    } else {\n      node.setAttribute(\"Id\", id);\n    }\n\n    return id;\n  }\n\n  /**\n   * Create the SignedInfo element\n   *\n   */\n  private createSignedInfo(doc, prefix) {\n    if (typeof this.canonicalizationAlgorithm !== \"string\") {\n      throw new Error(\n        \"Missing canonicalizationAlgorithm when trying to create signed info for XML\",\n      );\n    }\n    const transform = this.findCanonicalizationAlgorithm(this.canonicalizationAlgorithm);\n    const algo = this.findSignatureAlgorithm(this.signatureAlgorithm);\n    const currentPrefix = prefix ? `${prefix}:` : \"\";\n\n    let res = `<${currentPrefix}SignedInfo>`;\n    res += `<${currentPrefix}CanonicalizationMethod Algorithm=\"${transform.getAlgorithmName()}\"`;\n    if (utils.isArrayHasLength(this.inclusiveNamespacesPrefixList)) {\n      res += \">\";\n      res += `<InclusiveNamespaces PrefixList=\"${this.inclusiveNamespacesPrefixList.join(\n        \" \",\n      )}\" xmlns=\"${transform.getAlgorithmName()}\"/>`;\n      res += `</${currentPrefix}CanonicalizationMethod>`;\n    } else {\n      res += \" />\";\n    }\n    res += `<${currentPrefix}SignatureMethod Algorithm=\"${algo.getAlgorithmName()}\" />`;\n\n    // No references here - added later\n    res += `</${currentPrefix}SignedInfo>`;\n    return res;\n  }\n\n  /**\n   * Create the Signature element\n   *\n   */\n  private createSignature(prefix?: string) {\n    let xmlNsAttr = \"xmlns\";\n\n    if (prefix) {\n      xmlNsAttr += `:${prefix}`;\n      prefix += \":\";\n    } else {\n      prefix = \"\";\n    }\n\n    const signatureValueXml = `<${prefix}SignatureValue>${this.signatureValue}</${prefix}SignatureValue>`;\n    //the canonicalization requires to get a valid xml node.\n    //we need to wrap the info in a dummy signature since it contains the default namespace.\n    const dummySignatureWrapper = `<${prefix}Signature ${xmlNsAttr}=\"http://www.w3.org/2000/09/xmldsig#\">${signatureValueXml}</${prefix}Signature>`;\n\n    const doc = new xmldom.DOMParser().parseFromString(dummySignatureWrapper);\n\n    // Because we are using a dummy wrapper hack described above, we know there will be a `firstChild`\n    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n    return doc.documentElement.firstChild!;\n  }\n\n  /**\n   * Returns just the signature part, must be called only after {@link computeSignature}\n   *\n   * @returns The signature XML.\n   */\n  getSignatureXml(): string {\n    return this.signatureXml;\n  }\n\n  /**\n   * Returns the original xml with Id attributes added on relevant elements (required for validation), must be called only after {@link computeSignature}\n   *\n   * @returns The original XML with IDs.\n   */\n  getOriginalXmlWithIds(): string {\n    return this.originalXmlWithIds;\n  }\n\n  /**\n   * Returns the original xml document with the signature in it, must be called only after {@link computeSignature}\n   *\n   * @returns The signed XML.\n   */\n  getSignedXml(): string {\n    return this.signedXml;\n  }\n}\n"
  },
  {
    "path": "src/types.ts",
    "content": "/* eslint-disable no-unused-vars */\n// Type definitions for @node-saml/xml-crypto\n// Project: https://github.com/node-saml/xml-crypto#readme\n// Original definitions by: Eric Heikes <https://github.com/eheikes>\n//                          Max Chehab <https://github.com/maxchehab>\n\n/// <reference types=\"node\" />\n\nimport * as crypto from \"crypto\";\n\nexport type ErrorFirstCallback<T> = (err: Error | null, result?: T) => void;\n\nexport type CanonicalizationAlgorithmType =\n  | \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"\n  | \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"\n  | \"http://www.w3.org/2001/10/xml-exc-c14n#\"\n  | \"http://www.w3.org/2001/10/xml-exc-c14n#WithComments\"\n  | string;\n\nexport type CanonicalizationOrTransformAlgorithmType =\n  | CanonicalizationAlgorithmType\n  | \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\";\n\nexport type HashAlgorithmType =\n  | \"http://www.w3.org/2000/09/xmldsig#sha1\"\n  | \"http://www.w3.org/2001/04/xmlenc#sha256\"\n  | \"http://www.w3.org/2001/04/xmlenc#sha512\"\n  | string;\n\nexport type SignatureAlgorithmType =\n  | \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"\n  | \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\"\n  | \"http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1\"\n  | \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512\"\n  | \"http://www.w3.org/2000/09/xmldsig#hmac-sha1\"\n  | string;\n\n/**\n * @param cert the certificate as a string or array of strings (@see https://www.w3.org/TR/2008/REC-xmldsig-core-20080610/#sec-X509Data)\n * @param prefix an optional namespace alias to be used for the generated XML\n */\nexport interface GetKeyInfoContentArgs {\n  publicCert?: crypto.KeyLike;\n  prefix?: string | null;\n}\n\n/**\n * Object attributes as defined in XMLDSig spec and are emitted verbatim\n * @see https://www.w3.org/TR/xmldsig-core/#sec-Object\n */\nexport interface ObjectAttributes {\n  /** Optional ID attribute */\n  Id?: string;\n  /** Optional MIME type attribute */\n  MimeType?: string;\n  /** Optional encoding attribute */\n  Encoding?: string;\n  /** Any additional custom attributes */\n  [key: string]: string | undefined;\n}\n\n/**\n * Options for the SignedXml constructor.\n */\nexport interface SignedXmlOptions {\n  idMode?: \"wssecurity\";\n  idAttribute?: string;\n  privateKey?: crypto.KeyLike;\n  publicCert?: crypto.KeyLike;\n  signatureAlgorithm?: SignatureAlgorithmType;\n  canonicalizationAlgorithm?: CanonicalizationAlgorithmType;\n  inclusiveNamespacesPrefixList?: string | string[];\n  implicitTransforms?: ReadonlyArray<CanonicalizationOrTransformAlgorithmType>;\n  keyInfoAttributes?: Record<string, string>;\n  getKeyInfoContent?(args?: GetKeyInfoContentArgs): string | null;\n  getCertFromKeyInfo?(keyInfo?: Node | null): string | null;\n  objects?: Array<{ content: string; attributes?: ObjectAttributes }>;\n}\n\nexport interface NamespacePrefix {\n  prefix: string;\n  namespaceURI: string;\n}\n\nexport interface RenderedNamespace {\n  rendered: string;\n  newDefaultNs: string;\n}\n\nexport interface CanonicalizationOrTransformationAlgorithmProcessOptions {\n  defaultNs?: string;\n  defaultNsForPrefix?: Record<string, string>;\n  ancestorNamespaces?: NamespacePrefix[];\n  signatureNode?: Node | null;\n  inclusiveNamespacesPrefixList?: string[];\n}\n\nexport interface ComputeSignatureOptionsLocation {\n  reference?: string;\n  action?: \"append\" | \"prepend\" | \"before\" | \"after\";\n}\n\n/**\n * Options for the computeSignature method.\n *\n * - `prefix` {String} Adds a prefix for the generated signature tags\n * - `attrs` {Object} A hash of attributes and values `attrName: value` to add to the signature root node\n * - `location` {{ reference: String, action: String }}\n * - `existingPrefixes` {Object} A hash of prefixes and namespaces `prefix: namespace` already in the xml\n *   An object with a `reference` key which should\n *   contain a XPath expression, an `action` key which\n *   should contain one of the following values:\n *   `append`, `prepend`, `before`, `after`\n */\nexport interface ComputeSignatureOptions {\n  prefix?: string;\n  attrs?: Record<string, string>;\n  location?: ComputeSignatureOptionsLocation;\n  existingPrefixes?: Record<string, string>;\n}\n\n/**\n * Represents a reference node for XML digital signature.\n */\nexport interface Reference {\n  // The XPath expression that selects the data to be signed.\n  xpath?: string;\n\n  // An array of transforms to be applied to the data before signing.\n  transforms: ReadonlyArray<CanonicalizationOrTransformAlgorithmType>;\n\n  // The algorithm used to calculate the digest value of the data.\n  digestAlgorithm: HashAlgorithmType;\n\n  // The URI that identifies the data to be signed.\n  uri: string;\n\n  // Optional. The digest value of the referenced data.\n  digestValue?: unknown;\n\n  // A list of namespace prefixes to be treated as \"inclusive\" during canonicalization.\n  inclusiveNamespacesPrefixList: string[];\n\n  // Optional. Indicates whether the URI is empty.\n  isEmptyUri: boolean;\n\n  // Optional. The `Id` attribute of the reference node.\n  id?: string;\n\n  // Optional. The `Type` attribute of the reference node.\n  type?: string;\n\n  // Optional. The type of the reference node.\n  ancestorNamespaces?: NamespacePrefix[];\n\n  validationError?: Error;\n\n  getValidatedNode(xpathSelector?: string): Node | null;\n\n  signedReference?: string;\n}\n\n/** Implement this to create a new CanonicalizationOrTransformationAlgorithm */\nexport interface CanonicalizationOrTransformationAlgorithm {\n  process(\n    node: Node,\n    options: CanonicalizationOrTransformationAlgorithmProcessOptions,\n  ): Node | string;\n\n  getAlgorithmName(): CanonicalizationOrTransformAlgorithmType;\n}\n\n/** Implement this to create a new HashAlgorithm */\nexport interface HashAlgorithm {\n  getAlgorithmName(): HashAlgorithmType;\n\n  getHash(xml: string): string;\n}\n\n/** Extend this to create a new SignatureAlgorithm */\nexport interface SignatureAlgorithm {\n  /**\n   * Sign the given string using the given key\n   */\n  getSignature(signedInfo: crypto.BinaryLike, privateKey: crypto.KeyLike): string;\n  getSignature(\n    signedInfo: crypto.BinaryLike,\n    privateKey: crypto.KeyLike,\n    callback?: ErrorFirstCallback<string>,\n  ): void;\n  /**\n   * Verify the given signature of the given string using key\n   *\n   * @param key a public cert, public key, or private key can be passed here\n   */\n  verifySignature(material: string, key: crypto.KeyLike, signatureValue: string): boolean;\n  verifySignature(\n    material: string,\n    key: crypto.KeyLike,\n    signatureValue: string,\n    callback?: ErrorFirstCallback<boolean>,\n  ): void;\n\n  getAlgorithmName(): SignatureAlgorithmType;\n}\n\n/** Implement this to create a new TransformAlgorithm */\nexport interface TransformAlgorithm {\n  getAlgorithmName(): CanonicalizationOrTransformAlgorithmType;\n\n  process(node: Node): string;\n}\n\n/**\n * ### Sign\n * #### Properties\n * - {@link SignedXml#privateKey} [required]\n * - {@link SignedXml#publicCert} [optional]\n * - {@link SignedXml#signatureAlgorithm} [optional]\n * - {@link SignedXml#canonicalizationAlgorithm} [optional]\n * #### Api\n *  - {@link SignedXml#addReference}\n *  - {@link SignedXml#computeSignature}\n *  - {@link SignedXml#getSignedXml}\n *  - {@link SignedXml#getSignatureXml}\n *  - {@link SignedXml#getOriginalXmlWithIds}\n *\n * ### Verify\n * #### Properties\n * -  {@link SignedXml#publicCert} [optional]\n * #### Api\n *  - {@link SignedXml#loadSignature}\n *  - {@link SignedXml#checkSignature}\n */\n\nfunction isErrorFirstCallback<T>(\n  possibleCallback: unknown,\n): possibleCallback is ErrorFirstCallback<T> {\n  return typeof possibleCallback === \"function\";\n}\n\n/**\n * This function will add a callback version of a sync function.\n *\n * This follows the factory pattern.\n * Just call this function, passing the function that you'd like to add a callback version of.\n */\nexport function createOptionalCallbackFunction<T, A extends unknown[]>(\n  syncVersion: (...args: A) => T,\n): {\n  (...args: A): T;\n  (...args: [...A, ErrorFirstCallback<T>]): void;\n} {\n  return ((...args: A | [...A, ErrorFirstCallback<T>]) => {\n    const possibleCallback = args[args.length - 1];\n    if (isErrorFirstCallback(possibleCallback)) {\n      try {\n        const result = syncVersion(...(args.slice(0, -1) as A));\n        possibleCallback(null, result);\n      } catch (err) {\n        possibleCallback(err instanceof Error ? err : new Error(\"Unknown error\"));\n      }\n    } else {\n      return syncVersion(...(args as A));\n    }\n  }) as {\n    (...args: A): T;\n    (...args: [...A, ErrorFirstCallback<T>]): void;\n  };\n}\n"
  },
  {
    "path": "src/utils.ts",
    "content": "import * as xpath from \"xpath\";\nimport type { NamespacePrefix } from \"./types\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\nexport function isArrayHasLength(array: unknown): array is unknown[] {\n  return Array.isArray(array) && array.length > 0;\n}\n\nfunction attrEqualsExplicitly(attr: Attr, localName: string, namespace?: string) {\n  return attr.localName === localName && (attr.namespaceURI === namespace || namespace == null);\n}\n\nfunction attrEqualsImplicitly(attr: Attr, localName: string, namespace?: string, node?: Element) {\n  return (\n    attr.localName === localName &&\n    ((!attr.namespaceURI && node?.namespaceURI === namespace) || namespace == null)\n  );\n}\n\nexport function findAttr(element: Element, localName: string, namespace?: string) {\n  for (let i = 0; i < element.attributes.length; i++) {\n    const attr = element.attributes[i];\n\n    if (\n      attrEqualsExplicitly(attr, localName, namespace) ||\n      attrEqualsImplicitly(attr, localName, namespace, element)\n    ) {\n      return attr;\n    }\n  }\n  return null;\n}\n\nexport function findChildren(node: Node | Document, localName: string, namespace?: string) {\n  const element = (node as Document).documentElement ?? node;\n  const res: Element[] = [];\n  for (let i = 0; i < element.childNodes.length; i++) {\n    const child = element.childNodes[i];\n    if (\n      isDomNode.isElementNode(child) &&\n      child.localName === localName &&\n      (child.namespaceURI === namespace || namespace == null)\n    ) {\n      res.push(child);\n    }\n  }\n  return res;\n}\n\n/** @deprecated */\nexport function findChilds(node: Node | Document, localName: string, namespace?: string) {\n  return findChildren(node, localName, namespace);\n}\n\nconst xml_special_to_encoded_attribute = {\n  \"&\": \"&amp;\",\n  \"<\": \"&lt;\",\n  '\"': \"&quot;\",\n  \"\\r\": \"&#xD;\",\n  \"\\n\": \"&#xA;\",\n  \"\\t\": \"&#x9;\",\n};\n\nconst xml_special_to_encoded_text = {\n  \"&\": \"&amp;\",\n  \"<\": \"&lt;\",\n  \">\": \"&gt;\",\n  \"\\r\": \"&#xD;\",\n};\n\nexport function encodeSpecialCharactersInAttribute(attributeValue) {\n  return attributeValue.replace(/([&<\"\\r\\n\\t])/g, function (str, item) {\n    /** Special character normalization.\n     * @see:\n     * - https://www.w3.org/TR/xml-c14n#ProcessingModel (Attribute Nodes)\n     * - https://www.w3.org/TR/xml-c14n#Example-Chars\n     */\n    return xml_special_to_encoded_attribute[item];\n  });\n}\n\nexport function encodeSpecialCharactersInText(text: string): string {\n  return text.replace(/([&<>\\r])/g, function (str, item) {\n    /** Special character normalization.\n     * @see:\n     * - https://www.w3.org/TR/xml-c14n#ProcessingModel (Text Nodes)\n     * - https://www.w3.org/TR/xml-c14n#Example-Chars\n     */\n    return xml_special_to_encoded_text[item];\n  });\n}\n\n/**\n * PEM format has wide range of usages, but this library\n * is enforcing RFC7468 which focuses on PKIX, PKCS and CMS.\n *\n * https://www.rfc-editor.org/rfc/rfc7468\n *\n * PEM_FORMAT_REGEX is validating given PEM file against RFC7468 'stricttextualmsg' definition.\n *\n * With few exceptions;\n *  - 'posteb' MAY have 'eol', but it is not mandatory.\n *  - 'preeb' and 'posteb' lines are limited to 64 characters, but\n *     should not cause any issues in context of PKIX, PKCS and CMS.\n */\nexport const PEM_FORMAT_REGEX = new RegExp(\n  \"^-----BEGIN [A-Z\\x20]{1,48}-----([^-]*)-----END [A-Z\\x20]{1,48}-----$\",\n  \"s\",\n);\nexport const EXTRACT_X509_CERTS = new RegExp(\n  \"-----BEGIN CERTIFICATE-----[^-]*-----END CERTIFICATE-----\",\n  \"g\",\n);\nexport const BASE64_REGEX = new RegExp(\n  \"^(?:[A-Za-z0-9\\\\+\\\\/]{4}\\\\n{0,1})*(?:[A-Za-z0-9\\\\+\\\\/]{2}==|[A-Za-z0-9\\\\+\\\\/]{3}=)?$\",\n  \"s\",\n);\n\n/**\n * -----BEGIN [LABEL]-----\n * base64([DATA])\n * -----END [LABEL]-----\n *\n * Above is shown what PEM file looks like. As can be seen, base64 data\n * can be in single line or multiple lines.\n *\n * This function normalizes PEM presentation to;\n *  - contain PEM header and footer as they are given\n *  - normalize line endings to '\\n'\n *  - normalize line length to maximum of 64 characters\n *  - ensure that 'preeb' has line ending '\\n'\n *\n * With a couple of notes:\n *  - 'eol' is normalized to '\\n'\n *\n * @param pem The PEM string to normalize to RFC7468 'stricttextualmsg' definition\n */\nexport function normalizePem(pem: string): string {\n  return `${(\n    pem\n      .trim()\n      .replace(/(\\r\\n|\\r)/g, \"\\n\")\n      .match(/.{1,64}/g) ?? []\n  ).join(\"\\n\")}\\n`;\n}\n\n/**\n * @param pem The PEM-encoded base64 certificate to strip headers from\n */\nexport function pemToDer(pem: string): Buffer {\n  if (!PEM_FORMAT_REGEX.test(pem.trim())) {\n    throw new Error(\"Invalid PEM format.\");\n  }\n\n  return Buffer.from(\n    pem\n      .replace(/(\\r\\n|\\r)/g, \"\")\n      .replace(/-----BEGIN [A-Z\\x20]{1,48}-----\\n?/, \"\")\n      .replace(/-----END [A-Z\\x20]{1,48}-----\\n?/, \"\"),\n    \"base64\",\n  );\n}\n\n/**\n * @param der The DER-encoded base64 certificate to add PEM headers too\n * @param pemLabel The label of the header and footer to add\n */\nexport function derToPem(\n  der: string | Buffer,\n  pemLabel?: \"CERTIFICATE\" | \"PRIVATE KEY\" | \"RSA PUBLIC KEY\",\n): string {\n  const base64Der = Buffer.isBuffer(der)\n    ? der.toString(\"base64\").trim()\n    : der.replace(/(\\r\\n|\\r)/g, \"\").trim();\n\n  if (PEM_FORMAT_REGEX.test(base64Der)) {\n    return normalizePem(base64Der);\n  }\n\n  if (BASE64_REGEX.test(base64Der.replace(/ /g, \"\"))) {\n    if (pemLabel == null) {\n      throw new Error(\"PEM label is required when DER is given.\");\n    }\n    const pem = `-----BEGIN ${pemLabel}-----\\n${base64Der.replace(\n      / /g,\n      \"\",\n    )}\\n-----END ${pemLabel}-----`;\n\n    return normalizePem(pem);\n  }\n\n  throw new Error(\"Unknown DER format.\");\n}\n\nfunction collectAncestorNamespaces(\n  node: Element,\n  nsArray: NamespacePrefix[] = [],\n): NamespacePrefix[] {\n  if (!isDomNode.isElementNode(node.parentNode)) {\n    return nsArray;\n  }\n\n  const parent: Element = node.parentNode;\n\n  if (!parent) {\n    return nsArray;\n  }\n\n  if (parent.attributes && parent.attributes.length > 0) {\n    for (let i = 0; i < parent.attributes.length; i++) {\n      const attr = parent.attributes[i];\n      if (attr && attr.nodeName && attr.nodeName.search(/^xmlns:?/) !== -1) {\n        nsArray.push({\n          prefix: attr.nodeName.replace(/^xmlns:?/, \"\"),\n          namespaceURI: attr.nodeValue || \"\",\n        });\n      }\n    }\n  }\n\n  return collectAncestorNamespaces(parent, nsArray);\n}\n\nfunction findNSPrefix(subset) {\n  const subsetAttributes = subset.attributes;\n  for (let k = 0; k < subsetAttributes.length; k++) {\n    const nodeName = subsetAttributes[k].nodeName;\n    if (nodeName.search(/^xmlns:?/) !== -1) {\n      return nodeName.replace(/^xmlns:?/, \"\");\n    }\n  }\n  return subset.prefix || \"\";\n}\n\nfunction isElementSubset(docSubset: Node[]): docSubset is Element[] {\n  return docSubset.every((node) => isDomNode.isElementNode(node));\n}\n\n/**\n * Extract ancestor namespaces in order to import it to root of document subset\n * which is being canonicalized for non-exclusive c14n.\n *\n * @param doc - Usually a product from `new xmldom.DOMParser().parseFromString()`\n * @param docSubsetXpath - xpath query to get document subset being canonicalized\n * @param namespaceResolver - xpath namespace resolver\n * @returns i.e. [{prefix: \"saml\", namespaceURI: \"urn:oasis:names:tc:SAML:2.0:assertion\"}]\n */\nexport function findAncestorNs(\n  doc: Document,\n  docSubsetXpath?: string,\n  namespaceResolver?: XPathNSResolver,\n): NamespacePrefix[] {\n  if (docSubsetXpath == null) {\n    return [];\n  }\n\n  const docSubset = xpath.selectWithResolver(docSubsetXpath, doc, namespaceResolver);\n\n  if (!isArrayHasLength(docSubset)) {\n    return [];\n  }\n\n  if (!isElementSubset(docSubset)) {\n    throw new Error(\"Document subset must be list of elements\");\n  }\n\n  // Remove duplicate on ancestor namespace\n  const ancestorNs = collectAncestorNamespaces(docSubset[0]);\n  const ancestorNsWithoutDuplicate: NamespacePrefix[] = [];\n  for (let i = 0; i < ancestorNs.length; i++) {\n    let notOnTheList = true;\n    for (const v in ancestorNsWithoutDuplicate) {\n      if (ancestorNsWithoutDuplicate[v].prefix === ancestorNs[i].prefix) {\n        notOnTheList = false;\n        break;\n      }\n    }\n\n    if (notOnTheList) {\n      ancestorNsWithoutDuplicate.push(ancestorNs[i]);\n    }\n  }\n\n  // Remove namespaces which are already declared in the subset with the same prefix\n  const returningNs: NamespacePrefix[] = [];\n  const subsetNsPrefix = findNSPrefix(docSubset[0]);\n  for (const ancestorNs of ancestorNsWithoutDuplicate) {\n    if (ancestorNs.prefix !== subsetNsPrefix) {\n      returningNs.push(ancestorNs);\n    }\n  }\n\n  return returningNs;\n}\n\nexport function validateDigestValue(digest, expectedDigest) {\n  const buffer = Buffer.from(digest, \"base64\");\n  const expectedBuffer = Buffer.from(expectedDigest, \"base64\");\n\n  if (typeof buffer.equals === \"function\") {\n    return buffer.equals(expectedBuffer);\n  }\n\n  if (buffer.length !== expectedBuffer.length) {\n    return false;\n  }\n\n  for (let i = 0; i < buffer.length; i++) {\n    if (buffer[i] !== expectedBuffer[i]) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n// Check if the given node is descendant of the given parent node\nexport function isDescendantOf(node: Node, parent: Node): boolean {\n  if (!node || !parent) {\n    return false;\n  }\n\n  let currentNode: Node | null = node.parentNode;\n\n  while (currentNode) {\n    if (currentNode === parent) {\n      return true;\n    }\n    currentNode = currentNode.parentNode;\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "test/c14n-non-exclusive-unit-tests.spec.ts",
    "content": "import { expect } from \"chai\";\n\nimport { C14nCanonicalization } from \"../src/c14n-canonicalization\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as xpath from \"xpath\";\nimport * as utils from \"../src/utils\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\nconst test_C14nCanonicalization = function (xml, xpathArg, expected) {\n  const doc = new xmldom.DOMParser().parseFromString(xml);\n  const node = xpath.select1(xpathArg, doc);\n  const can = new C14nCanonicalization();\n\n  isDomNode.assertIsNodeLike(node);\n  const result = can\n    .process(node, {\n      ancestorNamespaces: utils.findAncestorNs(doc, xpathArg),\n    })\n    .toString();\n\n  expect(result).to.equal(expected);\n};\n\nconst test_findAncestorNs = function (xml, xpath, expected) {\n  const doc = new xmldom.DOMParser().parseFromString(xml);\n  const result = utils.findAncestorNs(doc, xpath);\n\n  expect(result).to.deep.equal(expected);\n};\n\ndescribe(\"C14N non-exclusive canonicalization tests\", function () {\n  it(\"findAncestorNs: Correctly picks up root ancestor namespace\", function () {\n    const xml = \"<root xmlns:aaa='bbb'><child1><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = [{ prefix: \"aaa\", namespaceURI: \"bbb\" }];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  it(\"findAncestorNs: Correctly picks up intermediate ancestor namespace\", function () {\n    const xml = \"<root><child1 xmlns:aaa='bbb'><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = [{ prefix: \"aaa\", namespaceURI: \"bbb\" }];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  it(\"findAncestorNs: Correctly picks up multiple ancestor namespaces declared in the one same element\", function () {\n    const xml = \"<root xmlns:aaa='bbb' xmlns:ccc='ddd'><child1><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = [\n      { prefix: \"aaa\", namespaceURI: \"bbb\" },\n      { prefix: \"ccc\", namespaceURI: \"ddd\" },\n    ];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  it(\"findAncestorNs: Correctly picks up multiple ancestor namespaces scattered among depth\", function () {\n    const xml = \"<root xmlns:aaa='bbb'><child1 xmlns:ccc='ddd'><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = [\n      { prefix: \"ccc\", namespaceURI: \"ddd\" },\n      { prefix: \"aaa\", namespaceURI: \"bbb\" },\n    ];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  it(\"findAncestorNs: Correctly picks up multiple ancestor namespaces without duplicate\", function () {\n    const xml = \"<root xmlns:ccc='bbb'><child1 xmlns:ccc='bbb'><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = [{ prefix: \"ccc\", namespaceURI: \"bbb\" }];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  it(\"findAncestorNs: Correctly eliminates duplicate prefix\", function () {\n    const xml = \"<root xmlns:ccc='bbb'><child1 xmlns:ccc='AAA'><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = [{ prefix: \"ccc\", namespaceURI: \"AAA\" }];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  it(\"findAncestorNs: Exclude namespace which is already declared with same prefix on target node\", function () {\n    const xml =\n      \"<root xmlns:ccc='bbb'><child1 xmlns:ccc='AAA'><child2 xmlns:ccc='AAA'></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = [];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  it(\"findAncestorNs: Ignores namespace declared in the target xpath node\", function () {\n    const xml = \"<root xmlns:aaa='bbb'><child1><child2 xmlns:ccc='ddd'></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = [{ prefix: \"aaa\", namespaceURI: \"bbb\" }];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  it(\"findAncestorNs: Should find namespace without prefix\", function () {\n    const xml =\n      \"<root xmlns='bbb'><child1><ds:child2 xmlns:ds='ddd'><ds:child3></ds:child3></ds:child2></child1></root>\";\n    const xpath = \"//*[local-name()='child2']\";\n    const expected = [{ prefix: \"\", namespaceURI: \"bbb\" }];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  it(\"findAncestorNs: Should not find namespace when both has no prefix\", function () {\n    const xml = \"<root xmlns='bbb'><child1><child2 xmlns='ddd'></child2></child1></root>\";\n    const xpath = \"//*[local-name()='child2']\";\n    const expected = [];\n\n    test_findAncestorNs(xml, xpath, expected);\n  });\n\n  // Tests for c14nCanonicalization\n  it(\"C14n: Correctly picks up root ancestor namespace\", function () {\n    const xml = \"<root xmlns:aaa='bbb'><child1><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = '<child2 xmlns:aaa=\"bbb\"></child2>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: Correctly picks up intermediate ancestor namespace\", function () {\n    const xml = \"<root><child1 xmlns:aaa='bbb'><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = '<child2 xmlns:aaa=\"bbb\"></child2>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: Correctly picks up multiple ancestor namespaces declared in the one same element\", function () {\n    const xml = \"<root xmlns:aaa='bbb' xmlns:ccc='ddd'><child1><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = '<child2 xmlns:aaa=\"bbb\" xmlns:ccc=\"ddd\"></child2>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: Correctly picks up multiple ancestor namespaces scattered among depth\", function () {\n    const xml = \"<root xmlns:aaa='bbb'><child1 xmlns:ccc='ddd'><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = '<child2 xmlns:aaa=\"bbb\" xmlns:ccc=\"ddd\"></child2>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: Correctly picks up multiple ancestor namespaces without duplicate\", function () {\n    const xml = \"<root xmlns:ccc='bbb'><child1 xmlns:ccc='bbb'><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = '<child2 xmlns:ccc=\"bbb\"></child2>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: Correctly eliminates duplicate prefix\", function () {\n    const xml = \"<root xmlns:ccc='bbb'><child1 xmlns:ccc='AAA'><child2></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = '<child2 xmlns:ccc=\"AAA\"></child2>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: Exclude namespace which is already declared with same prefix on target node\", function () {\n    const xml =\n      \"<root xmlns:ccc='bbb'><child1 xmlns:ccc='AAA'><child2 xmlns:ccc='AAA'></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = '<child2 xmlns:ccc=\"AAA\"></child2>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: Preserve namespace declared in the target xpath node\", function () {\n    const xml = '<root xmlns:aaa=\"bbb\"><child1><child2 xmlns:ccc=\"ddd\"></child2></child1></root>';\n    const xpath = \"/root/child1/child2\";\n    const expected = '<child2 xmlns:aaa=\"bbb\" xmlns:ccc=\"ddd\"></child2>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: Don't redeclare an attribute's namespace prefix if already in scope\", function () {\n    const xml =\n      \"<root xmlns:aaa='bbb'><child1><child2 xmlns:aaa='bbb' aaa:foo='bar'></child2></child1></root>\";\n    const xpath = \"/root/child1/child2\";\n    const expected = '<child2 xmlns:aaa=\"bbb\" aaa:foo=\"bar\"></child2>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: Don't declare an attribute's namespace prefix if in scope from parent\", function () {\n    const xml =\n      \"<root xmlns:aaa='bbb'><child1><child2><child3 aaa:foo='bar'></child3></child2></child1></root>\";\n    const xpath = \"/root/child1\";\n    const expected =\n      '<child1 xmlns:aaa=\"bbb\"><child2><child3 aaa:foo=\"bar\"></child3></child2></child1>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n\n  it(\"C14n: should not has colon when parent namespace has no prefix\", function () {\n    const xml =\n      \"<root xmlns='bbb'><child1><cc:child2 xmlns:cc='ddd'><cc:child3></cc:child3></cc:child2></child1></root>\";\n    const xpath = \"//*[local-name()='child3']\";\n    const expected = '<cc:child3 xmlns=\"bbb\" xmlns:cc=\"ddd\"></cc:child3>';\n\n    test_C14nCanonicalization(xml, xpath, expected);\n  });\n});\n"
  },
  {
    "path": "test/c14nWithComments-unit-tests.spec.ts",
    "content": "import { expect } from \"chai\";\n\nimport { ExclusiveCanonicalizationWithComments as c14nWithComments } from \"../src/exclusive-canonicalization\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as xpath from \"xpath\";\nimport { SignedXml } from \"../src/index\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\nconst compare = function (xml, xpathArg, expected, inclusiveNamespacesPrefixList?: string[]) {\n  const doc = new xmldom.DOMParser().parseFromString(xml);\n  const elem = xpath.select1(xpathArg, doc);\n  const can = new c14nWithComments();\n  isDomNode.assertIsElementNode(elem);\n  const result = can.process(elem, { inclusiveNamespacesPrefixList }).toString();\n  expect(result).to.equal(expected);\n};\n\ndescribe(\"Exclusive canonicalization with comments\", function () {\n  it(\"Exclusive canonicalization works on xml with no namespaces\", function () {\n    compare(\"<root><child>123</child></root>\", \"//*\", \"<root><child>123</child></root>\");\n  });\n\n  it(\"Exclusive canonicalization works on inner xpath\", function () {\n    compare(\"<root><child>123</child></root>\", \"//*[local-name(.)='child']\", \"<child>123</child>\");\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespaces defined in output nodes\", function () {\n    compare(\n      '<root><p:child xmlns:p=\"s\"><inner>123</inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:p=\"s\"><inner>123</inner></p:child>',\n    );\n  });\n\n  it(\"element used prefixed ns which is also the default\", function () {\n    compare(\n      '<root><child xmlns=\"s\"><p:inner xmlns:p=\"s\">123</p:inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"s\"><p:inner xmlns:p=\"s\">123</p:inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespaces defined in output nodes. ns definition is not duplicated on each usage\", function () {\n    compare(\n      '<root><p:child xmlns:p=\"ns\"><p:inner>123</p:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:p=\"ns\"><p:inner>123</p:inner></p:child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespaces defined in output nodes but before used\", function () {\n    compare(\n      '<root><child xmlns:p=\"ns\"><p:inner>123</p:inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><p:inner xmlns:p=\"ns\">123</p:inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespaces defined outside output nodes\", function () {\n    compare(\n      '<root xmlns:p=\"ns\"><p:child>123</p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:p=\"ns\">123</p:child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespace defined in inclusive list\", function () {\n    compare(\n      '<root xmlns:p=\"ns\"><p:child xmlns:inclusive=\"ns2\"><inclusive:inner xmlns:inclusive=\"ns2\">123</inclusive:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:inclusive=\"ns2\" xmlns:p=\"ns\"><inclusive:inner>123</inclusive:inner></p:child>',\n      [\"inclusive\"],\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with multiple prefixed namespaces defined in inclusive list\", function () {\n    compare(\n      '<root xmlns:p=\"ns\"><p:child xmlns:inclusive=\"ns2\" xmlns:inclusive2=\"ns3\"><inclusive:inner xmlns:inclusive=\"ns2\">123</inclusive:inner><inclusive2:inner xmlns:inclusive2=\"ns3\">456</inclusive2:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:inclusive=\"ns2\" xmlns:inclusive2=\"ns3\" xmlns:p=\"ns\"><inclusive:inner>123</inclusive:inner><inclusive2:inner>456</inclusive2:inner></p:child>',\n      [\"inclusive\", \"inclusive2\"],\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespace defined in inclusive list defined outside output nodes\", function () {\n    compare(\n      '<root xmlns:p=\"ns\" xmlns:inclusive=\"ns2\"><p:child><inclusive:inner xmlns:inclusive=\"ns2\">123</inclusive:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:p=\"ns\"><inclusive:inner xmlns:inclusive=\"ns2\">123</inclusive:inner></p:child>',\n      [\"inclusive\"],\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespace defined in inclusive list used on attribute\", function () {\n    compare(\n      '<root xmlns:p=\"ns\"><p:child xmlns:inclusive=\"ns2\"><p:inner foo=\"inclusive:bar\">123</p:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:inclusive=\"ns2\" xmlns:p=\"ns\"><p:inner foo=\"inclusive:bar\">123</p:inner></p:child>',\n      [\"inclusive\"],\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with default namespace inside output nodes\", function () {\n    compare(\n      '<root><child><inner xmlns=\"ns\">123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><inner xmlns=\"ns\">123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with multiple different default namespaces\", function () {\n    compare(\n      '<root xmlns=\"ns1\"><child xmlns=\"ns2\"><inner xmlns=\"ns3\">123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"ns2\"><inner xmlns=\"ns3\">123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with multiple similar default namespaces\", function () {\n    compare(\n      '<root xmlns=\"ns1\"><child xmlns=\"ns2\"><inner xmlns=\"ns2\">123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"ns2\"><inner>123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with default namespace outside output nodes\", function () {\n    compare(\n      '<root xmlns=\"ns\"><child><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"ns\"><inner>123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works when prefixed namespace is defined in output nodes not in the parent chain of who needs it\", function () {\n    compare(\n      '<root><child><p:inner1 xmlns:p=\"foo\" /><p:inner2 xmlns:p=\"foo\" /></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><p:inner1 xmlns:p=\"foo\"></p:inner1><p:inner2 xmlns:p=\"foo\"></p:inner2></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with unordered attributes\", function () {\n    compare(\n      '<root><child xmlns:z=\"ns2\" xmlns:p=\"ns1\" p:name=\"val1\" z:someAttr=\"zval\" Id=\"value\" z:testAttr=\"ztestAttr\" someAttr=\"someAttrVal\" p:address=\"val2\"><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns:p=\"ns1\" xmlns:z=\"ns2\" Id=\"value\" someAttr=\"someAttrVal\" p:address=\"val2\" p:name=\"val1\" z:someAttr=\"zval\" z:testAttr=\"ztestAttr\"><inner>123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization sorts upper case attributes before lower case\", function () {\n    compare('<x id=\"\" Id=\"\"></x>', \"//*[local-name(.)='x']\", '<x Id=\"\" id=\"\"></x>');\n  });\n\n  it(\"C14N#WithComments retains Comments\", function () {\n    compare(\n      '<x id=\"\" Id=\"\"><!-- Comment --></x>',\n      \"//*[local-name(.)='x']\",\n      '<x Id=\"\" id=\"\"><!-- Comment --></x>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with attributes with different namespace than element\", function () {\n    compare(\n      '<root><child xmlns=\"bla\" xmlns:p=\"foo\" p:attr=\"val\"><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"bla\" xmlns:p=\"foo\" p:attr=\"val\"><inner>123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with attribute and element values with special characters\", function () {\n    compare(\n      '<root><child><inner attr=\"&amp;11\">&amp;11</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><inner attr=\"&amp;11\">&amp;11</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization preserves white space in values\", function () {\n    compare(\n      \"<root><child><inner>12\\n3\\t</inner></child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>12\\n3\\t</inner></child>\",\n    );\n  });\n\n  it(\"Exclusive canonicalization preserves white space between elements\", function () {\n    compare(\n      \"<root><child><inner>123</inner>\\n</child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>123</inner>\\n</child>\",\n    );\n  });\n\n  it(\"Exclusive canonicalization turns empty element to start-end tag pairs\", function () {\n    compare(\n      \"<root><child><inner /></child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner></inner></child>\",\n    );\n  });\n\n  it(\"Exclusive canonicalization preserves empty start-end tag pairs\", function () {\n    compare(\n      \"<root><child><inner></inner></child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner></inner></child>\",\n    );\n  });\n\n  it(\"Exclusive canonicalization with empty default namespace outside output nodes\", function () {\n    compare(\n      '<root xmlns=\"\"><child><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>123</inner></child>\",\n    );\n  });\n\n  /* \n  TODO: Uncomment this when this issue is fixed\n    it(\"Exclusive canonicalization removal of whitespace between PITarget and its data\", function () {\n      compare(\n        \"<root xmlns=\\\"\\\"><child><inner>123</inner></child></root><?pi-without-data   ?>\",\n        \"//*[local-name(.)='child']\",\n        \"<child><inner>123</inner></child><?pi-without-data?>\");\n    });\n    */\n\n  it(\"Exclusive canonicalization with empty default namespace inside output nodes\", function () {\n    compare(\n      '<root xmlns=\"foo\"><child><inner xmlns=\"\">123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"foo\"><inner xmlns=\"\">123</inner></child>',\n    );\n  });\n\n  it(\"The XML declaration and document type declaration (DTD) are removed\", function () {\n    compare(\n      '<?xml version=\"1.0\" encoding=\"utf-8\"?><root><child><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>123</inner></child>\",\n    );\n  });\n\n  /* \n  TODO: Uncomment this when this issue is fixed\n    it(\"The XML declaration and document type declaration (DTD) are removed, stylesheet retained\", function () {\n      compare(\n        \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><?xml-stylesheet   href=\\\"doc.xsl\\\"   type=\\\"text/xsl\\\"   ?><root><child><inner>123</inner></child></root>\",\n        \"//*[local-name(.)='child']\",\n        \"<?xml-stylesheet   href=\\\"doc.xsl\\\"   type=\\\"text/xsl\\\"   ?><child><inner>123</inner></child>\");\n    });\n    */\n\n  it(\"Attribute value delimiters are set to quotation marks (double quotes)\", function () {\n    compare(\n      \"<root><child xmlns='ns'><inner attr='value'>123 </inner></child></root>\",\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"ns\"><inner attr=\"value\">123 </inner></child>',\n    );\n  });\n\n  it(\"CDATA sections are replaced with their character content\", function () {\n    compare(\n      \"<root><child><inner><![CDATA[foo & bar in the <x>123</x>]]></inner></child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>foo &amp; bar in the &lt;x&gt;123&lt;/x&gt;</inner></child>\",\n    );\n  });\n\n  it(\"SignedInfo canonization\", function () {\n    compare(\n      '<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"><soap:Header><wsa:Action wsu:Id=\"Id-fbcf79b7-9c1b-4e51-b3da-7d6c237be1ec\">http://stockservice.contoso.com/wse/samples/2003/06/StockQuoteRequest</wsa:Action><wsa:MessageID wsu:Id=\"Id-02b76fe1-945c-4e26-a8a5-6650285bbd4c\">uuid:6250c037-bcde-40ab-82b3-3a08efc86cdc</wsa:MessageID><wsa:ReplyTo wsu:Id=\"Id-ccc937f4-8ec8-416a-b97b-0b612a69b040\"><wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:Address></wsa:ReplyTo><wsa:To wsu:Id=\"Id-fa48ae82-88bb-4bf1-9c0d-4eb1de66c4fc\">http://localhost:8889/</wsa:To><wsse:Security soap:mustUnderstand=\"1\"><wsu:Timestamp wsu:Id=\"Timestamp-4d2cce4a-39fb-4d7d-b0d5-17d583255ef5\"><wsu:Created>2008-09-01T17:44:21Z</wsu:Created><wsu:Expires>2008-09-01T17:49:21Z</wsu:Expires></wsu:Timestamp><wsse:BinarySecurityToken ValueType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3\" EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"SecurityToken-d68c34d4-be89-4a29-aecc-971bce003ed3\">MIIBxDCCAW6gAwIBAgIQxUSXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BAQQFADAWMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ3NTlaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0Q2xpZW50MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+L6aB9x928noY4+0QBsXnxkQE4quJl7c3PUPdVu7k9A02hRG481XIfWhrDY5i7OEB7KGW7qFJotLLeMec/UkKUwCgv3VvJrs2nE9xO3SSWIdNzADukYh+Cxt+FUU6tUkDeqg7dqwivOXhuOTRyOI3HqbWTbumaLdc8jufz2LhaQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcNAQEEBQADQQAfIbnMPVYkNNfX1tG1F+qfLhHwJdfDUZuPyRPucWF5qkh6sSdWVBY5sT/txBnVJGziyO8DPYdu2fPMER8ajJfl</wsse:BinarySecurityToken><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" /><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\" /><Reference URI=\"#Id-fbcf79b7-9c1b-4e51-b3da-7d6c237be1ec\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>+465BlJx5xOfHsIFezQt0MS1vZQ=</DigestValue></Reference><Reference URI=\"#Id-02b76fe1-945c-4e26-a8a5-6650285bbd4c\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>jEe8rnaaqBWZQe+xHBQXriVG99o=</DigestValue></Reference><Reference URI=\"#Id-ccc937f4-8ec8-416a-b97b-0b612a69b040\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>W45ginYdBVqOqEaqPI2piZMPReA=</DigestValue></Reference><Reference URI=\"#Id-fa48ae82-88bb-4bf1-9c0d-4eb1de66c4fc\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>m2VlWz/ZDTWL7FREHK+wpKhvjJM=</DigestValue></Reference><Reference URI=\"#Timestamp-4d2cce4a-39fb-4d7d-b0d5-17d583255ef5\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>Qws229qmAzSTZ4OKmAUWgl0PWWo=</DigestValue></Reference><Reference URI=\"#Id-0175a715-4db3-4886-8af1-991b1472e7f4\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>iEazGnkPY5caCWVZOHyR87CZ1h0=</DigestValue></Reference></SignedInfo><SignatureValue>Fkm7AbwiJCiOzY8ldfuA9pTW1G+EtE+UX4Cv7SoMIqeUdfWRDVHZpJAQyf7aoQnlpJNV/3k9L1PT6rJbfV478CkULJENPLm1m0fmDeLzhIHDEANuzp/AirC60tMD5jCARb4B4Nr/6bTmoyDQsTY8VLRiiINng7Mpweg1FZvd8a0=</SignatureValue><KeyInfo><wsse:SecurityTokenReference><wsse:Reference URI=\"#SecurityToken-d68c34d4-be89-4a29-aecc-971bce003ed3\" ValueType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3\" /></wsse:SecurityTokenReference></KeyInfo></Signature></wsse:Security></soap:Header><soap:Body wsu:Id=\"Id-0175a715-4db3-4886-8af1-991b1472e7f4\"><StockQuoteRequest xmlns=\"http://stockservice.contoso.com/wse/samples/2003/06\"><symbols><Symbol>FABRIKAM</Symbol></symbols></StockQuoteRequest></soap:Body></soap:Envelope>',\n      \"//*[local-name(.)='SignedInfo']\",\n      '<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><ds:CanonicalizationMethod xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></ds:CanonicalizationMethod><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"></SignatureMethod><Reference URI=\"#Id-fbcf79b7-9c1b-4e51-b3da-7d6c237be1ec\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>+465BlJx5xOfHsIFezQt0MS1vZQ=</DigestValue></Reference><Reference URI=\"#Id-02b76fe1-945c-4e26-a8a5-6650285bbd4c\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>jEe8rnaaqBWZQe+xHBQXriVG99o=</DigestValue></Reference><Reference URI=\"#Id-ccc937f4-8ec8-416a-b97b-0b612a69b040\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>W45ginYdBVqOqEaqPI2piZMPReA=</DigestValue></Reference><Reference URI=\"#Id-fa48ae82-88bb-4bf1-9c0d-4eb1de66c4fc\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>m2VlWz/ZDTWL7FREHK+wpKhvjJM=</DigestValue></Reference><Reference URI=\"#Timestamp-4d2cce4a-39fb-4d7d-b0d5-17d583255ef5\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>Qws229qmAzSTZ4OKmAUWgl0PWWo=</DigestValue></Reference><Reference URI=\"#Id-0175a715-4db3-4886-8af1-991b1472e7f4\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>iEazGnkPY5caCWVZOHyR87CZ1h0=</DigestValue></Reference></SignedInfo>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on complex xml\", function () {\n    compare(\n      '<?xml version=\"1.0\" encoding=\"utf-8\"?>\\n' +\n        '<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\">\\n' +\n        \"  <Body>\\n\" +\n        '    <ACORD xmlns=\"http://www.ACORD.org/standards/PC_Surety/ACORD1.10.0/xml/\">\\n' +\n        \"      <SignonRq>\\n\" +\n        \"        <SessKey />\\n\" +\n        \"        <ClientDt />\\n\" +\n        \"        <CustLangPref />\\n\" +\n        \"        <ClientApp>\\n\" +\n        '          <Org p6:type=\"AssignedIdentifier\" id=\"wewe\" xmlns:p6=\"http://www.w3.org/2001/XMLSchema-instance\" />\\n' +\n        \"          <Name />\\n\" +\n        \"          <Version />\\n\" +\n        \"        </ClientApp>\\n\" +\n        \"        <ProxyClient>\\n\" +\n        '          <Org p6:type=\"AssignedIdentifier\" id=\"erer\" xmlns:p6=\"http://www.w3.org/2001/XMLSchema-instance\" />\\n' +\n        \"          <Name>ererer</Name>\\n\" +\n        \"          <Version>dfdf</Version>\\n\" +\n        \"        </ProxyClient>\\n\" +\n        \"      </SignonRq>\\n\" +\n        \"      <InsuranceSvcRq>\\n\" +\n        \"        <RqUID />\\n\" +\n        '        <SPName id=\"rter\" />\\n' +\n        '        <QuickHit xmlns=\"urn:com.thehartford.bi.acord-extensions\">\\n' +\n        '          <StateProvCd CodeListRef=\"dfdf\" xmlns=\"http://www.ACORD.org/standards/PC_Surety/ACORD1.10.0/xml/\" />\\n' +\n        \"        </QuickHit>\\n\" +\n        \"        <WorkCompPolicyQuoteInqRq>\\n\" +\n        \"          <RqUID>erer</RqUID>\\n\" +\n        '          <TransactionRequestDt id=\"erer\" />\\n' +\n        \"          <CurCd />\\n\" +\n        '          <BroadLOBCd id=\"erer\" />\\n' +\n        \"          <InsuredOrPrincipal>\\n\" +\n        \"            <ItemIdInfo>\\n\" +\n        '              <AgencyId id=\"3434\" />\\n' +\n        \"              <OtherIdentifier>\\n\" +\n        '                <CommercialName id=\"3434\" />\\n' +\n        \"                <ContractTerm>\\n\" +\n        '                  <EffectiveDt id=\"3434\" />\\n' +\n        '                  <StartTime id=\"3434\" />\\n' +\n        \"                </ContractTerm>\\n\" +\n        \"              </OtherIdentifier>\\n\" +\n        \"            </ItemIdInfo>\\n\" +\n        \"          </InsuredOrPrincipal>\\n\" +\n        \"          <InsuredOrPrincipal>\\n\" +\n        \"          </InsuredOrPrincipal>\\n\" +\n        \"          <CommlPolicy>\\n\" +\n        '            <PolicyNumber id=\"3434\" />\\n' +\n        \"            <LOBCd />\\n\" +\n        \"          </CommlPolicy>\\n\" +\n        \"          <WorkCompLineBusiness>\\n\" +\n        \"            <LOBCd />\\n\" +\n        \"            <WorkCompRateState>\\n\" +\n        \"              <WorkCompLocInfo>\\r\" +\n        \"              </WorkCompLocInfo>\\n\" +\n        \"            </WorkCompRateState>\\n\" +\n        \"          </WorkCompLineBusiness>\\n\" +\n        '          <RemarkText IdRef=\"\">\\n' +\n        \"          </RemarkText>\\n\" +\n        '          <RemarkText IdRef=\"2323\" id=\"3434\">\\n' +\n        \"          </RemarkText>\\n\" +\n        \"        </WorkCompPolicyQuoteInqRq>\\n\" +\n        \"      </InsuranceSvcRq>\\n\" +\n        \"    </ACORD>\\n\" +\n        \"  </Body>\\n\" +\n        \"</Envelope>\",\n      \"//*[local-name(.)='Body']\",\n      '<Body xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\">\\n    <ACORD xmlns=\"http://www.ACORD.org/standards/PC_Surety/ACORD1.10.0/xml/\">\\n      <SignonRq>\\n        <SessKey></SessKey>\\n        <ClientDt></ClientDt>\\n        <CustLangPref></CustLangPref>\\n        <ClientApp>\\n          <Org xmlns:p6=\"http://www.w3.org/2001/XMLSchema-instance\" id=\"wewe\" p6:type=\"AssignedIdentifier\"></Org>\\n          <Name></Name>\\n          <Version></Version>\\n        </ClientApp>\\n        <ProxyClient>\\n          <Org xmlns:p6=\"http://www.w3.org/2001/XMLSchema-instance\" id=\"erer\" p6:type=\"AssignedIdentifier\"></Org>\\n          <Name>ererer</Name>\\n          <Version>dfdf</Version>\\n        </ProxyClient>\\n      </SignonRq>\\n      <InsuranceSvcRq>\\n        <RqUID></RqUID>\\n        <SPName id=\"rter\"></SPName>\\n        <QuickHit xmlns=\"urn:com.thehartford.bi.acord-extensions\">\\n          <StateProvCd xmlns=\"http://www.ACORD.org/standards/PC_Surety/ACORD1.10.0/xml/\" CodeListRef=\"dfdf\"></StateProvCd>\\n        </QuickHit>\\n        <WorkCompPolicyQuoteInqRq>\\n          <RqUID>erer</RqUID>\\n          <TransactionRequestDt id=\"erer\"></TransactionRequestDt>\\n          <CurCd></CurCd>\\n          <BroadLOBCd id=\"erer\"></BroadLOBCd>\\n          <InsuredOrPrincipal>\\n            <ItemIdInfo>\\n              <AgencyId id=\"3434\"></AgencyId>\\n              <OtherIdentifier>\\n                <CommercialName id=\"3434\"></CommercialName>\\n                <ContractTerm>\\n                  <EffectiveDt id=\"3434\"></EffectiveDt>\\n                  <StartTime id=\"3434\"></StartTime>\\n                </ContractTerm>\\n              </OtherIdentifier>\\n            </ItemIdInfo>\\n          </InsuredOrPrincipal>\\n          <InsuredOrPrincipal>\\n          </InsuredOrPrincipal>\\n          <CommlPolicy>\\n            <PolicyNumber id=\"3434\"></PolicyNumber>\\n            <LOBCd></LOBCd>\\n          </CommlPolicy>\\n          <WorkCompLineBusiness>\\n            <LOBCd></LOBCd>\\n            <WorkCompRateState>\\n              <WorkCompLocInfo>\\n              </WorkCompLocInfo>\\n            </WorkCompRateState>\\n          </WorkCompLineBusiness>\\n          <RemarkText IdRef=\"\">\\n          </RemarkText>\\n          <RemarkText IdRef=\"2323\" id=\"3434\">\\n          </RemarkText>\\n        </WorkCompPolicyQuoteInqRq>\\n      </InsuranceSvcRq>\\n    </ACORD>\\n  </Body>',\n    );\n  });\n\n  it(\"Multiple Canonicalization with namespace definition outside of signed element\", function () {\n    const doc = new xmldom.DOMParser().parseFromString(\n      '<x xmlns:p=\"myns\"><p:y><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"></ds:Signature></p:y></x>',\n    );\n    const node = xpath.select1(\"//*[local-name(.)='y']\", doc);\n    isDomNode.assertIsNodeLike(node);\n    const sig = new SignedXml();\n    const res = sig.getCanonXml(\n      [\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      ],\n      node,\n    );\n    expect(res).to.equal('<p:y xmlns:p=\"myns\"></p:y>');\n  });\n\n  it(\"Enveloped-signature canonicalization respects current node\", function () {\n    // older versions of enveloped-signature removed the first signature in the whole doc, but should\n    //   be the signature inside the current node if we want to be able to verify multiple signatures\n    //   in a document.\n    const xml =\n      '<x><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" /><y><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" /></y></x>';\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const node = xpath.select1(\"//*[local-name(.)='y']\", doc);\n    const sig = new SignedXml();\n    const transforms = [\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"];\n    isDomNode.assertIsNodeLike(node);\n    const res = sig.getCanonXml(transforms, node);\n    expect(res).to.equal(\"<y/>\");\n  });\n\n  it(\"The XML canonicalization method processes a node-set by imposing the following additional document order rules on the namespace and attribute nodes of each element: \\\n  - An element's namespace and attribute nodes have a document order position greater than the element but less than any child node of the element. \\\n    Namespace nodes have a lesser document order position than attribute nodes. \\\n  - An element's namespace nodes are sorted lexicographically by local name (the default namespace node, if one exists, has no local name and is therefore lexicographically least). \\\n  - An element's attribute nodes are sorted lexicographically with namespace URI as the primary key and local name as the secondary key (an empty namespace URI is lexicographically least). \\\n    Lexicographic comparison, which orders strings from least to greatest alphabetically, is based on the UCS codepoint values, which is equivalent to lexicographic ordering based on UTF-8.\", function () {\n    compare(\n      '<root xmlns:b=\"moo\" b:attr1=\"a1\" a:attr1=\"a1\" b:attr4=\"b4\" xmlns=\"foo\" b:attr3=\"a3\" xmlns:a=\"zoo\"></root>',\n      \"//*[local-name(.)='root']\",\n      '<root xmlns=\"foo\" xmlns:a=\"zoo\" xmlns:b=\"moo\" b:attr1=\"a1\" b:attr3=\"a3\" b:attr4=\"b4\" a:attr1=\"a1\"></root>',\n    );\n  });\n\n  it(\"saml attributed order (bug #25)\", function () {\n    compare(\n      '<root xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" samlp:a=\"1\" saml:a=\"1\"></root>',\n      \"//*[local-name(.)='root']\",\n      '<root xmlns=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" saml:a=\"1\" samlp:a=\"1\"></root>',\n    );\n  });\n});\n"
  },
  {
    "path": "test/canonicalization-unit-tests.spec.ts",
    "content": "import { expect } from \"chai\";\n\nimport { ExclusiveCanonicalization } from \"../src/exclusive-canonicalization\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as xpath from \"xpath\";\nimport { SignedXml } from \"../src/index\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\nconst compare = function (\n  xml: string,\n  xpathArg: string,\n  expected: string,\n  inclusiveNamespacesPrefixList?: string[],\n  defaultNsForPrefix?: Record<string, string>,\n) {\n  const doc = new xmldom.DOMParser().parseFromString(xml);\n  const elem = xpath.select1(xpathArg, doc);\n  const can = new ExclusiveCanonicalization();\n  isDomNode.assertIsElementNode(elem);\n  const result = can\n    .process(elem, {\n      inclusiveNamespacesPrefixList,\n      defaultNsForPrefix,\n    })\n    .toString();\n\n  expect(expected).to.equal(result);\n};\n\ndescribe(\"Canonicalization unit tests\", function () {\n  it(\"Exclusive canonicalization works on xml with no namespaces\", function () {\n    compare(\"<root><child>123</child></root>\", \"//*\", \"<root><child>123</child></root>\");\n  });\n\n  it(\"Exclusive canonicalization works on inner xpath\", function () {\n    compare(\"<root><child>123</child></root>\", \"//*[local-name(.)='child']\", \"<child>123</child>\");\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespaces defined in output nodes\", function () {\n    compare(\n      '<root><p:child xmlns:p=\"s\"><inner>123</inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:p=\"s\"><inner>123</inner></p:child>',\n    );\n  });\n\n  it(\"element used prefixed ns which is also the default\", function () {\n    compare(\n      '<root><child xmlns=\"s\"><p:inner xmlns:p=\"s\">123</p:inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"s\"><p:inner xmlns:p=\"s\">123</p:inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works with default namespace for prefix\", function () {\n    compare(\n      '<ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:SignedInfo>',\n      \"//*[local-name(.)='SignedInfo']\",\n      '<ds:SignedInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></ds:CanonicalizationMethod></ds:SignedInfo>',\n      undefined,\n      { ds: \"http://www.w3.org/2000/09/xmldsig#\" },\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespaces defined in output nodes. ns definition is not duplicated on each usage\", function () {\n    compare(\n      '<root><p:child xmlns:p=\"ns\"><p:inner>123</p:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:p=\"ns\"><p:inner>123</p:inner></p:child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespaces defined in output nodes but before used\", function () {\n    compare(\n      '<root><child xmlns:p=\"ns\"><p:inner>123</p:inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><p:inner xmlns:p=\"ns\">123</p:inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespaces defined outside output nodes\", function () {\n    compare(\n      '<root xmlns:p=\"ns\"><p:child>123</p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:p=\"ns\">123</p:child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespace defined in inclusive list\", function () {\n    compare(\n      '<root xmlns:p=\"ns\"><p:child xmlns:inclusive=\"ns2\"><inclusive:inner xmlns:inclusive=\"ns2\">123</inclusive:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:inclusive=\"ns2\" xmlns:p=\"ns\"><inclusive:inner>123</inclusive:inner></p:child>',\n      [\"inclusive\"],\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with multiple prefixed namespaces defined in inclusive list\", function () {\n    compare(\n      '<root xmlns:p=\"ns\"><p:child xmlns:inclusive=\"ns2\" xmlns:inclusive2=\"ns3\"><inclusive:inner xmlns:inclusive=\"ns2\">123</inclusive:inner><inclusive2:inner xmlns:inclusive2=\"ns3\">456</inclusive2:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:inclusive=\"ns2\" xmlns:inclusive2=\"ns3\" xmlns:p=\"ns\"><inclusive:inner>123</inclusive:inner><inclusive2:inner>456</inclusive2:inner></p:child>',\n      [\"inclusive\", \"inclusive2\"],\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with prefixed namespace defined in inclusive list defined outside output nodes\", function () {\n    compare(\n      '<root xmlns:p=\"ns\" xmlns:inclusive=\"ns2\"><p:child><inclusive:inner xmlns:inclusive=\"ns2\">123</inclusive:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:p=\"ns\"><inclusive:inner xmlns:inclusive=\"ns2\">123</inclusive:inner></p:child>',\n      [\"inclusive\"],\n    );\n  });\n  it(\"Exclusive canonicalization works on xml with prefixed namespace defined in inclusive list used on attribute\", function () {\n    compare(\n      '<root xmlns:p=\"ns\"><p:child xmlns:inclusive=\"ns2\"><p:inner foo=\"inclusive:bar\">123</p:inner></p:child></root>',\n      \"//*[local-name(.)='child']\",\n      '<p:child xmlns:inclusive=\"ns2\" xmlns:p=\"ns\"><p:inner foo=\"inclusive:bar\">123</p:inner></p:child>',\n      [\"inclusive\"],\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with default namespace inside output nodes\", function () {\n    compare(\n      '<root><child><inner xmlns=\"ns\">123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><inner xmlns=\"ns\">123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with multiple different default namespaces\", function () {\n    compare(\n      '<root xmlns=\"ns1\"><child xmlns=\"ns2\"><inner xmlns=\"ns3\">123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"ns2\"><inner xmlns=\"ns3\">123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with multiple similar default namespaces\", function () {\n    compare(\n      '<root xmlns=\"ns1\"><child xmlns=\"ns2\"><inner xmlns=\"ns2\">123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"ns2\"><inner>123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with default namespace outside output nodes\", function () {\n    compare(\n      '<root xmlns=\"ns\"><child><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"ns\"><inner>123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works when prefixed namespace is defined in output nodes not in the parent chain of who needs it\", function () {\n    compare(\n      '<root><child><p:inner1 xmlns:p=\"foo\" /><p:inner2 xmlns:p=\"foo\" /></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><p:inner1 xmlns:p=\"foo\"></p:inner1><p:inner2 xmlns:p=\"foo\"></p:inner2></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with unordered attributes\", function () {\n    compare(\n      '<root><child xmlns:z=\"ns2\" xmlns:p=\"ns1\" p:name=\"val1\" z:someAttr=\"zval\" Id=\"value\" z:testAttr=\"ztestAttr\" someAttr=\"someAttrVal\" p:address=\"val2\"><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns:p=\"ns1\" xmlns:z=\"ns2\" Id=\"value\" someAttr=\"someAttrVal\" p:address=\"val2\" p:name=\"val1\" z:someAttr=\"zval\" z:testAttr=\"ztestAttr\"><inner>123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization sorts upper case attributes before lower case\", function () {\n    compare('<x id=\"\" Id=\"\"></x>', \"//*[local-name(.)='x']\", '<x Id=\"\" id=\"\"></x>');\n  });\n\n  it(\"Exclusive canonicalization removes Comments\", function () {\n    compare('<x id=\"\" Id=\"\"><!-- Comment --></x>', \"//*[local-name(.)='x']\", '<x Id=\"\" id=\"\"></x>');\n  });\n\n  it(\"Exclusive canonicalization works on xml with attributes with different namespace than element\", function () {\n    compare(\n      '<root><child xmlns=\"bla\" xmlns:p=\"foo\" p:attr=\"val\"><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"bla\" xmlns:p=\"foo\" p:attr=\"val\"><inner>123</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with attribute values with special characters\", function () {\n    compare(\n      '<root><child><inner attrEncoded=\"&amp;&lt;>&quot;11&#xD;&#xA;\" attrUnencoded=\\'&>\"11\\r\\n\\'>11</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><inner attrEncoded=\"&amp;&lt;>&quot;11&#xD;&#xA;\" attrUnencoded=\"&amp;>&quot;11 \">11</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization does not normalize whitespace characters into single spaces\", function () {\n    compare(\n      '<root><child><inner attrEncoded=\"&#xA;&#xD;&#x9;11\" attrUnencoded=\"\\n\\r\\t11\">11</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><inner attrEncoded=\"&#xA;&#xD;&#x9;11\" attrUnencoded=\"   11\">11</inner></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization works on xml with element values with special characters\", function () {\n    compare(\n      // eslint-disable-next-line no-useless-escape\n      '<root><child><innerEncoded>&amp;&lt;>&quot;11&#xD;</innerEncoded><innerUnencoded>&>\"11\\r</innerUnencoded></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child><innerEncoded>&amp;&lt;&gt;\"11&#xD;</innerEncoded><innerUnencoded>&amp;&gt;\"11\\n</innerUnencoded></child>',\n    );\n  });\n\n  it(\"Exclusive canonicalization preserves white space in values\", function () {\n    compare(\n      \"<root><child><inner>12\\n3\\t</inner></child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>12\\n3\\t</inner></child>\",\n    );\n  });\n\n  it(\"Exclusive canonicalization does not alter CR-NL (windows line separator) sequences\", function () {\n    compare(\n      \"<root><child><inner>123</inner>\\r\\n</child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>123</inner>\\n</child>\",\n    );\n  });\n  it(\"Exclusive canonicalization preserves and encodes CR white space\", function () {\n    compare(\n      \"<root><child><inner>\\r12\\r3\\r</inner></child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>\\n12\\n3\\n</inner></child>\",\n    );\n  });\n\n  it(\"Exclusive canonicalization preserves white space between elements\", function () {\n    compare(\n      \"<root><child><inner>123</inner>\\n</child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>123</inner>\\n</child>\",\n    );\n  });\n\n  it(\"Exclusive canonicalization turns empty element to start-end tag pairs\", function () {\n    compare(\n      \"<root><child><inner /></child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner></inner></child>\",\n    );\n  });\n\n  it(\"Exclusive canonicalization preserves empty start-end tag pairs\", function () {\n    compare(\n      \"<root><child><inner></inner></child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner></inner></child>\",\n    );\n  });\n\n  it(\"Exclusive canonicalization with empty default namespace outside output nodes\", function () {\n    compare(\n      '<root xmlns=\"\"><child><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>123</inner></child>\",\n    );\n  });\n\n  /*\n    TODO: Uncomment this when this issue is fixed\n    it(\"Exclusive canonicalization removal of whitespace between PITarget and its data\", function() {\n      compare(\n        \"<root xmlns=\\\"\\\"><child><inner>123</inner></child></root><?pi-without-data   ?>\",\n        \"//*[local-name(.)='child']\",\n        \"<child><inner>123</inner></child><?pi-without-data?>\"\n      );\n    });\n    */\n\n  it(\"Exclusive canonicalization with empty default namespace inside output nodes\", function () {\n    compare(\n      '<root xmlns=\"foo\"><child><inner xmlns=\"\">123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"foo\"><inner xmlns=\"\">123</inner></child>',\n    );\n  });\n\n  it(\"The XML declaration and document type declaration (DTD) are removed\", function () {\n    compare(\n      '<?xml version=\"1.0\" encoding=\"utf-8\"?><root><child><inner>123</inner></child></root>',\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>123</inner></child>\",\n    );\n  });\n\n  /*\n    TODO: Uncomment this when this issue is fixed\n    it(\"The XML declaration and document type declaration (DTD) are removed, stylesheet retained\", function() {\n      compare(\n        \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><?xml-stylesheet   href=\\\"doc.xsl\\\"   type=\\\"text/xsl\\\"   ?><root><child><inner>123</inner></child></root>\",\n        \"//*[local-name(.)='child']\",\n        \"<?xml-stylesheet   href=\\\"doc.xsl\\\"   type=\\\"text/xsl\\\"   ?><child><inner>123</inner></child>\"\n      );\n    });\n    */\n\n  it(\"Attribute value delimiters are set to quotation marks (double quotes)\", function () {\n    compare(\n      \"<root><child xmlns='ns'><inner attr='value'>123 </inner></child></root>\",\n      \"//*[local-name(.)='child']\",\n      '<child xmlns=\"ns\"><inner attr=\"value\">123 </inner></child>',\n    );\n  });\n\n  it(\"CDATA sections are replaced with their character content\", function () {\n    compare(\n      \"<root><child><inner><![CDATA[foo & bar in the <x>123</x>]]></inner></child></root>\",\n      \"//*[local-name(.)='child']\",\n      \"<child><inner>foo &amp; bar in the &lt;x&gt;123&lt;/x&gt;</inner></child>\",\n    );\n  });\n\n  it(\"SignedInfo canonization\", function () {\n    compare(\n      '<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"><soap:Header><wsa:Action wsu:Id=\"Id-fbcf79b7-9c1b-4e51-b3da-7d6c237be1ec\">http://stockservice.contoso.com/wse/samples/2003/06/StockQuoteRequest</wsa:Action><wsa:MessageID wsu:Id=\"Id-02b76fe1-945c-4e26-a8a5-6650285bbd4c\">uuid:6250c037-bcde-40ab-82b3-3a08efc86cdc</wsa:MessageID><wsa:ReplyTo wsu:Id=\"Id-ccc937f4-8ec8-416a-b97b-0b612a69b040\"><wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:Address></wsa:ReplyTo><wsa:To wsu:Id=\"Id-fa48ae82-88bb-4bf1-9c0d-4eb1de66c4fc\">http://localhost:8889/</wsa:To><wsse:Security soap:mustUnderstand=\"1\"><wsu:Timestamp wsu:Id=\"Timestamp-4d2cce4a-39fb-4d7d-b0d5-17d583255ef5\"><wsu:Created>2008-09-01T17:44:21Z</wsu:Created><wsu:Expires>2008-09-01T17:49:21Z</wsu:Expires></wsu:Timestamp><wsse:BinarySecurityToken ValueType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3\" EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"SecurityToken-d68c34d4-be89-4a29-aecc-971bce003ed3\">MIIBxDCCAW6gAwIBAgIQxUSXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BAQQFADAWMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ3NTlaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0Q2xpZW50MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+L6aB9x928noY4+0QBsXnxkQE4quJl7c3PUPdVu7k9A02hRG481XIfWhrDY5i7OEB7KGW7qFJotLLeMec/UkKUwCgv3VvJrs2nE9xO3SSWIdNzADukYh+Cxt+FUU6tUkDeqg7dqwivOXhuOTRyOI3HqbWTbumaLdc8jufz2LhaQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcNAQEEBQADQQAfIbnMPVYkNNfX1tG1F+qfLhHwJdfDUZuPyRPucWF5qkh6sSdWVBY5sT/txBnVJGziyO8DPYdu2fPMER8ajJfl</wsse:BinarySecurityToken><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" /><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\" /><Reference URI=\"#Id-fbcf79b7-9c1b-4e51-b3da-7d6c237be1ec\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>+465BlJx5xOfHsIFezQt0MS1vZQ=</DigestValue></Reference><Reference URI=\"#Id-02b76fe1-945c-4e26-a8a5-6650285bbd4c\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>jEe8rnaaqBWZQe+xHBQXriVG99o=</DigestValue></Reference><Reference URI=\"#Id-ccc937f4-8ec8-416a-b97b-0b612a69b040\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>W45ginYdBVqOqEaqPI2piZMPReA=</DigestValue></Reference><Reference URI=\"#Id-fa48ae82-88bb-4bf1-9c0d-4eb1de66c4fc\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>m2VlWz/ZDTWL7FREHK+wpKhvjJM=</DigestValue></Reference><Reference URI=\"#Timestamp-4d2cce4a-39fb-4d7d-b0d5-17d583255ef5\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>Qws229qmAzSTZ4OKmAUWgl0PWWo=</DigestValue></Reference><Reference URI=\"#Id-0175a715-4db3-4886-8af1-991b1472e7f4\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" /><DigestValue>iEazGnkPY5caCWVZOHyR87CZ1h0=</DigestValue></Reference></SignedInfo><SignatureValue>Fkm7AbwiJCiOzY8ldfuA9pTW1G+EtE+UX4Cv7SoMIqeUdfWRDVHZpJAQyf7aoQnlpJNV/3k9L1PT6rJbfV478CkULJENPLm1m0fmDeLzhIHDEANuzp/AirC60tMD5jCARb4B4Nr/6bTmoyDQsTY8VLRiiINng7Mpweg1FZvd8a0=</SignatureValue><KeyInfo><wsse:SecurityTokenReference><wsse:Reference URI=\"#SecurityToken-d68c34d4-be89-4a29-aecc-971bce003ed3\" ValueType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3\" /></wsse:SecurityTokenReference></KeyInfo></Signature></wsse:Security></soap:Header><soap:Body wsu:Id=\"Id-0175a715-4db3-4886-8af1-991b1472e7f4\"><StockQuoteRequest xmlns=\"http://stockservice.contoso.com/wse/samples/2003/06\"><symbols><Symbol>FABRIKAM</Symbol></symbols></StockQuoteRequest></soap:Body></soap:Envelope>',\n      \"//*[local-name(.)='SignedInfo']\",\n      '<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><ds:CanonicalizationMethod xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></ds:CanonicalizationMethod><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"></SignatureMethod><Reference URI=\"#Id-fbcf79b7-9c1b-4e51-b3da-7d6c237be1ec\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>+465BlJx5xOfHsIFezQt0MS1vZQ=</DigestValue></Reference><Reference URI=\"#Id-02b76fe1-945c-4e26-a8a5-6650285bbd4c\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>jEe8rnaaqBWZQe+xHBQXriVG99o=</DigestValue></Reference><Reference URI=\"#Id-ccc937f4-8ec8-416a-b97b-0b612a69b040\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>W45ginYdBVqOqEaqPI2piZMPReA=</DigestValue></Reference><Reference URI=\"#Id-fa48ae82-88bb-4bf1-9c0d-4eb1de66c4fc\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>m2VlWz/ZDTWL7FREHK+wpKhvjJM=</DigestValue></Reference><Reference URI=\"#Timestamp-4d2cce4a-39fb-4d7d-b0d5-17d583255ef5\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>Qws229qmAzSTZ4OKmAUWgl0PWWo=</DigestValue></Reference><Reference URI=\"#Id-0175a715-4db3-4886-8af1-991b1472e7f4\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod><DigestValue>iEazGnkPY5caCWVZOHyR87CZ1h0=</DigestValue></Reference></SignedInfo>',\n    );\n  }),\n    it(\"Exclusive canonicalization works on complex xml\", function () {\n      compare(\n        '<?xml version=\"1.0\" encoding=\"utf-8\"?>\\n' +\n          '<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\">\\n' +\n          \"  <Body>\\n\" +\n          '    <ACORD xmlns=\"http://www.ACORD.org/standards/PC_Surety/ACORD1.10.0/xml/\">\\n' +\n          \"      <SignonRq>\\n\" +\n          \"        <SessKey />\\n\" +\n          \"        <ClientDt />\\n\" +\n          \"        <CustLangPref />\\n\" +\n          \"        <ClientApp>\\n\" +\n          '          <Org p6:type=\"AssignedIdentifier\" id=\"wewe\" xmlns:p6=\"http://www.w3.org/2001/XMLSchema-instance\" />\\n' +\n          \"          <Name />\\n\" +\n          \"          <Version />\\n\" +\n          \"        </ClientApp>\\n\" +\n          \"        <ProxyClient>\\n\" +\n          '          <Org p6:type=\"AssignedIdentifier\" id=\"erer\" xmlns:p6=\"http://www.w3.org/2001/XMLSchema-instance\" />\\n' +\n          \"          <Name>ererer</Name>\\n\" +\n          \"          <Version>dfdf</Version>\\n\" +\n          \"        </ProxyClient>\\n\" +\n          \"      </SignonRq>\\n\" +\n          \"      <InsuranceSvcRq>\\n\" +\n          \"        <RqUID />\\n\" +\n          '        <SPName id=\"rter\" />\\n' +\n          '        <QuickHit xmlns=\"urn:com.thehartford.bi.acord-extensions\">\\n' +\n          '          <StateProvCd CodeListRef=\"dfdf\" xmlns=\"http://www.ACORD.org/standards/PC_Surety/ACORD1.10.0/xml/\" />\\n' +\n          \"        </QuickHit>\\n\" +\n          \"        <WorkCompPolicyQuoteInqRq>\\n\" +\n          \"          <RqUID>erer</RqUID>\\n\" +\n          '          <TransactionRequestDt id=\"erer\" />\\n' +\n          \"          <CurCd />\\n\" +\n          '          <BroadLOBCd id=\"erer\" />\\n' +\n          \"          <InsuredOrPrincipal>\\n\" +\n          \"            <ItemIdInfo>\\n\" +\n          '              <AgencyId id=\"3434\" />\\n' +\n          \"              <OtherIdentifier>\\n\" +\n          '                <CommercialName id=\"3434\" />\\n' +\n          \"                <ContractTerm>\\n\" +\n          '                  <EffectiveDt id=\"3434\" />\\n' +\n          '                  <StartTime id=\"3434\" />\\n' +\n          \"                </ContractTerm>\\n\" +\n          \"              </OtherIdentifier>\\n\" +\n          \"            </ItemIdInfo>\\n\" +\n          \"          </InsuredOrPrincipal>\\n\" +\n          \"          <InsuredOrPrincipal>\\n\" +\n          \"          </InsuredOrPrincipal>\\n\" +\n          \"          <CommlPolicy>\\n\" +\n          '            <PolicyNumber id=\"3434\" />\\n' +\n          \"            <LOBCd />\\n\" +\n          \"          </CommlPolicy>\\n\" +\n          \"          <WorkCompLineBusiness>\\n\" +\n          \"            <LOBCd />\\n\" +\n          \"            <WorkCompRateState>\\n\" +\n          \"              <WorkCompLocInfo>\\r\" +\n          \"              </WorkCompLocInfo>\\n\" +\n          \"            </WorkCompRateState>\\n\" +\n          \"          </WorkCompLineBusiness>\\n\" +\n          '          <RemarkText IdRef=\"\">\\n' +\n          \"          </RemarkText>\\n\" +\n          '          <RemarkText IdRef=\"2323\" id=\"3434\">\\n' +\n          \"          </RemarkText>\\n\" +\n          \"        </WorkCompPolicyQuoteInqRq>\\n\" +\n          \"      </InsuranceSvcRq>\\n\" +\n          \"    </ACORD>\\n\" +\n          \"  </Body>\\n\" +\n          \"</Envelope>\",\n        \"//*[local-name(.)='Body']\",\n        '<Body xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\">\\n    <ACORD xmlns=\"http://www.ACORD.org/standards/PC_Surety/ACORD1.10.0/xml/\">\\n      <SignonRq>\\n        <SessKey></SessKey>\\n        <ClientDt></ClientDt>\\n        <CustLangPref></CustLangPref>\\n        <ClientApp>\\n          <Org xmlns:p6=\"http://www.w3.org/2001/XMLSchema-instance\" id=\"wewe\" p6:type=\"AssignedIdentifier\"></Org>\\n          <Name></Name>\\n          <Version></Version>\\n        </ClientApp>\\n        <ProxyClient>\\n          <Org xmlns:p6=\"http://www.w3.org/2001/XMLSchema-instance\" id=\"erer\" p6:type=\"AssignedIdentifier\"></Org>\\n          <Name>ererer</Name>\\n          <Version>dfdf</Version>\\n        </ProxyClient>\\n      </SignonRq>\\n      <InsuranceSvcRq>\\n        <RqUID></RqUID>\\n        <SPName id=\"rter\"></SPName>\\n        <QuickHit xmlns=\"urn:com.thehartford.bi.acord-extensions\">\\n          <StateProvCd xmlns=\"http://www.ACORD.org/standards/PC_Surety/ACORD1.10.0/xml/\" CodeListRef=\"dfdf\"></StateProvCd>\\n        </QuickHit>\\n        <WorkCompPolicyQuoteInqRq>\\n          <RqUID>erer</RqUID>\\n          <TransactionRequestDt id=\"erer\"></TransactionRequestDt>\\n          <CurCd></CurCd>\\n          <BroadLOBCd id=\"erer\"></BroadLOBCd>\\n          <InsuredOrPrincipal>\\n            <ItemIdInfo>\\n              <AgencyId id=\"3434\"></AgencyId>\\n              <OtherIdentifier>\\n                <CommercialName id=\"3434\"></CommercialName>\\n                <ContractTerm>\\n                  <EffectiveDt id=\"3434\"></EffectiveDt>\\n                  <StartTime id=\"3434\"></StartTime>\\n                </ContractTerm>\\n              </OtherIdentifier>\\n            </ItemIdInfo>\\n          </InsuredOrPrincipal>\\n          <InsuredOrPrincipal>\\n          </InsuredOrPrincipal>\\n          <CommlPolicy>\\n            <PolicyNumber id=\"3434\"></PolicyNumber>\\n            <LOBCd></LOBCd>\\n          </CommlPolicy>\\n          <WorkCompLineBusiness>\\n            <LOBCd></LOBCd>\\n            <WorkCompRateState>\\n              <WorkCompLocInfo>\\n              </WorkCompLocInfo>\\n            </WorkCompRateState>\\n          </WorkCompLineBusiness>\\n          <RemarkText IdRef=\"\">\\n          </RemarkText>\\n          <RemarkText IdRef=\"2323\" id=\"3434\">\\n          </RemarkText>\\n        </WorkCompPolicyQuoteInqRq>\\n      </InsuranceSvcRq>\\n    </ACORD>\\n  </Body>',\n      );\n    });\n\n  it(\"Multiple Canonicalization with namespace definition outside of signed element\", function () {\n    const doc = new xmldom.DOMParser().parseFromString(\n      '<x xmlns:p=\"myns\"><p:y><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"></ds:Signature></p:y></x>',\n    );\n    const node = xpath.select1(\"//*[local-name(.)='y']\", doc);\n    isDomNode.assertIsNodeLike(node);\n\n    const sig = new SignedXml();\n    const res = sig.getCanonXml(\n      [\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      ],\n      node,\n    );\n    expect(res).to.equal('<p:y xmlns:p=\"myns\"></p:y>');\n  });\n\n  it(\"Shouldn't continue processing transforms if we end up with a string as a result of a transform\", function () {\n    const doc = new xmldom.DOMParser().parseFromString(\n      '<x xmlns:p=\"myns\"><p:y><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"></ds:Signature></p:y></x>',\n    );\n    const node1 = xpath.select1(\"//*[local-name(.)='y']\", doc);\n    const node2 = xpath.select1(\"//*[local-name(.)='y']\", doc);\n    isDomNode.assertIsNodeLike(node1);\n    isDomNode.assertIsNodeLike(node2);\n    const sig = new SignedXml();\n    const res1 = sig.getCanonXml(\n      [\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n      ],\n      node1,\n    );\n    const res2 = sig.getCanonXml([\"http://www.w3.org/2001/10/xml-exc-c14n#\"], node2);\n    expect(res1)\n      .to.equal(res2)\n      .to.equal(\n        '<p:y xmlns:p=\"myns\"><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"></ds:Signature></p:y>',\n      );\n  });\n\n  it(\"Enveloped-signature canonicalization respects current node\", function () {\n    // older versions of enveloped-signature removed the first signature in the whole doc, but should\n    //   be the signature inside the current node if we want to be able to verify multiple signatures\n    //   in a document.\n    const xml =\n      '<x><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" /><y><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" /></y></x>';\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const node = xpath.select1(\"//*[local-name(.)='y']\", doc);\n    isDomNode.assertIsNodeLike(node);\n\n    const sig = new SignedXml();\n    const transforms = [\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"];\n    const res = sig.getCanonXml(transforms, node);\n    expect(res).to.equal(\"<y/>\");\n  });\n\n  it(\"The XML canonicalization method processes a node-set by imposing the following additional document order rules on the namespace and attribute nodes of each element: \\\n    - An element's namespace and attribute nodes have a document order position greater than the element but less than any child node of the element. \\\n      Namespace nodes have a lesser document order position than attribute nodes. \\\n    - An element's namespace nodes are sorted lexicographically by local name (the default namespace node, if one exists, has no local name and is therefore lexicographically least). \\\n    - An element's attribute nodes are sorted lexicographically with namespace URI as the primary key and local name as the secondary key (an empty namespace URI is lexicographically least). \\\n      Lexicographic comparison, which orders strings from least to greatest alphabetically, is based on the UCS codepoint values, which is equivalent to lexicographic ordering based on UTF-8.\", function () {\n    compare(\n      '<root xmlns:b=\"moo\" b:attr1=\"a1\" a:attr1=\"a1\" b:attr4=\"b4\" xmlns=\"foo\" b:attr3=\"a3\" xmlns:a=\"zoo\"></root>',\n      \"//*[local-name(.)='root']\",\n      '<root xmlns=\"foo\" xmlns:a=\"zoo\" xmlns:b=\"moo\" b:attr1=\"a1\" b:attr3=\"a3\" b:attr4=\"b4\" a:attr1=\"a1\"></root>',\n    );\n  });\n\n  it(\"saml attributed order (bug #25)\", function () {\n    compare(\n      '<root xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" samlp:a=\"1\" saml:a=\"1\"></root>',\n      \"//*[local-name(.)='root']\",\n      '<root xmlns=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" saml:a=\"1\" samlp:a=\"1\"></root>',\n    );\n  });\n\n  it(\"Body Xml Element Canonicalization\", function () {\n    compare(\n      '<s:Body xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" Id=\"SignedSoapBodyContent\" xmlns:s=\"' +\n        'http://schemas.xmlsoap.org/soap/envelope/\">' +\n        '<getBatchStatus xmlns=\"http://webservice.edefter.gib.gov.tr/\">' +\n        '<paketID xmlns=\"\">3810016849-201501-KB-0000</paketID>' +\n        \"</getBatchStatus>\" +\n        \"</s:Body>\",\n      \"//*\",\n      '<s:Body xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" Id=\"SignedSoapBodyContent\">' +\n        '<getBatchStatus xmlns=\"http://webservice.edefter.gib.gov.tr/\">' +\n        '<paketID xmlns=\"\">3810016849-201501-KB-0000</paketID>' +\n        \"</getBatchStatus>\" +\n        \"</s:Body>\",\n    );\n  });\n\n  it(\"Overriding namespace in canonicalization\", function () {\n    compare(\n      '<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:InclusiveNamespaces xmlns:ds=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></ds:InclusiveNamespaces></ds:Signature>',\n      \"//*\",\n      '<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:InclusiveNamespaces xmlns:ds=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></ds:InclusiveNamespaces></ds:Signature>',\n      [\"ds\"],\n    );\n  });\n});\n"
  },
  {
    "path": "test/document-tests.spec.ts",
    "content": "import { SignedXml } from \"../src/index\";\nimport * as xpath from \"xpath\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as fs from \"fs\";\nimport { expect } from \"chai\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\ndescribe(\"Document tests\", function () {\n  it(\"test with a document (using FileKeyInfo)\", function () {\n    const xml = fs.readFileSync(\"./test/static/valid_saml.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const node = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n\n    isDomNode.assertIsNodeLike(node);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/feide_public.pem\");\n    sig.loadSignature(node);\n    const result = sig.checkSignature(xml);\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"test with a document (using StringKeyInfo)\", function () {\n    const xml = fs.readFileSync(\"./test/static/valid_saml.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const node = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n\n    isDomNode.assertIsNodeLike(node);\n    const sig = new SignedXml();\n    const feidePublicCert = fs.readFileSync(\"./test/static/feide_public.pem\");\n    sig.publicCert = feidePublicCert;\n    sig.loadSignature(node);\n    const result = sig.checkSignature(xml);\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n});\n\ndescribe(\"Validated node references tests\", function () {\n  it(\"should return references if the document is validly signed\", function () {\n    const xml = fs.readFileSync(\"./test/static/valid_saml.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const sig = new SignedXml();\n    sig.getCertFromKeyInfo = SignedXml.getCertFromKeyInfo;\n    sig.loadSignature(sig.findSignatures(doc)[0]);\n    const validSignature = sig.checkSignature(xml);\n    expect(validSignature).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n\n    /* eslint-disable-next-line deprecation/deprecation */\n    const ref = sig.getReferences()[0];\n    const result = ref.getValidatedNode();\n    expect(result?.toString()).to.equal(doc.toString());\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"should not return references if the document is not validly signed\", function () {\n    const xml = fs.readFileSync(\"./test/static/invalid_signature - changed content.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const sig = new SignedXml();\n    sig.loadSignature(sig.findSignatures(doc)[0]);\n    const validSignature = sig.checkSignature(xml);\n    expect(validSignature).to.be.false;\n    expect(sig.getSignedReferences().length).to.equal(0);\n\n    /* eslint-disable-next-line deprecation/deprecation */\n    const ref = sig.getReferences()[1];\n    const result = ref.getValidatedNode();\n    expect(result).to.be.null;\n    expect(sig.getSignedReferences().length).to.equal(0);\n  });\n\n  it(\"should return `null` if the selected node isn't found\", function () {\n    const xml = fs.readFileSync(\"./test/static/valid_saml.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const sig = new SignedXml();\n    sig.getCertFromKeyInfo = SignedXml.getCertFromKeyInfo;\n    sig.loadSignature(sig.findSignatures(doc)[0]);\n    const validSignature = sig.checkSignature(xml);\n    expect(validSignature).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n\n    /* eslint-disable-next-line deprecation/deprecation */\n    const ref = sig.getReferences()[0];\n    const result = ref.getValidatedNode(\"/non-existent-node\");\n    expect(result).to.be.null;\n  });\n\n  it(\"should return the selected node if it is validly signed\", function () {\n    const xml = fs.readFileSync(\"./test/static/valid_saml.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const sig = new SignedXml();\n    sig.getCertFromKeyInfo = SignedXml.getCertFromKeyInfo;\n    sig.loadSignature(sig.findSignatures(doc)[0]);\n    const validSignature = sig.checkSignature(xml);\n    expect(validSignature).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n\n    /* eslint-disable-next-line deprecation/deprecation */\n    const ref = sig.getReferences()[0];\n    const result = ref.getValidatedNode(\n      \"//*[local-name()='Attribute' and @Name='mail']/*[local-name()='AttributeValue']/text()\",\n    );\n    expect(result?.nodeValue).to.equal(\"henri.bergius@nemein.com\");\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"should return `null` if the selected node isn't validly signed\", function () {\n    const xml = fs.readFileSync(\"./test/static/invalid_signature - changed content.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const sig = new SignedXml();\n    sig.loadSignature(sig.findSignatures(doc)[0]);\n    const validSignature = sig.checkSignature(xml);\n    expect(validSignature).to.be.false;\n    expect(sig.getSignedReferences().length).to.equal(0);\n\n    /* eslint-disable-next-line deprecation/deprecation */\n    const ref = sig.getReferences()[0];\n    const result = ref.getValidatedNode(\n      \"//*[local-name()='Attribute' and @Name='mail']/*[local-name()='AttributeValue']/text()\",\n    );\n    expect(result).to.be.null;\n    // Not all references verified, so no references should be in `.getSignedReferences()`.\n    expect(sig.getSignedReferences().length).to.equal(0);\n  });\n});\n"
  },
  {
    "path": "test/hmac-tests.spec.ts",
    "content": "import { SignedXml } from \"../src/index\";\nimport * as xpath from \"xpath\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as fs from \"fs\";\nimport { expect } from \"chai\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\ndescribe(\"HMAC tests\", function () {\n  it(\"test validating HMAC signature\", function () {\n    const xml = fs.readFileSync(\"./test/static/hmac_signature.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const signature = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n\n    const sig = new SignedXml();\n    sig.enableHMAC();\n    sig.publicCert = fs.readFileSync(\"./test/static/hmac.key\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(xml);\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"test HMAC signature with incorrect key\", function () {\n    const xml = fs.readFileSync(\"./test/static/hmac_signature.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const signature = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n\n    const sig = new SignedXml();\n    sig.enableHMAC();\n    sig.publicCert = fs.readFileSync(\"./test/static/hmac-foobar.key\");\n    sig.loadSignature(signature);\n\n    expect(() => sig.checkSignature(xml)).to.throw(/^invalid signature/);\n    expect(sig.getSignedReferences().length).to.equal(0);\n  });\n\n  it(\"test create and validate HMAC signature\", function () {\n    const xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\" + \"</library>\";\n    const sig = new SignedXml();\n    sig.enableHMAC();\n    sig.privateKey = fs.readFileSync(\"./test/static/hmac.key\");\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#hmac-sha1\";\n    sig.addReference({\n      xpath: \"//*[local-name(.)='book']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.computeSignature(xml);\n\n    const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());\n    const signature = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n\n    const verify = new SignedXml();\n    verify.enableHMAC();\n    verify.publicCert = fs.readFileSync(\"./test/static/hmac.key\");\n    verify.loadSignature(signature);\n    const result = verify.checkSignature(sig.getSignedXml());\n\n    expect(result).to.be.true;\n    expect(verify.getSignedReferences().length).to.equal(1);\n  });\n});\n"
  },
  {
    "path": "test/key-info-tests.spec.ts",
    "content": "import * as xmldom from \"@xmldom/xmldom\";\nimport * as fs from \"fs\";\nimport * as xpath from \"xpath\";\nimport { SignedXml } from \"../src/index\";\nimport { expect } from \"chai\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\ndescribe(\"KeyInfo tests\", function () {\n  it(\"adds X509Certificate element during signature\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml();\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.publicCert = fs.readFileSync(\"./test/static/client_public.pem\");\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const x509 = xpath.select(\"//*[local-name(.)='X509Certificate']\", doc.documentElement);\n    isDomNode.assertIsArrayOfNodes(x509);\n\n    expect(x509.length, \"X509Certificate element should exist\").to.equal(1);\n  });\n\n  it(\"make sure private hmac key is not leaked due to key confusion\", function () {\n    const xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\" + \"</library>\";\n    const sig = new SignedXml();\n    sig.privateKey = fs.readFileSync(\"./test/static/hmac.key\");\n    sig.publicCert = fs.readFileSync(\"./test/static/hmac.key\");\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#hmac-sha1\";\n    sig.enableHMAC();\n    sig.addReference({\n      xpath: \"//*[local-name(.)='book']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.computeSignature(xml);\n\n    const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());\n    const keyInfo = xpath.select1(\"//*[local-name(.)='KeyInfo']\", doc);\n\n    expect(keyInfo).to.be.undefined;\n  });\n});\n"
  },
  {
    "path": "test/saml-response-tests.spec.ts",
    "content": "import { SignedXml } from \"../src/index\";\nimport * as xpath from \"xpath\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as fs from \"fs\";\nimport { expect } from \"chai\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\ndescribe(\"SAML response tests\", function () {\n  it(\"test validating SAML response\", function () {\n    const xml = fs.readFileSync(\"./test/static/valid_saml.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const signature = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/feide_public.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(xml);\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"test validating SAML response with sha256-rsa-MGF1\", function () {\n    const xml = fs.readFileSync(\"./test/static/valid_saml_sha256_rsa_mgf1.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const signature = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/idp_certificate.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(xml);\n\n    expect(result).to.be.true;\n  });\n\n  it(\"test validating SAML response with sha256-rsa-MGF1 fails for modified file\", function () {\n    const xml = fs.readFileSync(\"./test/static/invalid_saml_sha256_rsa_mgf1.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const signature = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/idp_certificate.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(xml);\n\n    expect(result).to.be.false;\n  });\n\n  it(\"test validating wrapped assertion signature\", function () {\n    const xml = fs.readFileSync(\"./test/static/valid_saml_signature_wrapping.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const assertion = xpath.select1(\"//*[local-name(.)='Assertion']\", doc);\n    isDomNode.assertIsNodeLike(assertion);\n    const signature = xpath.select1(\n      \"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      assertion,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/feide_public.pem\");\n    sig.loadSignature(signature);\n    expect(\n      function () {\n        sig.checkSignature(xml);\n      },\n      \"Should not validate a document which contains multiple elements with the \" +\n        \"same value for the ID / Id / Id attributes, in order to prevent \" +\n        \"signature wrapping attack.\",\n    ).to.throw();\n    expect(sig.getSignedReferences().length).to.equal(0);\n  });\n\n  it(\"test validating SAML response where a namespace is defined outside the signed element\", function () {\n    const xml = fs.readFileSync(\"./test/static/saml_external_ns.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const signature = xpath.select1(\n      \"//*//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/saml_external_ns.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(xml);\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"test reference id does not contain quotes\", function () {\n    const xml = fs.readFileSync(\"./test/static/id_with_quotes.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const assertion = xpath.select1(\"//*[local-name(.)='Assertion']\", doc);\n    isDomNode.assertIsNodeLike(assertion);\n    const signature = xpath.select1(\n      \"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      assertion,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/feide_public.pem\");\n    sig.loadSignature(signature);\n    expect(function () {\n      sig.checkSignature(xml);\n    }, \"id should not contain quotes\").to.throw();\n  });\n\n  it(\"test validating SAML response WithComments\", function () {\n    const xml = fs.readFileSync(\"./test/static/valid_saml_withcomments.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const signature = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/feide_public.pem\");\n    sig.loadSignature(signature);\n    // This doesn't matter, just want to make sure that we don't fail due to unknown algorithm\n    expect(() => sig.checkSignature(xml)).to.throw(/^invalid signature/);\n    expect(sig.getSignedReferences().length).to.equal(0);\n  });\n\n  it(\"throws an error for a document with no `SignedInfo` node\", function () {\n    const xml = fs.readFileSync(\"./test/static/invalid_saml_no_signed_info.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const node = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n\n    isDomNode.assertIsNodeLike(node);\n    const sig = new SignedXml();\n    const feidePublicCert = fs.readFileSync(\"./test/static/feide_public.pem\");\n    sig.publicCert = feidePublicCert;\n\n    expect(() => sig.loadSignature(node)).to.throw(\"no signed info node found\");\n  });\n\n  it(\"test validation ignores an additional wrapped `SignedInfo` node\", function () {\n    const xml = fs.readFileSync(\"./test/static/saml_wrapped_signed_info_node.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const assertion = xpath.select1(\"//*[local-name(.)='Assertion']\", doc);\n    isDomNode.assertIsNodeLike(assertion);\n    const signature = xpath.select1(\n      \"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      assertion,\n    );\n    isDomNode.assertIsNodeLike(signature);\n\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/saml_external_ns.pem\");\n    sig.loadSignature(signature);\n    /* eslint-disable-next-line deprecation/deprecation */\n    expect(sig.getReferences().length).to.equal(1);\n    const checkSignatureResult = sig.checkSignature(xml);\n    expect(checkSignatureResult).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"test signature throws if multiple `SignedInfo` nodes are found\", function () {\n    const xml = fs.readFileSync(\"./test/static/saml_multiple_signed_info_nodes.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const assertion = xpath.select1(\"//*[local-name(.)='Assertion'][1]\", doc);\n    isDomNode.assertIsNodeLike(assertion);\n    const signature = xpath.select1(\n      \"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      assertion,\n    );\n    isDomNode.assertIsNodeLike(signature);\n\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/saml_external_ns.pem\");\n    expect(() => sig.loadSignature(signature)).to.throw(\n      \"could not load signature that contains multiple SignedInfo nodes\",\n    );\n  });\n\n  describe(\"for a SAML response with a digest value comment\", () => {\n    it(\"loads digest value from text content instead of comment\", function () {\n      const xml = fs.readFileSync(\"./test/static/valid_saml_with_digest_comment.xml\", \"utf-8\");\n      const doc = new xmldom.DOMParser().parseFromString(xml);\n      const assertion = xpath.select1(\"//*[local-name(.)='Assertion']\", doc);\n      isDomNode.assertIsNodeLike(assertion);\n      const signature = xpath.select1(\n        \"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n        assertion,\n      );\n      isDomNode.assertIsNodeLike(signature);\n      const sig = new SignedXml();\n      sig.publicCert = fs.readFileSync(\"./test/static/feide_public.pem\");\n\n      sig.loadSignature(signature);\n\n      /* eslint-disable-next-line deprecation/deprecation */\n      expect(sig.getReferences()[0].digestValue).to.equal(\"RnNjoyUguwze5w2R+cboyTHlkQk=\");\n      expect(sig.checkSignature(xml)).to.be.false;\n      expect(sig.getSignedReferences().length).to.equal(0);\n    });\n  });\n});\n"
  },
  {
    "path": "test/signature-integration-tests.spec.ts",
    "content": "import * as xpath from \"xpath\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport { SignedXml } from \"../src/index\";\nimport * as fs from \"fs\";\nimport { expect } from \"chai\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\ndescribe(\"Signature integration tests\", function () {\n  function verifySignature(xml, expected, xpath, canonicalizationAlgorithm) {\n    const sig = new SignedXml();\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    xpath.map(function (n) {\n      sig.addReference({\n        xpath: n,\n        digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n        transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n      });\n    });\n\n    sig.canonicalizationAlgorithm = canonicalizationAlgorithm;\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signed = sig.getSignedXml();\n\n    const expectedContent = fs.readFileSync(expected).toString();\n    expect(signed, \"signature xml different than expected\").to.equal(expectedContent);\n  }\n\n  it(\"verify signature\", function () {\n    const xml =\n      '<root><x xmlns=\"ns\"></x><y z_attr=\"value\" a_attr1=\"foo\"></y><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\"></ns:w></z></root>';\n    verifySignature(\n      xml,\n      \"./test/static/integration/expectedVerify.xml\",\n      [\"//*[local-name(.)='x']\", \"//*[local-name(.)='y']\", \"//*[local-name(.)='w']\"],\n      \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n    );\n  });\n\n  it(\"verify signature of complex element\", function () {\n    const xml =\n      \"<library>\" +\n      \"<book>\" +\n      \"<name>Harry Potter</name>\" +\n      '<author id=\"123456789\">' +\n      \"<firstName>Joanne K</firstName>\" +\n      \"<lastName>Rowling</lastName>\" +\n      \"</author>\" +\n      \"</book>\" +\n      \"</library>\";\n\n    verifySignature(\n      xml,\n      \"./test/static/integration/expectedVerifyComplex.xml\",\n      [\"//*[local-name(.)='book']\"],\n      \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n    );\n  });\n\n  it(\"empty URI reference should consider the whole document\", function () {\n    const xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\" + \"</library>\";\n\n    const signature =\n      '<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">' +\n      \"<SignedInfo>\" +\n      '<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>' +\n      '<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>' +\n      '<Reference URI=\"\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>' +\n      \"</Transforms>\" +\n      '<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>' +\n      \"<DigestValue>1tjZsV007JgvE1YFe1C8sMQ+iEg=</DigestValue>\" +\n      \"</Reference>\" +\n      \"</SignedInfo>\" +\n      \"<SignatureValue>FONRc5/nnQE2GMuEV0wK5/ofUJMHH7dzZ6VVd+oHDLfjfWax/lCMzUahJxW1i/dtm9Pl0t2FbJONVd3wwDSZzy6u5uCnj++iWYkRpIEN19RAzEMD1ejfZET8j3db9NeBq2JjrPbw81Fm7qKvte6jGa9ThTTB+1MHFRkC8qjukRM=</SignatureValue>\" +\n      \"</Signature>\";\n\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/client_public.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(xml);\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"add canonicalization if output of transforms will be a node-set rather than an octet stream\", function () {\n    let xml = fs.readFileSync(\"./test/static/windows_store_signature.xml\", \"utf-8\");\n\n    /** Make sure that whitespace in the source document is removed --\n     * @see xml-crypto issue #23 and post at\n     *   http://webservices20.blogspot.co.il/2013/06/validating-windows-mobile-app-store.html\n     * This regex is naive but works for this test case; for a more general solution consider\n     *   the xmldom-fork-fixed library which can pass {ignoreWhiteSpace: true} into the Dom constructor.\n     */\n    xml = xml.replace(/>\\s*</g, \"><\");\n\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const childXml = doc.firstChild?.toString();\n\n    const signature = xpath.select1(\n      \"//*//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/windows_store_certificate.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(childXml ?? \"\");\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"signature with inclusive namespaces\", function () {\n    const xml = fs.readFileSync(\"./test/static/signature_with_inclusivenamespaces.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const childXml = doc.firstChild?.toString();\n\n    const signature = xpath.select1(\n      \"//*//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/signature_with_inclusivenamespaces.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(childXml ?? \"\");\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"signature with inclusive namespaces with unix line separators\", function () {\n    const xml = fs.readFileSync(\n      \"./test/static/signature_with_inclusivenamespaces_lines.xml\",\n      \"utf-8\",\n    );\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const childXml = doc.firstChild?.toString();\n\n    const signature = xpath.select1(\n      \"//*//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/signature_with_inclusivenamespaces.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(childXml ?? \"\");\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"signature with inclusive namespaces with windows line separators\", function () {\n    const xml = fs.readFileSync(\n      \"./test/static/signature_with_inclusivenamespaces_lines_windows.xml\",\n      \"utf-8\",\n    );\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const childXml = doc.firstChild?.toString();\n\n    const signature = xpath.select1(\n      \"//*//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/signature_with_inclusivenamespaces.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(childXml ?? \"\");\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n\n  it(\"should create single root xml document when signing inner node\", function () {\n    const xml = \"<library>\" + \"<book>\" + \"<name>Harry Potter</name>\" + \"</book>\" + \"</library>\";\n\n    const sig = new SignedXml();\n    sig.addReference({\n      xpath: \"//*[local-name(.)='book']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n\n    const signed = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signed);\n\n    /*\n        Expecting this structure:\n        <library>\n            <book Id=\"_0\">\n                <name>Harry Potter</name>\n            </book>\n            <Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">\n                <SignedInfo>\n                    <CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n                    <SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\n                    <Reference URI=\"#_0\">\n                        <Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms>\n                        <DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>\n                        <DigestValue>cdiS43aFDQMnb3X8yaIUej3+z9Q=</DigestValue>\n                    </Reference>\n                </SignedInfo>\n                <SignatureValue>J79hiSUrKdLOuX....Mthy1M=</SignatureValue>\n            </Signature>\n        </library>\n    */\n\n    expect(doc.documentElement.nodeName, \"root node = <library>.\").to.equal(\"library\");\n    expect(doc.childNodes.length, \"only one root node is expected.\").to.equal(1);\n    expect(\n      doc.documentElement.childNodes.length,\n      \"<library> should have two child nodes : <book> and <Signature>\",\n    ).to.equal(2);\n  });\n});\n"
  },
  {
    "path": "test/signature-object-tests.spec.ts",
    "content": "import * as fs from \"fs\";\nimport { expect, assert } from \"chai\";\nimport * as xpath from \"xpath\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\nimport { SignedXml } from \"../src\";\nimport { Sha256 } from \"../src/hash-algorithms\";\n\nconst privateKey = fs.readFileSync(\"./test/static/client.pem\", \"utf-8\");\nconst publicCert = fs.readFileSync(\"./test/static/client_public.pem\", \"utf-8\");\nconst publicCertDer = fs.readFileSync(\"./test/static/client_public.der\");\nconst selectNs = (expression: string, node: Node, ns?: Record<string, string>) =>\n  xpath.useNamespaces({\n    ds: \"http://www.w3.org/2000/09/xmldsig#\",\n    xades: \"http://uri.etsi.org/01903/v1.3.2#\",\n    ...ns,\n  })(expression, node, false);\nconst select1Ns = (expression: string, node: Node, ns?: Record<string, string>) =>\n  xpath.useNamespaces({\n    ds: \"http://www.w3.org/2000/09/xmldsig#\",\n    xades: \"http://uri.etsi.org/01903/v1.3.2#\",\n    ...ns,\n  })(expression, node, true);\n\nconst checkSignature = (signedXml: string, signedDoc: Document) => {\n  const verifier = new SignedXml({ publicCert });\n  const signatureNode = select1Ns(\"//ds:Signature\", signedDoc);\n  isDomNode.assertIsNodeLike(signatureNode);\n  verifier.loadSignature(signatureNode);\n  const valid = verifier.checkSignature(signedXml);\n\n  return {\n    valid,\n    errorMessage: verifier\n      .getReferences()\n      .flatMap((ref) => ref.validationError?.message || [])\n      .join(\", \"),\n  };\n};\n\ndescribe(\"ds:Object support in XML signatures\", function () {\n  it(\"should add custom ds:Object elements with attributes to the signature\", function () {\n    const xml = '<root><x xmlns=\"ns\"></x><y attr=\"value\"></y><z><w></w></z></root>';\n\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      objects: [\n        {\n          content: \"<Data>Test data in Object element</Data>\",\n          attributes: {\n            Id: \"object1\",\n            MimeType: \"text/xml\",\n            Encoding: \"\",\n          },\n        },\n        {\n          content: \"Plain text content\",\n          attributes: {\n            Id: \"object2\",\n            MimeType: \"text/plain\",\n          },\n        },\n        {\n          content: Buffer.from(\"This is base64 encoded data\").toString(\"base64\"),\n          attributes: {\n            Id: \"object3\",\n            MimeType: \"text/plain\",\n            Encoding: \"http://www.w3.org/2000/09/xmldsig#base64\",\n          },\n        },\n      ],\n    });\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='x']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    // Should have three Object elements\n    const objectNodes = selectNs(\"/root/ds:Signature/ds:Object\", doc);\n    isDomNode.assertIsArrayOfNodes(objectNodes);\n    expect(objectNodes.length).to.equal(3);\n\n    // Verify the first Object element\n    const object1 = objectNodes[0];\n    isDomNode.assertIsElementNode(object1);\n    expect(object1.getAttribute(\"Id\")).to.equal(\"object1\");\n    expect(object1.getAttribute(\"MimeType\")).to.equal(\"text/xml\");\n    expect(object1.hasAttribute(\"Encoding\")).to.be.true;\n    expect(object1.getAttribute(\"Encoding\")).to.equal(\"\");\n    const object1Data = select1Ns(\"ds:Data\", object1);\n    isDomNode.assertIsElementNode(object1Data);\n    expect(object1Data.textContent).to.equal(\"Test data in Object element\");\n\n    // Verify the second Object element\n    const object2 = objectNodes[1];\n    isDomNode.assertIsElementNode(object2);\n    expect(object2.getAttribute(\"Id\")).to.equal(\"object2\");\n    expect(object2.getAttribute(\"MimeType\")).to.equal(\"text/plain\");\n    expect(object2.hasAttribute(\"Encoding\")).to.be.false;\n    expect(object2.textContent).to.equal(\"Plain text content\");\n\n    // Verify the third Object element\n    const object3 = objectNodes[2];\n    isDomNode.assertIsElementNode(object3);\n    expect(object3.getAttribute(\"Id\")).to.equal(\"object3\");\n    expect(object3.getAttribute(\"MimeType\")).to.equal(\"text/plain\");\n    expect(object3.getAttribute(\"Encoding\")).to.equal(\"http://www.w3.org/2000/09/xmldsig#base64\");\n    assert(object3.textContent);\n    expect(Buffer.from(object3.textContent, \"base64\").toString(\"utf-8\")).to.equal(\n      \"This is base64 encoded data\",\n    );\n  });\n\n  it(\"should have correct ds:Object namespace when there is no default namespace\", function () {\n    const xml = \"<root></root>\";\n\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      objects: [\n        {\n          content: \"Test data\",\n          attributes: {\n            Id: \"object1\",\n            MimeType: \"text/plain\",\n          },\n        },\n      ],\n    });\n\n    sig.addReference({\n      xpath: \"/*\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    // When we add a prefix to the signature, there is no default namespace\n    sig.computeSignature(xml, { prefix: \"ds\" });\n    const signedXml = sig.getSignedXml();\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    // Verify the namespace of the ds:Object element\n    const objectNode = select1Ns(\"/root/ds:Signature/ds:Object[@Id='object1']\", doc);\n    isDomNode.assertIsElementNode(objectNode);\n  });\n\n  it(\"should handle empty or undefined objects\", function () {\n    const xml = \"<root></root>\";\n\n    // Test with undefined objects\n    const sigWithNull = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      objects: undefined,\n    });\n\n    sigWithNull.addReference({\n      xpath: \"/*\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sigWithNull.computeSignature(xml);\n    const signedXmlWithNull = sigWithNull.getSignedXml();\n    const docWithNull = new xmldom.DOMParser().parseFromString(signedXmlWithNull);\n\n    // Verify that no Object elements exist\n    const objectNodesWithNull = selectNs(\"//ds:Object\", docWithNull);\n    isDomNode.assertIsArrayOfNodes(objectNodesWithNull);\n    expect(objectNodesWithNull.length).to.equal(0);\n\n    // Test with empty array objects\n    const sigWithEmpty = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      objects: [],\n    });\n\n    sigWithEmpty.addReference({\n      xpath: \"/*\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sigWithEmpty.computeSignature(xml);\n    const signedXmlWithEmpty = sigWithEmpty.getSignedXml();\n    const docWithEmpty = new xmldom.DOMParser().parseFromString(signedXmlWithEmpty);\n\n    // Verify that no Object elements exist\n    const objectNodesWithEmpty = selectNs(\"//ds:Object\", docWithEmpty);\n    isDomNode.assertIsArrayOfNodes(objectNodesWithEmpty);\n    expect(objectNodesWithEmpty.length).to.equal(0);\n  });\n\n  it(\"should handle Reference to Object\", function () {\n    const xml = \"<root></root>\";\n\n    const sig = new SignedXml({\n      privateKey: privateKey,\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      objects: [\n        {\n          content:\n            \"<Test xmlns:ns1='http://example.com/ns1' xmlns:ns2='http://example.com/ns2'>Content</Test>\",\n          attributes: {\n            Id: \"object1\",\n          },\n        },\n      ],\n    });\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='Object' and @Id='object1']\",\n      inclusiveNamespacesPrefixList: [\"ns1\", \"ns2\"],\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n    const signedDoc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    // Verify that there is exactly one ds:Reference\n    const referenceNodes = selectNs(\"/root/ds:Signature/ds:SignedInfo/ds:Reference\", signedDoc);\n    isDomNode.assertIsArrayOfNodes(referenceNodes);\n    expect(referenceNodes.length).to.equal(1);\n    const referenceEl = referenceNodes[0];\n    isDomNode.assertIsElementNode(referenceEl);\n\n    // Verify that the Reference URI points to the Object\n    expect(referenceEl.getAttribute(\"URI\")).to.equal(\"#object1\");\n\n    // Verify that the Reference contains the correct Transform\n    const transformEl = select1Ns(\"ds:Transforms/ds:Transform\", referenceEl);\n    isDomNode.assertIsElementNode(transformEl);\n    expect(transformEl.getAttribute(\"Algorithm\")).to.equal(\n      \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n    );\n\n    // Verify that the InclusiveNamespacesPrefixList is set correctly\n    const inclusiveNamespacesEl = select1Ns(\"ec:InclusiveNamespaces\", transformEl, {\n      ec: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n    });\n    isDomNode.assertIsElementNode(inclusiveNamespacesEl);\n    expect(inclusiveNamespacesEl.getAttribute(\"PrefixList\")).to.equal(\"ns1 ns2\");\n\n    // Verify that the Reference contains the correct DigestMethod\n    const digestMethodEl = select1Ns(\"ds:DigestMethod\", referenceEl);\n    isDomNode.assertIsElementNode(digestMethodEl);\n    expect(digestMethodEl.getAttribute(\"Algorithm\")).to.equal(\n      \"http://www.w3.org/2000/09/xmldsig#sha1\",\n    );\n\n    // Verify that the Reference contains a non-empty DigestValue\n    const digestValueEl = select1Ns(\"ds:DigestValue\", referenceEl);\n    isDomNode.assertIsElementNode(digestValueEl);\n    expect(digestValueEl.textContent).to.not.be.empty;\n  });\n});\n\ndescribe(\"Valid signatures with ds:Object elements\", function () {\n  it(\"should create valid signatures with NO references to ds:Object\", function () {\n    const xml = \"<root></root>\";\n\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      objects: [\n        {\n          content: \"<Data>Test data in Object element</Data>\",\n          attributes: {\n            Id: \"object1\",\n            MimeType: \"text/xml\",\n          },\n        },\n      ],\n    });\n\n    sig.addReference({\n      xpath: \"/*\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      ],\n    });\n\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    // Verify that the signature is valid\n    const { valid, errorMessage } = checkSignature(signedXml, doc);\n    expect(valid, errorMessage).to.be.true;\n  });\n\n  it(\"should create valid signatures with references to ds:Object\", () => {\n    const xml = '<ns1:root xmlns:ns1=\"uri:ns1\"></ns1:root>';\n\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      inclusiveNamespacesPrefixList: [\"ns1\", \"ns2\"],\n      objects: [\n        {\n          content:\n            '<Data xmlns:ns2=\"uri:ns2\" xmlns:ns3=\"uri:ns3\">Test data in Object element</Data>',\n          attributes: {\n            Id: \"object1\",\n            MimeType: \"text/xml\",\n          },\n        },\n      ],\n    });\n\n    sig.addReference({\n      xpath: \"/*\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      ],\n    });\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='Object' and @Id='object1']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      ],\n      inclusiveNamespacesPrefixList: [\"ns1\", \"ns3\"],\n    });\n\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    // Verify that there are two Reference elements\n    const referenceNodes = selectNs(\"/ns1:root/ds:Signature/ds:SignedInfo/ds:Reference\", doc, {\n      ns1: \"uri:ns1\",\n    });\n    isDomNode.assertIsArrayOfNodes(referenceNodes);\n    expect(referenceNodes.length).to.equal(2);\n\n    // Verify that the second Reference points to the ds:Object\n    const objectReference = referenceNodes[1];\n    isDomNode.assertIsElementNode(objectReference);\n    expect(objectReference.getAttribute(\"URI\")).to.equal(\"#object1\");\n\n    // Verify that the signature is valid\n    const { valid, errorMessage } = checkSignature(signedXml, doc);\n    expect(valid, errorMessage).to.be.true;\n  });\n\n  it(\"should create valid signature and generate Id attribute for ds:Object when not provided\", function () {\n    const xml = \"<root></root>\";\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      objects: [\n        {\n          content: \"<Data>Test data in Object element</Data>\",\n        },\n      ],\n    });\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='Data']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      ],\n    });\n\n    sig.computeSignature(xml, { prefix: \"ds\" });\n    const signedXml = sig.getSignedXml();\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    // Find the ds:Object/Data element and get the value of its Id attribute (ensuring it was generated)\n    const dataEl = select1Ns(\"/root/ds:Signature/ds:Object/Data[@Id]\", doc);\n    isDomNode.assertIsElementNode(dataEl);\n    const idValue = dataEl.getAttribute(\"Id\");\n    expect(idValue).to.be.a(\"string\").that.is.not.empty;\n\n    // Verify that there is a Reference pointing to the generated Id\n    const uri = `#${idValue}`;\n    const refEl = select1Ns(`/root/ds:Signature/ds:SignedInfo/ds:Reference[@URI='${uri}']`, doc);\n    isDomNode.assertIsElementNode(refEl);\n\n    // Verify that the signature is valid\n    const { valid, errorMessage } = checkSignature(signedXml, doc);\n    expect(valid, errorMessage).to.be.true;\n  });\n});\n\ndescribe(\"Should successfuly sign references to ds:KeyInfo elements\", function () {\n  it(\"should create valid signatures with references to ds:KeyInfo when the Id attribute is provided\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      keyInfoAttributes: {\n        Id: \"key-info-1\",\n      },\n      getKeyInfoContent: () => \"<dummy></dummy>\",\n    });\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='KeyInfo']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      ],\n    });\n\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    // Verify that there is a Reference to KeyInfo\n    const referenceEl = select1Ns(\n      \"/root/ds:Signature/ds:SignedInfo/ds:Reference[@URI='#key-info-1']\",\n      doc,\n    );\n    isDomNode.assertIsElementNode(referenceEl);\n\n    // Verify that the signature is valid\n    const { valid, errorMessage } = checkSignature(signedXml, doc);\n    expect(valid, errorMessage).to.be.true;\n  });\n\n  it(\"should create valid signatures with references to ds:KeyInfo when the Id attribute is autogenerated\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n      getKeyInfoContent: () => \"<dummy></dummy>\",\n    });\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='KeyInfo']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      ],\n    });\n\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    // Find the KeyInfo element and get the value of its Id attribute (ensuring it was generated)\n    const keyInfoEl = select1Ns(\"/root/ds:Signature/ds:KeyInfo[@Id]\", doc);\n    isDomNode.assertIsElementNode(keyInfoEl);\n    const idValue = keyInfoEl.getAttribute(\"Id\");\n    expect(idValue).to.be.a(\"string\").that.is.not.empty;\n\n    // Find a Reference with URI=`#${idValue}`\n    const uri = `#${idValue}`;\n    const referenceEl = select1Ns(\n      `/root/ds:Signature/ds:SignedInfo/ds:Reference[@URI='${uri}']`,\n      doc,\n    );\n    isDomNode.assertIsElementNode(referenceEl);\n\n    // Verify that the signature is valid\n    const { valid, errorMessage } = checkSignature(signedXml, doc);\n    expect(valid, errorMessage).to.be.true;\n  });\n});\n\ndescribe(\"XAdES Object support in XML signatures\", function () {\n  it(\"should be able to add and sign XAdES objects\", function () {\n    const signatureId = \"signature_0\";\n    const signedPropertiesId = \"signedProperties_0\";\n\n    const publicCertDigest = new Sha256().getHash(publicCertDer);\n    const xml = `<root><content>text</content></root>`;\n\n    const sig = new SignedXml({\n      publicCert,\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\",\n      objects: [\n        {\n          content:\n            `<xades:QualifyingProperties xmlns:xades=\"http://uri.etsi.org/01903/v1.3.2#\" Target=\"#${signatureId}\">` +\n            `<xades:SignedProperties Id=\"${signedPropertiesId}\">` +\n            `<xades:SignedSignatureProperties>` +\n            `<xades:SigningTime>2025-06-21T12:00:00Z</xades:SigningTime>` +\n            `<xades:SigningCertificateV2><xades:Cert><xades:CertDigest>` +\n            `<ds:DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\"/>` +\n            `<ds:DigestValue>${publicCertDigest}</ds:DigestValue>` +\n            `</xades:CertDigest></xades:Cert></xades:SigningCertificateV2>` +\n            `</xades:SignedSignatureProperties>` +\n            `</xades:SignedProperties>` +\n            `</xades:QualifyingProperties>`,\n        },\n      ],\n    });\n\n    sig.addReference({\n      xpath: `/*`,\n      isEmptyUri: true,\n      digestAlgorithm: \"http://www.w3.org/2001/04/xmlenc#sha256\",\n      transforms: [\n        \"http://www.w3.org/2000/09/xmldsig#enveloped-signature\",\n        \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      ],\n    });\n\n    sig.addReference({\n      xpath: `//*[@Id='${signedPropertiesId}']`,\n      type: \"http://uri.etsi.org/01903#SignedProperties\",\n      digestAlgorithm: \"http://www.w3.org/2001/04/xmlenc#sha256\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.computeSignature(xml, {\n      prefix: \"ds\",\n      location: {\n        action: \"append\",\n        reference: \"/root\",\n      },\n      attrs: {\n        Id: signatureId,\n      },\n    });\n\n    const signedXml = sig.getSignedXml();\n    const signedDoc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    // ds:Signature exists and has the expected Id\n    const elSig = select1Ns(`/root/ds:Signature[@Id='${signatureId}']`, signedDoc);\n    isDomNode.assertIsElementNode(elSig);\n\n    // ds:Object/xades:QualifyingProperties exists within the signature\n    const elQP = select1Ns(\"ds:Object/xades:QualifyingProperties\", elSig);\n    isDomNode.assertIsElementNode(elQP);\n\n    // The Reference to SignedProperties exists and has the correct URI and Type\n    const elSPRef = select1Ns(\n      `ds:SignedInfo/ds:Reference[@URI='#${signedPropertiesId}' and @Type='http://uri.etsi.org/01903#SignedProperties']`,\n      elSig,\n    );\n    isDomNode.assertIsElementNode(elSPRef);\n\n    // Verify that the signature is valid\n    const { valid, errorMessage } = checkSignature(signedXml, signedDoc);\n    expect(valid, errorMessage).to.be.true;\n  });\n});\n\ndescribe(\"Signature self-reference prevention\", function () {\n  it(\"should not allow self-referencing the Signature element\", function () {\n    const xml = \"<root></root>\";\n\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n    });\n\n    sig.addReference({\n      xpath: \".//*[local-name(.)='Signature']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    expect(() => {\n      sig.computeSignature(xml);\n    }).to.throw(/Cannot sign a reference to the Signature or SignedInfo element itself/);\n  });\n\n  it(\"should not allow self-referencing the SignedInfo element\", function () {\n    const xml = \"<root></root>\";\n\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n    });\n\n    sig.addReference({\n      xpath: \".//*[local-name(.)='SignedInfo']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    expect(() => {\n      sig.computeSignature(xml);\n    }).to.throw(/Cannot sign a reference to the Signature or SignedInfo element itself/);\n  });\n\n  it(\"should not allow signing children of the SignedInfo element\", function () {\n    const xml = \"<root></root>\";\n\n    const sig = new SignedXml({\n      privateKey,\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n    });\n\n    sig.addReference({\n      xpath: \"/*\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.addReference({\n      xpath: \".//*[local-name(.)='Reference']/*\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    expect(() => {\n      sig.computeSignature(xml);\n    }).to.throw(/Cannot sign a reference to the Signature or SignedInfo element itself/);\n  });\n});\n"
  },
  {
    "path": "test/signature-unit-tests.spec.ts",
    "content": "import * as xpath from \"xpath\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport { SignedXml, createOptionalCallbackFunction } from \"../src/index\";\nimport * as fs from \"fs\";\nimport * as crypto from \"crypto\";\nimport { expect } from \"chai\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\nconst signatureAlgorithms = [\n  \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n  \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\",\n  \"http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1\",\n  \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512\",\n];\n\ndescribe(\"Signature unit tests\", function () {\n  describe(\"sign and verify\", function () {\n    signatureAlgorithms.forEach((signatureAlgorithm) => {\n      function signWith(signatureAlgorithm: string): string {\n        const xml = '<root><x attr=\"value\"></x></root>';\n        const sig = new SignedXml();\n        sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n        sig.addReference({\n          xpath: \"//*[local-name(.)='x']\",\n          digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n          transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n        });\n\n        sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n        sig.signatureAlgorithm = signatureAlgorithm;\n        sig.computeSignature(xml);\n        return sig.getSignedXml();\n      }\n\n      function loadSignature(xml: string): SignedXml {\n        const doc = new xmldom.DOMParser().parseFromString(xml);\n        const node = xpath.select1(\n          \"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n          doc,\n        );\n        isDomNode.assertIsNodeLike(node);\n        const sig = new SignedXml();\n        sig.publicCert = fs.readFileSync(\"./test/static/client_public.pem\");\n        sig.loadSignature(node);\n        return sig;\n      }\n\n      it(`should verify signed xml with ${signatureAlgorithm}`, function () {\n        const xml = signWith(signatureAlgorithm);\n        const sig = loadSignature(xml);\n        const res = sig.checkSignature(xml);\n        expect(\n          res,\n          `expected all signatures with ${signatureAlgorithm} to be valid, but some reported invalid`,\n        ).to.be.true;\n      });\n\n      it(`should fail verification of signed xml with ${signatureAlgorithm} after manipulation`, function () {\n        const xml = signWith(signatureAlgorithm);\n        const doc = new xmldom.DOMParser().parseFromString(xml);\n        const node = xpath.select1(\"//*[local-name(.)='x']\", doc);\n        isDomNode.assertIsElementNode(node);\n        const targetElement = node as Element;\n        targetElement.setAttribute(\"attr\", \"manipulatedValue\");\n        const manipulatedXml = new xmldom.XMLSerializer().serializeToString(doc);\n\n        const sig = loadSignature(manipulatedXml);\n        const res = sig.checkSignature(manipulatedXml);\n        expect(\n          res,\n          `expected all signatures with ${signatureAlgorithm} to be invalid, but some reported valid`,\n        ).to.be.false;\n      });\n    });\n  });\n\n  describe(\"verify adds ID\", function () {\n    function nodeExists(doc, xpathArg) {\n      if (!doc && !xpathArg) {\n        return;\n      }\n      const node = xpath.select(xpathArg, doc);\n      isDomNode.assertIsArrayOfNodes(node);\n      expect(node.length, `xpath ${xpathArg} not found`).to.equal(1);\n    }\n\n    function verifyAddsId(mode, nsMode) {\n      const xml = '<root><x xmlns=\"ns\"></x><y attr=\"value\"></y><z><w></w></z></root>';\n      const sig = new SignedXml({ idMode: mode });\n      sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n      sig.addReference({\n        xpath: \"//*[local-name(.)='x']\",\n        digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n        transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n      });\n      sig.addReference({\n        xpath: \"//*[local-name(.)='y']\",\n        digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n        transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n      });\n      sig.addReference({\n        xpath: \"//*[local-name(.)='w']\",\n        digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n        transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n      });\n\n      sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n      sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n      sig.computeSignature(xml);\n      const signedXml = sig.getOriginalXmlWithIds();\n      const doc = new xmldom.DOMParser().parseFromString(signedXml);\n\n      const op = nsMode === \"equal\" ? \"=\" : \"!=\";\n\n      const xpathArg = `//*[local-name(.)='{elem}' and '_{id}' = @*[local-name(.)='Id' and namespace-uri(.)${op}'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd']]`;\n\n      //verify each of the signed nodes now has an \"Id\" attribute with the right value\n      nodeExists(doc, xpathArg.replace(\"{id}\", \"0\").replace(\"{elem}\", \"x\"));\n      nodeExists(doc, xpathArg.replace(\"{id}\", \"1\").replace(\"{elem}\", \"y\"));\n      nodeExists(doc, xpathArg.replace(\"{id}\", \"2\").replace(\"{elem}\", \"w\"));\n    }\n\n    it(\"signer adds increasing different id attributes to elements\", function () {\n      verifyAddsId(null, \"different\");\n    });\n\n    it(\"signer adds increasing equal id attributes to elements\", function () {\n      verifyAddsId(\"wssecurity\", \"equal\");\n    });\n  });\n\n  it(\"signer adds references with namespaces\", function () {\n    const xml =\n      '<root xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"><name wsu:Id=\"_1\">xml-crypto</name><repository wsu:Id=\"_2\">github</repository></root>';\n    const sig = new SignedXml({ idMode: \"wssecurity\" });\n\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[@wsu:Id]\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml, {\n      existingPrefixes: {\n        wsu: \"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\",\n      },\n    });\n\n    const signedXml = sig.getSignatureXml();\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const references = xpath.select(\"//*[local-name(.)='Reference']\", doc);\n    isDomNode.assertIsArrayOfNodes(references);\n    expect(references.length).to.equal(2);\n  });\n\n  describe(\"signer does not duplicate id attributes\", function () {\n    function verifyDoesNotDuplicateIdAttributes(prefix: string, idMode?: \"wssecurity\") {\n      const xml = `<x xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd' ${prefix}Id='_1'></x>`;\n      const sig = new SignedXml({ idMode });\n      sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n      sig.addReference({\n        xpath: \"//*[local-name(.)='x']\",\n        digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n        transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n      });\n      sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n      sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n      sig.computeSignature(xml);\n      const signedXml = sig.getOriginalXmlWithIds();\n      const doc = new xmldom.DOMParser().parseFromString(signedXml);\n      const attrs = xpath.select(\"//@*\", doc);\n      isDomNode.assertIsArrayOfNodes(attrs);\n      expect(attrs.length, \"wrong number of attributes\").to.equal(2);\n    }\n\n    it(\"signer does not implicitly duplicate existing id attributes\", function () {\n      verifyDoesNotDuplicateIdAttributes(\"\");\n    });\n\n    it(\"signer does not explicitly duplicate existing id attributes\", function () {\n      verifyDoesNotDuplicateIdAttributes(\"wsu:\", \"wssecurity\");\n    });\n  });\n\n  it(\"signer adds custom attributes to the signature root node\", function () {\n    const xml = '<root xmlns=\"ns\"><name>xml-crypto</name><repository>github</repository></root>';\n    const sig = new SignedXml();\n    const attrs = {\n      Id: \"signatureTest\",\n      data: \"dataValue\",\n      xmlns: \"http://custom-xmlns#\",\n    };\n\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='name']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml, {\n      attrs: attrs,\n    });\n\n    const signedXml = sig.getSignatureXml();\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const signatureNode = doc.documentElement;\n\n    expect(attrs.Id, `Id attribute is not equal to the expected value: \"${attrs.Id}\"`).to.equal(\n      signatureNode.getAttribute(\"Id\"),\n    );\n    expect(\n      attrs.data,\n      `data attribute is not equal to the expected value: \"${attrs.data}\"`,\n    ).to.equal(signatureNode.getAttribute(\"data\"));\n    expect(attrs.xmlns, \"xmlns attribute can not be overridden\").not.to.equal(\n      signatureNode.getAttribute(\"xmlns\"),\n    );\n    expect(\n      signatureNode.getAttribute(\"xmlns\"),\n      'xmlns attribute is not equal to the expected value: \"http://www.w3.org/2000/09/xmldsig#\"',\n    ).to.equal(\"http://www.w3.org/2000/09/xmldsig#\");\n  });\n\n  it(\"signer appends signature to the root node by default\", function () {\n    const xml = \"<root><name>xml-crypto</name><repository>github</repository></root>\";\n    const sig = new SignedXml();\n\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.addReference({\n      xpath: \"//*[local-name(.)='name']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n\n    const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());\n\n    const lastChild = doc.documentElement.lastChild;\n    isDomNode.assertIsElementNode(lastChild);\n    expect(\n      lastChild.localName,\n      \"the signature must be appended to the root node by default\",\n    ).to.equal(\"Signature\");\n  });\n\n  it(\"signer appends signature to a reference node\", function () {\n    const xml = \"<root><name>xml-crypto</name><repository>github</repository></root>\";\n    const sig = new SignedXml();\n\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.addReference({\n      xpath: \"//*[local-name(.)='repository']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml, {\n      location: {\n        reference: \"/root/name\",\n        action: \"append\",\n      },\n    });\n\n    const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());\n    const referenceNode = xpath.select1(\"/root/name\", doc);\n\n    isDomNode.assertIsNodeLike(referenceNode);\n    const lastChild = referenceNode.lastChild;\n\n    isDomNode.assertIsElementNode(lastChild);\n    expect(lastChild.localName, \"the signature should be appended to root/name\").to.equal(\n      \"Signature\",\n    );\n  });\n\n  it(\"signer prepends signature to a reference node\", function () {\n    const xml = \"<root><name>xml-crypto</name><repository>github</repository></root>\";\n    const sig = new SignedXml();\n\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.addReference({\n      xpath: \"//*[local-name(.)='repository']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml, {\n      location: {\n        reference: \"/root/name\",\n        action: \"prepend\",\n      },\n    });\n\n    const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());\n    const referenceNode = xpath.select1(\"/root/name\", doc);\n    isDomNode.assertIsNodeLike(referenceNode);\n    const firstChild = referenceNode.firstChild;\n\n    isDomNode.assertIsElementNode(firstChild);\n    expect(firstChild.localName, \"the signature should be prepended to root/name\").to.equal(\n      \"Signature\",\n    );\n  });\n\n  it(\"signer inserts signature before a reference node\", function () {\n    const xml = \"<root><name>xml-crypto</name><repository>github</repository></root>\";\n    const sig = new SignedXml();\n\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.addReference({\n      xpath: \"//*[local-name(.)='repository']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml, {\n      location: {\n        reference: \"/root/name\",\n        action: \"before\",\n      },\n    });\n\n    const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());\n    const referenceNode = xpath.select1(\"/root/name\", doc);\n    isDomNode.assertIsNodeLike(referenceNode);\n    const previousSibling = referenceNode.previousSibling;\n\n    isDomNode.assertIsElementNode(previousSibling);\n    expect(\n      previousSibling.localName,\n      \"the signature should be inserted before to root/name\",\n    ).to.equal(\"Signature\");\n  });\n\n  it(\"signer inserts signature after a reference node\", function () {\n    const xml = \"<root><name>xml-crypto</name><repository>github</repository></root>\";\n    const sig = new SignedXml();\n\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.addReference({\n      xpath: \"//*[local-name(.)='repository']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml, {\n      location: {\n        reference: \"/root/name\",\n        action: \"after\",\n      },\n    });\n\n    const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());\n    const referenceNode = xpath.select1(\"/root/name\", doc);\n\n    isDomNode.assertIsNodeLike(referenceNode);\n    const nextSibling = referenceNode.nextSibling;\n\n    isDomNode.assertIsElementNode(nextSibling);\n    expect(nextSibling.localName, \"the signature should be inserted after to root/name\").to.equal(\n      \"Signature\",\n    );\n  });\n\n  it(\"signer creates signature with correct structure\", function () {\n    class DummyDigest {\n      getHash = function () {\n        return \"dummy digest\";\n      };\n\n      getAlgorithmName = function () {\n        return \"dummy digest algorithm\";\n      };\n    }\n\n    class DummySignatureAlgorithm {\n      verifySignature = function () {\n        return true;\n      };\n\n      getSignature = function () {\n        return \"dummy signature\";\n      };\n\n      getAlgorithmName = function () {\n        return \"dummy algorithm\";\n      };\n    }\n\n    class DummyTransformation {\n      includeComments = false;\n      process = function () {\n        return \"< x/>\";\n      };\n\n      getAlgorithmName = function () {\n        return \"dummy transformation\";\n      };\n    }\n\n    class DummyCanonicalization {\n      includeComments = false;\n      process = function () {\n        return \"< x/>\";\n      };\n\n      getAlgorithmName = function () {\n        return \"dummy canonicalization\";\n      };\n    }\n\n    const xml = '<root><x xmlns=\"ns\"></x><y attr=\"value\"></y><z><w></w></z></root>';\n    const sig = new SignedXml();\n\n    sig.CanonicalizationAlgorithms[\"http://DummyTransformation\"] = DummyTransformation;\n    sig.CanonicalizationAlgorithms[\"http://DummyCanonicalization\"] = DummyCanonicalization;\n    sig.HashAlgorithms[\"http://dummyDigest\"] = DummyDigest;\n    sig.SignatureAlgorithms[\"http://dummySignatureAlgorithm\"] = DummySignatureAlgorithm;\n\n    sig.signatureAlgorithm = \"http://dummySignatureAlgorithm\";\n    sig.getKeyInfoContent = function () {\n      return \"dummy key info\";\n    };\n    sig.canonicalizationAlgorithm = \"http://DummyCanonicalization\";\n    sig.privateKey = \"\";\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='x']\",\n      transforms: [\"http://DummyTransformation\"],\n      digestAlgorithm: \"http://dummyDigest\",\n    });\n    sig.addReference({\n      xpath: \"//*[local-name(.)='y']\",\n      transforms: [\"http://DummyTransformation\"],\n      digestAlgorithm: \"http://dummyDigest\",\n    });\n    sig.addReference({\n      xpath: \"//*[local-name(.)='w']\",\n      transforms: [\"http://DummyTransformation\"],\n      digestAlgorithm: \"http://dummyDigest\",\n    });\n\n    sig.computeSignature(xml);\n    const signature = sig.getSignatureXml();\n    const expected =\n      '<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">' +\n      \"<SignedInfo>\" +\n      '<CanonicalizationMethod Algorithm=\"dummy canonicalization\"/>' +\n      '<SignatureMethod Algorithm=\"dummy algorithm\"/>' +\n      '<Reference URI=\"#_0\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"dummy transformation\"/>' +\n      \"</Transforms>\" +\n      '<DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<DigestValue>dummy digest</DigestValue>\" +\n      \"</Reference>\" +\n      '<Reference URI=\"#_1\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"dummy transformation\"/>' +\n      \"</Transforms>\" +\n      '<DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<DigestValue>dummy digest</DigestValue>\" +\n      \"</Reference>\" +\n      '<Reference URI=\"#_2\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"dummy transformation\"/>' +\n      \"</Transforms>\" +\n      '<DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<DigestValue>dummy digest</DigestValue>\" +\n      \"</Reference>\" +\n      \"</SignedInfo>\" +\n      \"<SignatureValue>dummy signature</SignatureValue>\" +\n      \"<KeyInfo>\" +\n      \"dummy key info\" +\n      \"</KeyInfo>\" +\n      \"</Signature>\";\n\n    expect(expected, \"wrong signature format\").to.equal(signature);\n\n    const signedXml = sig.getSignedXml();\n    const expectedSignedXml =\n      '<root><x xmlns=\"ns\" Id=\"_0\"/><y attr=\"value\" Id=\"_1\"/><z><w Id=\"_2\"/></z>' +\n      '<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">' +\n      \"<SignedInfo>\" +\n      '<CanonicalizationMethod Algorithm=\"dummy canonicalization\"/>' +\n      '<SignatureMethod Algorithm=\"dummy algorithm\"/>' +\n      '<Reference URI=\"#_0\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"dummy transformation\"/>' +\n      \"</Transforms>\" +\n      '<DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<DigestValue>dummy digest</DigestValue>\" +\n      \"</Reference>\" +\n      '<Reference URI=\"#_1\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"dummy transformation\"/>' +\n      \"</Transforms>\" +\n      '<DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<DigestValue>dummy digest</DigestValue>\" +\n      \"</Reference>\" +\n      '<Reference URI=\"#_2\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"dummy transformation\"/>' +\n      \"</Transforms>\" +\n      '<DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<DigestValue>dummy digest</DigestValue>\" +\n      \"</Reference>\" +\n      \"</SignedInfo>\" +\n      \"<SignatureValue>dummy signature</SignatureValue>\" +\n      \"<KeyInfo>\" +\n      \"dummy key info\" +\n      \"</KeyInfo>\" +\n      \"</Signature>\" +\n      \"</root>\";\n\n    expect(expectedSignedXml, \"wrong signedXml format\").to.equal(signedXml);\n\n    const originalXmlWithIds = sig.getOriginalXmlWithIds();\n    const expectedOriginalXmlWithIds =\n      '<root><x xmlns=\"ns\" Id=\"_0\"/><y attr=\"value\" Id=\"_1\"/><z><w Id=\"_2\"/></z></root>';\n    expect(expectedOriginalXmlWithIds, \"wrong OriginalXmlWithIds\").to.equal(originalXmlWithIds);\n  });\n\n  it(\"signer creates signature with correct structure (with prefix)\", function () {\n    const prefix = \"ds\";\n\n    class DummyDigest {\n      getHash = function () {\n        return \"dummy digest\";\n      };\n\n      getAlgorithmName = function () {\n        return \"dummy digest algorithm\";\n      };\n    }\n\n    class DummySignatureAlgorithm {\n      verifySignature = function () {\n        return true;\n      };\n\n      getSignature = function () {\n        return \"dummy signature\";\n      };\n\n      getAlgorithmName = function () {\n        return \"dummy algorithm\";\n      };\n    }\n\n    class DummyTransformation {\n      includeComments = false;\n      process = function () {\n        return \"< x/>\";\n      };\n\n      getAlgorithmName = function () {\n        return \"dummy transformation\";\n      };\n    }\n\n    class DummyCanonicalization {\n      includeComments = false;\n      process = function () {\n        return \"< x/>\";\n      };\n\n      getAlgorithmName = function () {\n        return \"dummy canonicalization\";\n      };\n    }\n\n    const xml = '<root><x xmlns=\"ns\"></x><y attr=\"value\"></y><z><w></w></z></root>';\n    const sig = new SignedXml();\n\n    sig.publicCert = fs.readFileSync(\"./test/static/client_public.pem\");\n    sig.CanonicalizationAlgorithms[\"http://DummyTransformation\"] = DummyTransformation;\n    sig.CanonicalizationAlgorithms[\"http://DummyCanonicalization\"] = DummyCanonicalization;\n    sig.HashAlgorithms[\"http://dummyDigest\"] = DummyDigest;\n    sig.SignatureAlgorithms[\"http://dummySignatureAlgorithm\"] = DummySignatureAlgorithm;\n\n    sig.signatureAlgorithm = \"http://dummySignatureAlgorithm\";\n    sig.canonicalizationAlgorithm = \"http://DummyCanonicalization\";\n    sig.privateKey = \"\";\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='x']\",\n      transforms: [\"http://DummyTransformation\"],\n      digestAlgorithm: \"http://dummyDigest\",\n    });\n    sig.addReference({\n      xpath: \"//*[local-name(.)='y']\",\n      transforms: [\"http://DummyTransformation\"],\n      digestAlgorithm: \"http://dummyDigest\",\n    });\n    sig.addReference({\n      xpath: \"//*[local-name(.)='w']\",\n      transforms: [\"http://DummyTransformation\"],\n      digestAlgorithm: \"http://dummyDigest\",\n    });\n\n    sig.computeSignature(xml, { prefix: prefix });\n    const signature = sig.getSignatureXml();\n\n    const expected =\n      '<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">' +\n      \"<ds:SignedInfo>\" +\n      '<ds:CanonicalizationMethod Algorithm=\"dummy canonicalization\"/>' +\n      '<ds:SignatureMethod Algorithm=\"dummy algorithm\"/>' +\n      '<ds:Reference URI=\"#_0\">' +\n      \"<ds:Transforms>\" +\n      '<ds:Transform Algorithm=\"dummy transformation\"/>' +\n      \"</ds:Transforms>\" +\n      '<ds:DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<ds:DigestValue>dummy digest</ds:DigestValue>\" +\n      \"</ds:Reference>\" +\n      '<ds:Reference URI=\"#_1\">' +\n      \"<ds:Transforms>\" +\n      '<ds:Transform Algorithm=\"dummy transformation\"/>' +\n      \"</ds:Transforms>\" +\n      '<ds:DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<ds:DigestValue>dummy digest</ds:DigestValue>\" +\n      \"</ds:Reference>\" +\n      '<ds:Reference URI=\"#_2\">' +\n      \"<ds:Transforms>\" +\n      '<ds:Transform Algorithm=\"dummy transformation\"/>' +\n      \"</ds:Transforms>\" +\n      '<ds:DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<ds:DigestValue>dummy digest</ds:DigestValue>\" +\n      \"</ds:Reference>\" +\n      \"</ds:SignedInfo>\" +\n      \"<ds:SignatureValue>dummy signature</ds:SignatureValue>\" +\n      \"<ds:KeyInfo>\" +\n      \"<ds:X509Data>\" +\n      \"<ds:X509Certificate>MIIBxDCCAW6gAwIBAgIQxUSXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BAQQFADAWMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ3NTlaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0Q2xpZW50MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+L6aB9x928noY4+0QBsXnxkQE4quJl7c3PUPdVu7k9A02hRG481XIfWhrDY5i7OEB7KGW7qFJotLLeMec/UkKUwCgv3VvJrs2nE9xO3SSWIdNzADukYh+Cxt+FUU6tUkDeqg7dqwivOXhuOTRyOI3HqbWTbumaLdc8jufz2LhaQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcNAQEEBQADQQAfIbnMPVYkNNfX1tG1F+qfLhHwJdfDUZuPyRPucWF5qkh6sSdWVBY5sT/txBnVJGziyO8DPYdu2fPMER8ajJfl</ds:X509Certificate>\" +\n      \"</ds:X509Data>\" +\n      \"</ds:KeyInfo>\" +\n      \"</ds:Signature>\";\n\n    expect(signature, \"wrong signature format\").to.equal(expected);\n\n    const signedXml = sig.getSignedXml();\n    const expectedSignedXml =\n      '<root><x xmlns=\"ns\" Id=\"_0\"/><y attr=\"value\" Id=\"_1\"/><z><w Id=\"_2\"/></z>' +\n      '<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">' +\n      \"<ds:SignedInfo>\" +\n      '<ds:CanonicalizationMethod Algorithm=\"dummy canonicalization\"/>' +\n      '<ds:SignatureMethod Algorithm=\"dummy algorithm\"/>' +\n      '<ds:Reference URI=\"#_0\">' +\n      \"<ds:Transforms>\" +\n      '<ds:Transform Algorithm=\"dummy transformation\"/>' +\n      \"</ds:Transforms>\" +\n      '<ds:DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<ds:DigestValue>dummy digest</ds:DigestValue>\" +\n      \"</ds:Reference>\" +\n      '<ds:Reference URI=\"#_1\">' +\n      \"<ds:Transforms>\" +\n      '<ds:Transform Algorithm=\"dummy transformation\"/>' +\n      \"</ds:Transforms>\" +\n      '<ds:DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<ds:DigestValue>dummy digest</ds:DigestValue>\" +\n      \"</ds:Reference>\" +\n      '<ds:Reference URI=\"#_2\">' +\n      \"<ds:Transforms>\" +\n      '<ds:Transform Algorithm=\"dummy transformation\"/>' +\n      \"</ds:Transforms>\" +\n      '<ds:DigestMethod Algorithm=\"dummy digest algorithm\"/>' +\n      \"<ds:DigestValue>dummy digest</ds:DigestValue>\" +\n      \"</ds:Reference>\" +\n      \"</ds:SignedInfo>\" +\n      \"<ds:SignatureValue>dummy signature</ds:SignatureValue>\" +\n      \"<ds:KeyInfo>\" +\n      \"<ds:X509Data>\" +\n      \"<ds:X509Certificate>MIIBxDCCAW6gAwIBAgIQxUSXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BAQQFADAWMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ3NTlaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0Q2xpZW50MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+L6aB9x928noY4+0QBsXnxkQE4quJl7c3PUPdVu7k9A02hRG481XIfWhrDY5i7OEB7KGW7qFJotLLeMec/UkKUwCgv3VvJrs2nE9xO3SSWIdNzADukYh+Cxt+FUU6tUkDeqg7dqwivOXhuOTRyOI3HqbWTbumaLdc8jufz2LhaQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcNAQEEBQADQQAfIbnMPVYkNNfX1tG1F+qfLhHwJdfDUZuPyRPucWF5qkh6sSdWVBY5sT/txBnVJGziyO8DPYdu2fPMER8ajJfl</ds:X509Certificate>\" +\n      \"</ds:X509Data>\" +\n      \"</ds:KeyInfo>\" +\n      \"</ds:Signature>\" +\n      \"</root>\";\n\n    expect(signedXml, \"wrong signedXml format\").to.equal(expectedSignedXml);\n\n    const originalXmlWithIds = sig.getOriginalXmlWithIds();\n    const expectedOriginalXmlWithIds =\n      '<root><x xmlns=\"ns\" Id=\"_0\"/><y attr=\"value\" Id=\"_1\"/><z><w Id=\"_2\"/></z></root>';\n    expect(originalXmlWithIds, \"wrong OriginalXmlWithIds\").to.equal(expectedOriginalXmlWithIds);\n  });\n\n  it(\"signer creates correct signature values\", function () {\n    const xml =\n      '<root><x xmlns=\"ns\" Id=\"_0\"></x><y attr=\"value\" Id=\"_1\"></y><z><w Id=\"_2\"></w></z></root>';\n    const sig = new SignedXml();\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='x']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n    sig.addReference({\n      xpath: \"//*[local-name(.)='y']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n    sig.addReference({\n      xpath: \"//*[local-name(.)='w']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n    const expected =\n      '<root><x xmlns=\"ns\" Id=\"_0\"/><y attr=\"value\" Id=\"_1\"/><z><w Id=\"_2\"/></z>' +\n      '<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">' +\n      \"<SignedInfo>\" +\n      '<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>' +\n      '<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>' +\n      '<Reference URI=\"#_0\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms>' +\n      '<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>' +\n      \"<DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</DigestValue>\" +\n      \"</Reference>\" +\n      '<Reference URI=\"#_1\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>' +\n      \"</Transforms>\" +\n      '<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>' +\n      \"<DigestValue>4Pq/sBri+AyOtxtSFsPSOyylyzk=</DigestValue>\" +\n      \"</Reference>\" +\n      '<Reference URI=\"#_2\">' +\n      \"<Transforms>\" +\n      '<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>' +\n      \"</Transforms>\" +\n      '<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>' +\n      \"<DigestValue>6I7SDu1iV2YOajTlf+iMLIBfLnE=</DigestValue>\" +\n      \"</Reference>\" +\n      \"</SignedInfo>\" +\n      \"<SignatureValue>NejzGB9MDUddKCt3GL2vJhEd5q6NBuhLdQc3W4bJI5q34hk7Hk6zBRoW3OliX+/f7Hpi9y0INYoqMSUfrsAVm3IuPzUETKlI6xiNZo07ULRj1DwxRo6cU66ar1EKUQLRuCZas795FjB8jvUI2lyhcax/00uMJ+Cjf4bwAQ+9gOQ=</SignatureValue>\" +\n      \"</Signature>\" +\n      \"</root>\";\n\n    expect(expected, \"wrong signature format\").to.equal(signedXml);\n  });\n\n  it(\"signer creates correct signature values using async callback\", function () {\n    class DummySignatureAlgorithm {\n      verifySignature = function () {\n        return true;\n      };\n\n      getSignature = createOptionalCallbackFunction(\n        (signedInfo: crypto.BinaryLike, privateKey: crypto.KeyLike) => {\n          const signer = crypto.createSign(\"RSA-SHA1\");\n          signer.update(signedInfo);\n          const res = signer.sign(privateKey, \"base64\");\n          return res;\n        },\n      );\n\n      getAlgorithmName = function () {\n        return \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n      };\n    }\n\n    const xml =\n      '<root><x xmlns=\"ns\" Id=\"_0\"></x><y attr=\"value\" Id=\"_1\"></y><z><w Id=\"_2\"></w></z></root>';\n    const sig = new SignedXml();\n    sig.SignatureAlgorithms[\"http://dummySignatureAlgorithmAsync\"] = DummySignatureAlgorithm;\n    sig.signatureAlgorithm = \"http://dummySignatureAlgorithmAsync\";\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='x']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n    sig.addReference({\n      xpath: \"//*[local-name(.)='y']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n    sig.addReference({\n      xpath: \"//*[local-name(.)='w']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.computeSignature(xml, function () {\n      const signedXml = sig.getSignedXml();\n      const expected =\n        '<root><x xmlns=\"ns\" Id=\"_0\"/><y attr=\"value\" Id=\"_1\"/><z><w Id=\"_2\"/></z>' +\n        '<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">' +\n        \"<SignedInfo>\" +\n        '<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>' +\n        '<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>' +\n        '<Reference URI=\"#_0\">' +\n        \"<Transforms>\" +\n        '<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms>' +\n        '<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>' +\n        \"<DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</DigestValue>\" +\n        \"</Reference>\" +\n        '<Reference URI=\"#_1\">' +\n        \"<Transforms>\" +\n        '<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>' +\n        \"</Transforms>\" +\n        '<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>' +\n        \"<DigestValue>4Pq/sBri+AyOtxtSFsPSOyylyzk=</DigestValue>\" +\n        \"</Reference>\" +\n        '<Reference URI=\"#_2\">' +\n        \"<Transforms>\" +\n        '<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>' +\n        \"</Transforms>\" +\n        '<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>' +\n        \"<DigestValue>6I7SDu1iV2YOajTlf+iMLIBfLnE=</DigestValue>\" +\n        \"</Reference>\" +\n        \"</SignedInfo>\" +\n        \"<SignatureValue>NejzGB9MDUddKCt3GL2vJhEd5q6NBuhLdQc3W4bJI5q34hk7Hk6zBRoW3OliX+/f7Hpi9y0INYoqMSUfrsAVm3IuPzUETKlI6xiNZo07ULRj1DwxRo6cU66ar1EKUQLRuCZas795FjB8jvUI2lyhcax/00uMJ+Cjf4bwAQ+9gOQ=</SignatureValue>\" +\n        \"</Signature>\" +\n        \"</root>\";\n\n      expect(expected, \"wrong signature format\").to.equal(signedXml);\n    });\n  });\n\n  describe(\"verify existing signature\", function () {\n    describe(\"pass loading signatures\", function () {\n      function passLoadSignature(file: string, toString?: boolean) {\n        const xml = fs.readFileSync(file, \"utf8\");\n        const doc = new xmldom.DOMParser().parseFromString(xml);\n        const signature = xpath.select1(\n          \"/*//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n          doc,\n        );\n        isDomNode.assertIsElementNode(signature);\n        const sig = new SignedXml();\n        sig.loadSignature(toString ? signature.toString() : signature);\n\n        expect(sig.canonicalizationAlgorithm, \"wrong canonicalization method\").to.equal(\n          \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n        );\n\n        expect(sig.signatureAlgorithm, \"wrong signature method\").to.equal(\n          \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n        );\n\n        sig.getCertFromKeyInfo = (keyInfo) => {\n          isDomNode.assertIsNodeLike(keyInfo);\n          const keyInfoContents = xpath.select1(\n            \"//*[local-name(.)='KeyInfo']/*[local-name(.)='dummyKey']\",\n            keyInfo,\n          );\n          isDomNode.assertIsNodeLike(keyInfoContents);\n          const firstChild = keyInfoContents.firstChild;\n          isDomNode.assertIsTextNode(firstChild);\n          expect(firstChild.data, \"keyInfo clause not correctly loaded\").to.equal(\"1234\");\n\n          return fs.readFileSync(\"./test/static/client.pem\", \"latin1\");\n        };\n\n        const checkedSignature = sig.checkSignature(xml);\n        expect(checkedSignature).to.be.true;\n\n        /* eslint-disable-next-line deprecation/deprecation */\n        expect(sig.getReferences().length).to.equal(3);\n        expect(sig.getSignedReferences().length).to.equal(3);\n\n        const digests = [\n          \"b5GCZ2xpP5T7tbLWBTkOl4CYupQ=\",\n          \"K4dI497ZCxzweDIrbndUSmtoezY=\",\n          \"sH1gxKve8wlU8LlFVa2l6w3HMJ0=\",\n        ];\n\n        const firstGrandchild = doc.firstChild?.firstChild;\n        isDomNode.assertIsElementNode(firstGrandchild);\n        const matchedReference = sig.validateElementAgainstReferences(firstGrandchild, doc);\n        expect(matchedReference).to.not.be.false;\n\n        /* eslint-disable-next-line deprecation/deprecation */\n        for (let i = 0; i < sig.getReferences().length; i++) {\n          /* eslint-disable-next-line deprecation/deprecation */\n          const ref = sig.getReferences()[i];\n          const expectedUri = `#_${i}`;\n          expect(\n            ref.uri,\n            `wrong uri for index ${i}. expected: ${expectedUri} actual: ${ref.uri}`,\n          ).to.equal(expectedUri);\n          expect(ref.transforms.length).to.equal(1);\n          expect(ref.transforms[0]).to.equal(\"http://www.w3.org/2001/10/xml-exc-c14n#\");\n          expect(ref.digestValue).to.equal(digests[i]);\n          expect(ref.digestAlgorithm).to.equal(\"http://www.w3.org/2000/09/xmldsig#sha1\");\n        }\n      }\n\n      it(\"correctly loads signature\", function () {\n        passLoadSignature(\"./test/static/valid_signature.xml\");\n      });\n\n      it(\"correctly loads signature with validation\", function () {\n        passLoadSignature(\"./test/static/valid_signature.xml\", true);\n      });\n\n      it(\"correctly loads signature with root level sig namespace\", function () {\n        passLoadSignature(\"./test/static/valid_signature_with_root_level_sig_namespace.xml\");\n      });\n    });\n\n    describe(\"pass verify signature\", function () {\n      function loadSignature(xml: string, idMode?: \"wssecurity\") {\n        const doc = new xmldom.DOMParser().parseFromString(xml);\n        const node = xpath.select1(\n          \"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n          doc,\n        );\n        isDomNode.assertIsNodeLike(node);\n        const sig = new SignedXml({ idMode });\n        sig.publicCert = fs.readFileSync(\"./test/static/client_public.pem\");\n        sig.loadSignature(node);\n\n        return sig;\n      }\n\n      function passValidSignature(file: string, mode?: \"wssecurity\") {\n        const xml = fs.readFileSync(file, \"utf8\");\n        const sig = loadSignature(xml, mode);\n        const res = sig.checkSignature(xml);\n        expect(res, \"expected all signatures to be valid, but some reported invalid\").to.be.true;\n        /* eslint-disable-next-line deprecation/deprecation */\n        expect(sig.getSignedReferences().length).to.equal(sig.getReferences().length);\n      }\n\n      function failInvalidSignature(file: string, idMode?: \"wssecurity\") {\n        const xml = fs.readFileSync(file).toString();\n        const sig = loadSignature(xml, idMode);\n        const res = sig.checkSignature(xml);\n        expect(res, \"expected a signature to be invalid, but all were reported valid\").to.be.false;\n        expect(sig.getSignedReferences().length).to.equal(0);\n      }\n\n      function throwsValidatingSignature(file: string, idMode?: \"wssecurity\") {\n        const xml = fs.readFileSync(file).toString();\n        const sig = loadSignature(xml, idMode);\n        expect(\n          () => sig.checkSignature(xml),\n          \"expected an error to be thrown because signatures couldn't be checked for validity\",\n        ).to.throw();\n        expect(sig.getSignedReferences().length).to.equal(0);\n      }\n\n      it(\"verifies valid signature\", function () {\n        passValidSignature(\"./test/static/valid_signature.xml\");\n      });\n\n      it(\"verifies valid signature with lowercase id attribute\", function () {\n        passValidSignature(\"./test/static/valid_signature_with_lowercase_id_attribute.xml\");\n      });\n\n      it(\"verifies valid signature with wsu\", function () {\n        passValidSignature(\"./test/static/valid_signature wsu.xml\", \"wssecurity\");\n      });\n\n      it(\"verifies valid signature with reference keyInfo\", function () {\n        passValidSignature(\"./test/static/valid_signature_with_reference_keyInfo.xml\");\n      });\n\n      it(\"verifies valid signature with whitespace in digestvalue\", function () {\n        passValidSignature(\"./test/static/valid_signature_with_whitespace_in_digestvalue.xml\");\n      });\n\n      it(\"verifies valid utf8 signature\", function () {\n        passValidSignature(\"./test/static/valid_signature_utf8.xml\");\n      });\n\n      it(\"verifies valid signature with unused prefixes\", function () {\n        passValidSignature(\"./test/static/valid_signature_with_unused_prefixes.xml\");\n      });\n\n      it(\"verifies valid signature without transforms element\", function () {\n        passValidSignature(\"./test/static/valid_signature_without_transforms_element.xml\");\n      });\n\n      it(\"throws validating signature - signature value\", function () {\n        throwsValidatingSignature(\"./test/static/invalid_signature - signature value.xml\");\n      });\n\n      it(\"fails invalid signature - hash\", function () {\n        failInvalidSignature(\"./test/static/invalid_signature - hash.xml\");\n      });\n\n      it(\"fails invalid signature - non existing reference\", function () {\n        failInvalidSignature(\"./test/static/invalid_signature - non existing reference.xml\");\n      });\n\n      it(\"fails invalid signature - changed content\", function () {\n        failInvalidSignature(\"./test/static/invalid_signature - changed content.xml\");\n      });\n\n      it(\"fails invalid signature - wsu - invalid signature value\", function () {\n        failInvalidSignature(\n          \"./test/static/invalid_signature - wsu - invalid signature value.xml\",\n          \"wssecurity\",\n        );\n      });\n\n      it(\"fails invalid signature - wsu - hash\", function () {\n        failInvalidSignature(\"./test/static/invalid_signature - wsu - hash.xml\", \"wssecurity\");\n      });\n\n      it(\"fails invalid signature - wsu - non existing reference\", function () {\n        failInvalidSignature(\n          \"./test/static/invalid_signature - wsu - non existing reference.xml\",\n          \"wssecurity\",\n        );\n      });\n\n      it(\"fails invalid signature - wsu - changed content\", function () {\n        failInvalidSignature(\n          \"./test/static/invalid_signature - wsu - changed content.xml\",\n          \"wssecurity\",\n        );\n      });\n\n      it(\"fails invalid signature without transforms element\", function () {\n        failInvalidSignature(\"./test/static/invalid_signature_without_transforms_element.xml\");\n      });\n    });\n  });\n\n  it(\"allow empty reference uri when signing\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml();\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='root']\",\n      transforms: [\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"],\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      uri: \"\",\n      digestValue: \"\",\n      inclusiveNamespacesPrefixList: [],\n      isEmptyUri: true,\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const URI = xpath.select1(\"//*[local-name(.)='Reference']/@URI\", doc);\n    isDomNode.assertIsAttributeNode(URI);\n    expect(URI.value, `uri should be empty but instead was ${URI.value}`).to.equal(\"\");\n  });\n\n  it(\"signer appends signature to a non-existing reference node\", function () {\n    const xml = \"<root><name>xml-crypto</name><repository>github</repository></root>\";\n    const sig = new SignedXml();\n\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.addReference({\n      xpath: \"//*[local-name(.)='repository']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    try {\n      sig.computeSignature(xml, {\n        location: {\n          reference: \"/root/foobar\",\n          action: \"append\",\n        },\n      });\n      expect.fail(\"Expected an error to be thrown\");\n    } catch (err) {\n      expect(err).not.to.be.an.instanceof(TypeError);\n    }\n  });\n\n  it(\"signer adds existing prefixes\", function () {\n    function getKeyInfoContentWithAssertionId({ assertionId }) {\n      return (\n        `<wsse:SecurityTokenReference wsse11:TokenType=\"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1\" wsu:Id=\"0\" ` +\n        `xmlns:wsse11=\"http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd\"> ` +\n        `<wsse:KeyIdentifier ValueType=\"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID\">${assertionId}</wsse:KeyIdentifier>` +\n        `</wsse:SecurityTokenReference>`\n      );\n    }\n\n    const xml =\n      '<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"> ' +\n      \"<SOAP-ENV:Header> \" +\n      \"<wsse:Security \" +\n      'xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" ' +\n      'xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"> ' +\n      \"<Assertion></Assertion> \" +\n      \"</wsse:Security> \" +\n      \"</SOAP-ENV:Header> \" +\n      \"</SOAP-ENV:Envelope>\";\n\n    const sig = new SignedXml();\n    const assertionId = \"_81d5fba5c807be9e9cf60c58566349b1\";\n    sig.getKeyInfoContent = getKeyInfoContentWithAssertionId.bind(this, { assertionId });\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml, {\n      prefix: \"ds\",\n      location: {\n        reference: \"//Assertion\",\n        action: \"after\",\n      },\n      existingPrefixes: {\n        wsse: \"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\",\n        wsu: \"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\",\n      },\n    });\n    const result = sig.getSignedXml();\n    expect((result.match(/xmlns:wsu=/g) || []).length).to.equal(1);\n    expect((result.match(/xmlns:wsse=/g) || []).length).to.equal(1);\n    expect(result.includes(assertionId)).to.be.true;\n  });\n\n  it(\"creates InclusiveNamespaces element when inclusiveNamespacesPrefixList is set on Reference\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml();\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='root']\",\n      transforms: [\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"],\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      uri: \"\",\n      digestValue: \"\",\n      inclusiveNamespacesPrefixList: [\"prefix1\", \"prefix2\"],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const inclusiveNamespaces = xpath.select(\n      \"//*[local-name(.)='Reference']/*[local-name(.)='Transforms']/*[local-name(.)='Transform']/*[local-name(.)='InclusiveNamespaces']\",\n      doc.documentElement,\n    );\n    isDomNode.assertIsArrayOfNodes(inclusiveNamespaces);\n    expect(inclusiveNamespaces.length, \"InclusiveNamespaces element should exist\").to.equal(1);\n\n    const firstNamespace = inclusiveNamespaces[0];\n    isDomNode.assertIsElementNode(firstNamespace);\n\n    const prefixListAttribute = firstNamespace.getAttribute(\"PrefixList\");\n    expect(\n      prefixListAttribute,\n      \"InclusiveNamespaces element should have the correct PrefixList attribute value\",\n    ).to.equal(\"prefix1 prefix2\");\n  });\n\n  it(\"does not create InclusiveNamespaces element when inclusiveNamespacesPrefixList is not set on Reference\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml();\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='root']\",\n      transforms: [\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"],\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      uri: \"\",\n      digestValue: \"\",\n      inclusiveNamespacesPrefixList: [],\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const inclusiveNamespaces = xpath.select1(\n      \"//*[local-name(.)='Reference']/*[local-name(.)='Transforms']/*[local-name(.)='Transform']/*[local-name(.)='InclusiveNamespaces']\",\n      doc.documentElement,\n    );\n\n    expect(inclusiveNamespaces, \"InclusiveNamespaces element should not exist\").to.be.undefined;\n  });\n\n  it(\"creates InclusiveNamespaces element inside CanonicalizationMethod when inclusiveNamespacesPrefixList is set on SignedXml options\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml({ inclusiveNamespacesPrefixList: \"prefix1 prefix2\" });\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='root']\",\n      transforms: [\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"],\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const inclusiveNamespaces = xpath.select(\n      \"//*[local-name(.)='CanonicalizationMethod']/*[local-name(.)='InclusiveNamespaces']\",\n      doc.documentElement,\n    );\n\n    isDomNode.assertIsArrayOfNodes(inclusiveNamespaces);\n\n    expect(\n      inclusiveNamespaces.length,\n      \"InclusiveNamespaces element should exist inside CanonicalizationMethod\",\n    ).to.equal(1);\n\n    const firstNamespace = inclusiveNamespaces[0];\n    isDomNode.assertIsElementNode(firstNamespace);\n\n    const prefixListAttribute = firstNamespace.getAttribute(\"PrefixList\");\n    expect(\n      prefixListAttribute,\n      \"InclusiveNamespaces element inside CanonicalizationMethod should have the correct PrefixList attribute value\",\n    ).to.equal(\"prefix1 prefix2\");\n  });\n\n  it(\"does not create InclusiveNamespaces element inside CanonicalizationMethod when inclusiveNamespacesPrefixList is not set on SignedXml options\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml(); // Omit inclusiveNamespacesPrefixList property\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='root']\",\n      transforms: [\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"],\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const inclusiveNamespaces = xpath.select1(\n      \"//*[local-name(.)='CanonicalizationMethod']/*[local-name(.)='InclusiveNamespaces']\",\n      doc.documentElement,\n    );\n\n    expect(\n      inclusiveNamespaces,\n      \"InclusiveNamespaces element should not exist inside CanonicalizationMethod\",\n    ).to.be.undefined;\n  });\n\n  it(\"adds attributes to KeyInfo element when attrs are present in keyInfoProvider\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml();\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n    sig.keyInfoAttributes = {\n      CustomUri: \"http://www.example.com/keyinfo\",\n      CustomAttribute: \"custom-value\",\n    };\n    sig.getKeyInfoContent = () => \"<dummy/>\";\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const keyInfoElements = xpath.select(\"//*[local-name(.)='KeyInfo']\", doc.documentElement);\n\n    isDomNode.assertIsArrayOfNodes(keyInfoElements);\n    expect(keyInfoElements.length, \"KeyInfo element should exist\").to.equal(1);\n    const keyInfoElement = keyInfoElements[0];\n\n    isDomNode.assertIsElementNode(keyInfoElement);\n    const algorithmAttribute = keyInfoElement.getAttribute(\"CustomUri\");\n    expect(\n      algorithmAttribute,\n      \"KeyInfo element should have the correct CustomUri attribute value\",\n    ).to.equal(\"http://www.example.com/keyinfo\");\n\n    const customAttribute = keyInfoElement.getAttribute(\"CustomAttribute\");\n    expect(\n      customAttribute,\n      \"KeyInfo element should have the correct CustomAttribute attribute value\",\n    ).to.equal(\"custom-value\");\n  });\n\n  it(\"adds all certificates and does not add private keys to KeyInfo element\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml();\n    const pemBuffer = fs.readFileSync(\"./test/static/client_bundle.pem\");\n    sig.privateKey = pemBuffer;\n    sig.publicCert = pemBuffer;\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n\n    const x509certificates = xpath.select(\n      \"//*[local-name(.)='X509Certificate']\",\n      doc.documentElement,\n    );\n    isDomNode.assertIsArrayOfNodes(x509certificates);\n    expect(x509certificates.length, \"There should be exactly two certificates\").to.equal(2);\n\n    const cert1 = x509certificates[0];\n    const cert2 = x509certificates[1];\n    expect(cert1.textContent, \"X509Certificate[0] TextContent does not exist\").to.exist;\n    expect(cert2.textContent, \"X509Certificate[1] TextContent does not exist\").to.exist;\n\n    const trimmedTextContent1 = cert1.textContent?.trim();\n    const trimmedTextContent2 = cert2.textContent?.trim();\n    expect(trimmedTextContent1, \"Empty certificate added [0]\").to.not.be.empty;\n    expect(trimmedTextContent2, \"Empty certificate added [1]\").to.not.be.empty;\n\n    expect(trimmedTextContent1?.substring(0, 5), \"Incorrect value for X509Certificate[0]\").to.equal(\n      \"MIIDC\",\n    );\n    expect(trimmedTextContent2?.substring(0, 5), \"Incorrect value for X509Certificate[1]\").to.equal(\n      \"MIIDZ\",\n    );\n  });\n\n  it(\"adds id and type attributes to Reference elements when provided\", function () {\n    const xml = \"<root><x /></root>\";\n    const sig = new SignedXml();\n    sig.privateKey = fs.readFileSync(\"./test/static/client.pem\");\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='x']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n      id: \"ref-1\",\n      type: \"http://www.w3.org/2000/09/xmldsig#Object\",\n    });\n\n    sig.canonicalizationAlgorithm = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n    sig.signatureAlgorithm = \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\";\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const referenceElements = xpath.select(\"//*[local-name(.)='Reference']\", doc);\n    isDomNode.assertIsArrayOfNodes(referenceElements);\n    expect(referenceElements.length, \"Reference element should exist\").to.equal(1);\n\n    const referenceElement = referenceElements[0];\n    isDomNode.assertIsElementNode(referenceElement);\n\n    const idAttribute = referenceElement.getAttribute(\"Id\");\n    expect(idAttribute, \"Reference element should have the correct Id attribute value\").to.equal(\n      \"ref-1\",\n    );\n\n    const typeAttribute = referenceElement.getAttribute(\"Type\");\n    expect(\n      typeAttribute,\n      \"Reference element should have the correct Type attribute value\",\n    ).to.equal(\"http://www.w3.org/2000/09/xmldsig#Object\");\n  });\n\n  it(\"should throw if xpath matches no nodes\", () => {\n    const sig = new SignedXml({\n      privateKey: fs.readFileSync(\"./test/static/client.pem\"),\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\",\n    });\n\n    sig.addReference({\n      xpath: \"//definitelyNotThere\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    expect(() => sig.computeSignature(\"<root></root>\")).to.throw(\n      /the following xpath cannot be signed because it was not found/,\n    );\n  });\n\n  it(\"should sign references when the Id attribute is prefixed\", () => {\n    const xml = '<root><x xmlns:ns=\"urn:example\" ns:Id=\"unique-id\"/></root>';\n    const sig = new SignedXml({\n      privateKey: fs.readFileSync(\"./test/static/client.pem\"),\n      canonicalizationAlgorithm: \"http://www.w3.org/2001/10/xml-exc-c14n#\",\n      signatureAlgorithm: \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n    });\n\n    sig.addReference({\n      xpath: \"//*[local-name(.)='x']\",\n      digestAlgorithm: \"http://www.w3.org/2000/09/xmldsig#sha1\",\n      transforms: [\"http://www.w3.org/2001/10/xml-exc-c14n#\"],\n    });\n\n    sig.computeSignature(xml);\n    const signedXml = sig.getSignedXml();\n\n    const doc = new xmldom.DOMParser().parseFromString(signedXml);\n    const referenceElements = xpath.select(\"//*[local-name(.)='Reference']\", doc);\n    isDomNode.assertIsArrayOfNodes(referenceElements);\n    expect(referenceElements.length, \"Reference element should exist\").to.equal(1);\n\n    const referenceElement = referenceElements[0];\n    isDomNode.assertIsElementNode(referenceElement);\n\n    const uriAttribute = referenceElement.getAttribute(\"URI\");\n    expect(uriAttribute, \"Reference element should have the correct URI attribute value\").to.equal(\n      \"#unique-id\",\n    );\n  });\n});\n"
  },
  {
    "path": "test/static/client.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL4vpoH3H3byehjj\n7RAGxefGRATiq4mXtzc9Q91W7uT0DTaFEbjzVch9aGsNjmLs4QHsoZbuoUmi0st4\nx5z9SQpTAKC/dW8muzacT3E7dJJYh03MAO6RiH4LG34VRTq1SQN6qDt2rCK85eG4\n5NHI4jceptZNu6Zot1zyO5/PYuFpAgMBAAECgYAhspeyF3M/xB7WIixy1oBiXMLY\nisESFAumgfhwU2LotkVRD6rgNl1QtMe3kCNWa9pCWQcYkxeI0IzA+JmFu2shVvoR\noL7eV4VCe1Af33z24E46+cY5grxNhHt/LyCnZKcitvCcrzXExUc5n6KngX0mMKgk\nW7skZDwsnKzhyUV8wQJBAN2bQMeASQVOqdfqBdFgC/NPnKY2cuDi6h659QN1l+kg\nX3ywdZ7KKftJo1G9l45SN9YpkyEd9zEO6PMFaufJvZUCQQDbtAWxk0i8BT3UTNWC\nT/9bUQROPcGZagwwnRFByX7gpmfkf1ImIvbWVXSpX68/IjbjSkTw1nj/Yj1NwFZ0\nnxeFAkEAzPhRpXVBlPgaXkvlz7AfvY+wW4hXHyyi0YK8XdPBi25XA5SPZiylQfjt\nZ6iN6qSfYqYXoPT/c0/QJR+orvVJNQJBANhRPNXljVTK2GDCseoXd/ZiI5ohxg+W\nUaA/1fDvQsRQM7TQA4NXI7BO/YmSk4rW1jIeOxjiIspY4MFAIh+7UL0CQFL6zTg6\nwfeMlEZzvgqwCGoLuvTnqtvyg45z7pfcrg2cHdgCXIy9kErcjwGiu6BOevEA1qTW\nRk+bv0tknWvcz/s=\n-----END PRIVATE KEY-----"
  },
  {
    "path": "test/static/client_bundle.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDCzCCAfMCFDdl3bSiEFLCBC3akD+sPuSbRKnyMA0GCSqGSIb3DQEBCwUAMEIx\nCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0Rl\nZmF1bHQgQ29tcGFueSBMdGQwHhcNMjMwNjE1MTAyNjMwWhcNMzMwNjEyMTAyNjMw\nWjBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQK\nDBNEZWZhdWx0IENvbXBhbnkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEArMLLZkjvJ/Kr3rfhR/77nJdjPumutJ7lJoDgQAwG2qBmse4oJmBDB6fY\nXFTrwVH4DKYnJFOaPBAqp+BGpFEjKo/zghEcGxidnuM5Hc6NAfnK3YEmbspc1DGX\ncLCfv0Mw3VV+XvDxfLpQdfTA4CM/lgPmO6lUF6er/WaLsLMfJc2+jLXYkIlj+x6b\nKVNHC7SG/HkD0WSZAAsfW1RCOQgsgVi/b+TEPR7MqcXzS3R1WWd8dB9EC8VwpU3o\nKBZ4EaYYvbEH+z2YW24jl+vxGHM9+UZaoYMzkBnDs+gtmpH35S/+YFbrro+qbRAs\nHy5FhhfQ0ZWbe9nAFUaID0CkemnQOwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBf\ngb5/f8Jv+zR5yD2VhaqZPgIc3lekCi1UxOrmSfnFZ1osSlgenf1dvJeCX9QEh2Lv\nFHmp0TflcJ12qHsWdfZSSantFhG5jMFxYD9uARyTHCWtRtdfO0P/KeuORleDN5lE\np7wBCy6JpE5INQxoHYnhO0ujfo9SvZVxpBHRpdSnHrkKn+6UOr6HVFQ4RVyEns7B\noZ/GQ7HWj4qpRF98MUmtwtCCemWPnNSjSAAWuJZ8e4JStjFcx8Vw3xIZbNGCZflw\nECjO3qQDUQmzySBub8FaDZkG1d2ODZsL221ETto4c5DXlesgYBVcPIkQAy53IVoP\nhupmcqhjnIejGHsgFAdF\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIDZTCCAk2gAwIBAgIUD2FdlpUMPuX6W1A0OiMKu6g0XuYwDQYJKoZIhvcNAQEL\nBQAwQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE\nCgwTRGVmYXVsdCBDb21wYW55IEx0ZDAeFw0yMzA2MTUxMDI2MDNaFw0zMzA2MTIx\nMDI2MDNaMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAa\nBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IB\nDwAwggEKAoIBAQD/emWytGY9zUAJ8Jq++GgTieFkmdgwPq8QcHzfIhqs0n5Y28cS\nCExFwoNZaJQiA1lobD2bgwAJPUb4j1zUmnaKeDuc2dq3RhcctJ2kbReqJVwzPW19\nDxWsvADYrjzE6UdgyWZfoanp7IBKjEj3xF13w0rYm1D3lrT7mE5roEA10oOVwErl\nHgRcCO8nbWMxy6HnZmMiTY815xdWXVKZpbjNJaVybEEnW128BFafAy24XmMg5PLx\nYGLEVExO2RHjEOibDb08/L91wJA8N8rSDoG8Akl1UesdH95VBcMvK4lA2e4Nn2Lu\nvFkqtsey6YrNw4OD1uAnQ0hinuo7OlVMYiRLAgMBAAGjUzBRMB0GA1UdDgQWBBTD\nb17H/nXO5ZUh74YhBn/X7zZuxTAfBgNVHSMEGDAWgBTDb17H/nXO5ZUh74YhBn/X\n7zZuxTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBsq1PBuJtg\nt+EFpbGngOmlMW4YaI77N8+H8Tk9+AIfvv+Awya+8T8ToMyEd7WZXuCabpzFwc5u\nTaZiHV0oyHNLLMt+QKrBZ9Ybu/RFJo0kjvbO2FEvtIiz9qqRqPUwD804HpXcyBvP\nlcQvJXRUSsaoTmcLtaA6TOWUbzxgHiXIDyiNVaM9B8hgKdqKCDqwtKYSAd9dpQVt\nYq2yEXxLKrJjZRrRF0d5CesA4rOoUiRK7VnZSIo8aO8BtLH7UjOrFg5WFial/1kh\nSEmjbsPp6oLNyDtg4eTWkS82polPsCWihm9gEu3+plBQNXH7X6xrPEsn5ZilscCc\n+lxT6hClXBXJ\n-----END CERTIFICATE-----\n-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCswstmSO8n8qve\nt+FH/vucl2M+6a60nuUmgOBADAbaoGax7igmYEMHp9hcVOvBUfgMpickU5o8ECqn\n4EakUSMqj/OCERwbGJ2e4zkdzo0B+crdgSZuylzUMZdwsJ+/QzDdVX5e8PF8ulB1\n9MDgIz+WA+Y7qVQXp6v9Zouwsx8lzb6MtdiQiWP7HpspU0cLtIb8eQPRZJkACx9b\nVEI5CCyBWL9v5MQ9HsypxfNLdHVZZ3x0H0QLxXClTegoFngRphi9sQf7PZhbbiOX\n6/EYcz35RlqhgzOQGcOz6C2akfflL/5gVuuuj6ptECwfLkWGF9DRlZt72cAVRogP\nQKR6adA7AgMBAAECggEAQVcvfNEq+u3yiTr8zrEm0vQDCmFxvUi3nJdzuWWTFg9C\nqBtOPi18TKHz2AAaZrSs34PcHAYuuHbY20OdFDrH1So6zD/SZIEr5FNGX/qmJFAo\npRxav95zu6HCCFIVKU6tZZkXQatZenYxRlu6s0tBmmiBJKGHd6boCuBFByDIMBB/\nP509g1TrRB70vAL8hqyd5wHJNhuwUvOOfLMfAMOXa5aAtwQlc0PXOUbUxwS3C4NW\nacqraGpFFWAOwg+J5eBi5jfXHDyiGhS5p8T8HkcoVyI5WrEQJES3fPlmA2IM8CXj\n4ipS329zJNM8SUJuluo1KIJeFMNN5cF1DZqtREb38QKBgQDywatu2mOIAoN+cpwf\nVtTDH1qsGYxuCka+7tipt+DxTxIJB/1KTQRwdWb1leqszO3nNS6Q/UIDFMV+oszG\n3UuoriOw+xuvYy/PrFdrDki3droipOEllSGmbXGk7rBalAbgswyF21ebgZi4moZr\nYjqdQl+R+XN1YjqnOn39njyeKQKBgQC2L5F90HBBhp+1qU1hbEGof5oMkp+Thjx/\nPWbJsqt6s41yIemug3MP8QLlUOMG5X+QTCN4RNTmf60V5McF2TSuT8jbT8jby0w+\nClnZ9lgGMSL7UjI26CHkw36xcDH2hzgXWGRxzttzlXttJqnbeATHC811yWaLDXGU\necC7bG9/wwKBgQChgq8fgtdjv2BjObebtja6V1sJU7o14EpvcBPg30Ee65+xOIqR\n66n/dGz7CjJno7TI9n4z4vwPdrtrZL9ftA5JfQqsDnW9+/zsa9qBlLBWt/xhXleZ\nnJ4Vz40j0datfP0SdK3pRSUFhnTopY63VVRwGp/hTBlASQmDB4yZt7TW+QKBgF73\neM2ug3WEqWfWcsGf3rHoofJ/07LgvFRPO29UNVLmmYqu5tLTLn1W0n2apl0H8HDV\nX3/n0Vq9nwnUkXIZAP8EE91OP5Ni68FDQAcABG5l2qhK9mXspw5KYZY4t7KcVb7F\nksZIX9hmSUpiZxRCAauIGXeWnl9JiLUuqiqIoa5lAoGAMS2HObavBhdTPkN998lq\nfnInmg5M466+PiPYZuQZh+Ea+8Gs0wv2wpFXw7Ds7hjo0hmiYGV/yw8etn45lpfA\nbuAIy50HQABwOWxH74AzddemsUSFEnRO4VgQ2Cu2dDaDGRjZbXcggRtOZ+ynuUJi\nG9/7qOuw5oPSq0v7tEDbqpI=\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/static/client_public.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIBxDCCAW6gAwIBAgIQxUSXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BAQQFADAW\nMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ3NTlaFw0zOTEyMzEy\nMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0Q2xpZW50MIGfMA0GCSqG\nSIb3DQEBAQUAA4GNADCBiQKBgQC+L6aB9x928noY4+0QBsXnxkQE4quJl7c3PUPd\nVu7k9A02hRG481XIfWhrDY5i7OEB7KGW7qFJotLLeMec/UkKUwCgv3VvJrs2nE9x\nO3SSWIdNzADukYh+Cxt+FUU6tUkDeqg7dqwivOXhuOTRyOI3HqbWTbumaLdc8juf\nz2LhaQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEU\nMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcN\nAQEEBQADQQAfIbnMPVYkNNfX1tG1F+qfLhHwJdfDUZuPyRPucWF5qkh6sSdWVBY5\nsT/txBnVJGziyO8DPYdu2fPMER8ajJfl\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/static/empty_uri.pem",
    "content": "-----BEGIN CERTIFICATE-----\r\nMIICcTCCAVmgAwIBAgIBATANBgkqhkiG9w0BAQQFADA+MQswCQYDVQQGEwJFUzEbMBkGA1UEChMS\r\nU2N5dGwgVU5JVCBURVNUIENBMRIwEAYDVQQLEwlVTklUIFRFU1QwHhcNMDYwMzAyMTEwOTEyWhcN\r\nMzAwNDA2MTEwOTEyWjA+MQswCQYDVQQGEwJFUzEbMBkGA1UEChMSU2N5dGwgVU5JVCBURVNUIENB\r\nMRIwEAYDVQQLEwlVTklUIFRFU1QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALfqpJyXfyna\r\nNPX70K0U4aof9xMg0I/M09WU+7l5or54uFWsrH+sx7/qDkSLwLfZ7WRNmQon/b+gglvoZkRZHYEa\r\nFaZg9kxK48pM6MMehX8n+QZFZ1QfPfoP2ajcsr14gXvEpqQa0SzjIn522nMqyXLKx38JQp7shil4\r\n9S38w3EfAgMBAAEwDQYJKoZIhvcNAQEEBQADggEBAJrtSsuqdB3RvGZMriETpO0pqQsBhZ+JRYqs\r\n5dFIiC+bdJE+dUB6v8fpv1exSQ0+i+e1oTs2I9Wd4eIQ4rlZCG9K6EYBKP9Z59OBDTf6luaisoul\r\n6gnKW7+kUfQQkBfJJw/4RA7FbaAmYNGEEfXTwDMU+ZoqIO/PV+JsfOtFUdPcwv1hPQHTE+KR1DtR\r\nAC+A4Ak+fOoaRnyTprvbT4inaPdn6D9fBrIpO6hQSAtM5K9+/VaskMSFqw03DkADRyxHacdz9JLp\r\n5ChDbRrXCDdT/a832acPDViS3nG/GhuSTK8mlrXeHjpG6vaSbKiXNXwrwz80k/XoNh3k5jlfrzUM\r\nCQ4=\r\n-----END CERTIFICATE-----"
  },
  {
    "path": "test/static/feide_public.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMC\nTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UE\nCxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0B\nCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoX\nDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhl\naW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBv\ncGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdA\ndW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlx\nAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4Hln\nO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZ\njcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQ\nYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1j\nwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3K\njjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/static/hmac-foobar.key",
    "content": "F\u001bG}P\\\u000e+=(9(\u000fz\n)e\u0015\u001e \u001b,\u001bz68\u0014\u0016\u001dã"
  },
  {
    "path": "test/static/hmac.key",
    "content": "R -\u000f\u0016B%P)\fAkl`97<YzC\bY^qq_\"q\b؎1C\u001bo\u001e "
  },
  {
    "path": "test/static/hmac_signature.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><test:Root xmlns:test=\"urn:test\"><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#hmac-sha1\"/><ds:Reference URI=\"\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\"/><ds:DigestValue>8ZvjCBK4twpNullktn5R4thOSezHWxuouNf6siHYJ1E=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>EEX7i+HCAfEELjwwKP1vKyPrW10=</ds:SignatureValue><ds:KeyInfo><ds:KeyName>some-key-name</ds:KeyName></ds:KeyInfo></ds:Signature></test:Root>"
  },
  {
    "path": "test/static/id_with_quotes.xml",
    "content": "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"pfx94e4a319-b6f7-4a40-25d1-01fcb642e4c5\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\" Destination=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status>\r\n<saml:Assertion xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" ID=\"pfx66496e6c-3c29-230d-6d47-b245434b872d\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\r\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\r\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\r\n  <ds:Reference URI=\"t't\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>RnNjoyUguwze5w2R+cboyTHlkQk=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>aw5711jKP7xragunjRRCAD4mT4xKHc37iohBpQDbdSomD3ksOSB96UZQp0MtaC3xlVSkMtYw85Om96T2q2xrxLLYVA50eFJEMMF7SCVPStWTVjBlaCuOPEQxIaHyJs9Sy3MCEfbBh4Pqn9IJBd1kzwdlCrWWjAmksbFFg5wHQJA=</ds:SignatureValue>\r\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>\r\nsome text\r\n</saml:Assertion>\r\n</samlp:Response>\r\n"
  },
  {
    "path": "test/static/idp_certificate.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIFFzCCAv+gAwIBAgIUaAU88KUbZLe7NwTw+jdCHIDU6wIwDQYJKoZIhvcNAQEL\nBQAwGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUuY29tMCAXDTI1MDkwODExMTUzMFoY\nDzIxMjUwODE1MTExNTMwWjAaMRgwFgYDVQQDDA9pZHAuZXhhbXBsZS5jb20wggIi\nMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXpgSoph176VQPw+4e91UAL6j0\nTbL/aI3Amj62TU91KOk4xigy+8xFSeU2IC64W7abfFq+25K+1ybJmMBq94UKyKab\n7yeXmen2xJ9PT5br4TwnsbeBZrziXSR8uTE60DdWLZYJEBREgu96JeEWLzP/0Hfn\nFlnuG5kXlb6rpy7l723YeDvU9lvsm6Rj46m5R8j4CSenKmLsHSIhmNP59SsEpJ16\nD+RfKcrKqxPxp6t/oCEKXjpmOeGoX9WT5V9UMxrGFgY2YLab9tLCIK48i6rgXpHU\nnbMq2XyAT58bSG/Tif99hoiQ2ovzsVUrVeCa4/uUg/pr+w1bZnIBl6R8WVPTVwgm\nYN+8Ww27aLiNksCn70t74XZLr9xnYnbnj324AiZp9Z48vDECm41Tc+V9eqGNO/5Y\nLgZqoGTy4El3AMcNF3lkecZ2UZKMI341pI1vHyRG0jCr2ZYpy30pYQKd+Z7AvZKM\nUTJFQfBIOn3zXN6SA8lWZLPOW4VTdOfcGjQij3AUDeTeilUigpRgkTl97WUrGfas\nvLXMrdRoXYxjGPe+s4+tf+gnKhTVQ6h6we+ISaFVOeXpCrOUwZM0OdikQtKYgH0G\n9OrJKxDZDl4YkkYFqqhyw5Eum9HZwMU8631lkBSqMRgz8AX7KdBn1PrGS6wOp+GC\n28L1ISeRxRriWtaeXQIDAQABo1MwUTAdBgNVHQ4EFgQULRbUCREu3zQABqNW8LMO\nfraF5BMwHwYDVR0jBBgwFoAULRbUCREu3zQABqNW8LMOfraF5BMwDwYDVR0TAQH/\nBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAA6Jm3pll7XHBY/oXrtRAu60RpH4p\ncZBSf68zhCQKUnXALy2FWrUGU8uVCJJuxXIcxszTOCZmwVF12YceIFpBrWHxKCDZ\nWYDO6hrwZvsa2vh5mXDZo3c/HX6GmJR4f4oIIZnbxFhXR30419PlrwMW3Rk7rnVS\nDz/HpQfdS4y8jYgsm2dIRo+PXQytFRCDj4afsT3eZa27QjFxLTuK+SwkhupSH1WW\nYmqL9+iIJiLL/ntfM4MwtOUwcfqI0ttbvFZZIPneBCuEDLn/zJ/QBV3ZvjQDt53W\n21HaPGPHBBfVZVroZPvuGvulWRLeECI1Hmbl3al/2aOC0LWzPIk8dlTcN+EWcCEu\nfpTOEgkob8waEyxlX0Z5OBjkCHpyDTPGkxBBOCJv88Frx7qdbu8eSV0OviuaM/B7\nky2NbDMKIybX4tf/Q8FNfjPLvTv+8nbrMz6kTno3RR2YC7ttI7Glb/eOg3F/ouF4\nwcoPAj+OyU5Q5WJMMaZ9cXF9pwszsglLbFms+WD5PFxlloh6I1hO7TccWKTeUJ5f\nYZSYYm31JqWit3DBltXTyRyL7KFSdT/FyRBk62YLCJqJmcukIUJUTya73/RmjW1M\n4zMBNaIj/pH77opKWnVbm9F4XnBCG4r9+FRXdV2zKW6DgvDzQ6DaZ+0cwC36vSqk\nDyjZYv/tviuWfM8=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/static/idp_private_key.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDXpgSoph176VQP\nw+4e91UAL6j0TbL/aI3Amj62TU91KOk4xigy+8xFSeU2IC64W7abfFq+25K+1ybJ\nmMBq94UKyKab7yeXmen2xJ9PT5br4TwnsbeBZrziXSR8uTE60DdWLZYJEBREgu96\nJeEWLzP/0HfnFlnuG5kXlb6rpy7l723YeDvU9lvsm6Rj46m5R8j4CSenKmLsHSIh\nmNP59SsEpJ16D+RfKcrKqxPxp6t/oCEKXjpmOeGoX9WT5V9UMxrGFgY2YLab9tLC\nIK48i6rgXpHUnbMq2XyAT58bSG/Tif99hoiQ2ovzsVUrVeCa4/uUg/pr+w1bZnIB\nl6R8WVPTVwgmYN+8Ww27aLiNksCn70t74XZLr9xnYnbnj324AiZp9Z48vDECm41T\nc+V9eqGNO/5YLgZqoGTy4El3AMcNF3lkecZ2UZKMI341pI1vHyRG0jCr2ZYpy30p\nYQKd+Z7AvZKMUTJFQfBIOn3zXN6SA8lWZLPOW4VTdOfcGjQij3AUDeTeilUigpRg\nkTl97WUrGfasvLXMrdRoXYxjGPe+s4+tf+gnKhTVQ6h6we+ISaFVOeXpCrOUwZM0\nOdikQtKYgH0G9OrJKxDZDl4YkkYFqqhyw5Eum9HZwMU8631lkBSqMRgz8AX7KdBn\n1PrGS6wOp+GC28L1ISeRxRriWtaeXQIDAQABAoICAGhLJwKngCfu4xRS1mWMicPy\nyNwKffDPUIsfLgg94JlRhWXLVCLAK30xLVUdgGryFCEjpcGbcN+yL1SddyXkeqgJ\n/aX5pmTH7+LEGiYh4GRJBK5P4WeIV/6EPILDj/8ZN0IK/v54E81Eo+wnyLHRd20X\nlf2hjjG9kC9bYSEkVGapAq+ICqvG0BNg/MLAltOAV745sz9CHSCDQIAOKSrAuyLe\nODkR2Yl6rVSSI62iQSuStpgMlWLeSHgFjUYfTxjqNF8rxKpk4LwSRcDUTGAEzkoA\nArhY4o9tKqzllRX9VPPyUCmVuJOR1tCvaXjxahSPARvFLoYtnzqek7GYdNkc3JA8\nyMOnXAVfuJ6xML9gFQvCJ9qFL5ayVBi+2OSXpKX0O2AwIOqFilT8/QSoR6bJXMwJ\nR4VRtsUbvQ84wG7cRSmGpMWs+PrGOgO2JmjCeLPrSZXNUIYchxGun+nG1OlBMjTc\nGdEzUdC0BLwOuGpvTKtCMDvwXStogq1PtjCHvEfjX84jtlV3mvJFHnqIJBGkLQPX\nO9P2SVL3g8vNwuAKvfMtSgW2sUXf+nFBtiAFXqXdYy0vL3O4AAoWU8Jfl5EUbO1S\nbAGJcF5N9vsSFGDfcZzuAbbSdj6qUlIkncTBlVO/tWsdFIg9BXbH/qQZEaprX//P\n5Z5wv+qBL353z7nCkb8zAoIBAQDrBQ8R49u/Pxupvr5pcFfZ14ifmIZnUar1bkig\no/ylb6Si3WgQ5PP788snYp2R3kbo+JBrdyl/OQBWgtCKOXxFllrBjwlihDXnK+SB\nigqHCkKbjTMjI+Gkgot7sR+tC9UnM0SNHlX6fkWfbmj6dQIIv0Cd3yOzx/v+ml2w\nTUwxCfmroiX67y3Sl0yVAGmXfjQ1uRCLBiulJEfONAu6+it0H8Whtx5d9FglF2Hj\nll+cOamAB+GZiJzAF6MucizS+Cfw+kWkrlOpFj2EqE7Z847Bhp1b6TSPCVZ+IUpY\n1FTYIBw1JFe7xeRKsfHs0KgrpSf3AxuSalFfpLeV997+sd/3AoIBAQDq5kPnZZTT\nV/i+DCa3Q94gNNQC+6j1YE/PDaQeOS7ybYz6pFizrIn6ioIfKD1as8vViTnvw9kq\nCehnO+rOzPA4oloVFDNKqliLViJMz7CY8hRoiOUuLzGbsmTyqvjcSi39IOmWs7Pq\nYFE0vDftEimMCxLNuTP/JpSa1ZY9std0Ljkk9zBTAykkXrrmjUxvd938DMSOqAv/\nPnib/Oq5cumROMXpPaRMjvhc56iyfEyluTntpJREN9KHvtll8TrGmDk/WW8sF87t\njmr0hNSa4dFOTkUS+EODL6BPKg+MwGN6UL7L811qztErKtFCK77JGr+dq66fU1bV\ny9JHSPYvJ8dLAoIBAQCnSUWNzWwoeEo/jCdLNA1EYXe9ajsZJfeTlXma5r86HvrI\nduLRS7cju0f68+YG43oD8JIT/JEMHs3PxnOcQAjmG3zkU+UxO7yGnSac0l5l+vao\ndFxXAf5mNAoG9HAAo/CIY6TC8jnvAJycPGH7DPhys3fSJ/foy0vi0Ywopwy5x0jx\nU4zHTiKGyO1ZDh8bF1kgeGd/HdhJR0bZTxCeed4eXVM2pfq2k+t+E2O5NNs/f4fY\nO0PpHmW9EdY0hE7FqJ/9lpel/fRM4ijN2WOvHf+aXzB5MMkZm2L2ism56wGtiUWq\nygCtBtJWHM2AbJGX54pH9+1TTdw4QS3wUKxpDMHHAoIBAAcs9ZISBlPWciDMGjqq\n9hQhyQA2U9j7EjUPA55wvMBnHFFjx9nlQWnH5WWyQv2MVIO3Z2+tmeqw1sqgh/G9\nTPFN9FaEgXScc4v+G5ohFhH2Ay2WUPnyMx/AeVj4ZBXGplT/NmOGJc7ZFmH4BfVW\nArLme7KRH8eBlDSOpcJIvlAsQU6hxnYiuJUF18vHMTiOftd+RFrfQ06Ox/xr43e6\nzOvEwjb3zRcRnwCniv240laVq/FYf7b9xY6kA9wbXGJIsCcBQmYkbAvRt+60SBJb\nJ5uuxGlp8BYH1GvWqxbvoZpQ8SMl0gq7OqSI8E+HKpLWIFhesDzpvNNXIJtQ3URf\ngLUCggEAa0SzoEaLut65B1mQuYaYXCvyXohRJn49BoHULUub/Zg2D+mPMJcyefBK\no/FUZD8ewXUiEoj6eoEXHTT8eOSvhXQHp2dc6AW6rADzL4Ni0oSQ8LwT5fgGq7B7\nyxWXkSkK3T43RLvrb7FSV21WTcsXYH560LHa5me1S4Pb1Zrz8+KCRNdNcoffZMfi\nb09pdLkS7Sbiskg69NrOFmwfD8SdAb9opPLY5lLWEVtkaPwQS4MrboJJlDutV9VC\n/Ye8QbuMwKQHduhAGGsCpkEwZhO5T4owdebVeY28t80HsInv7mFuiqZbIN/BMnU7\nzvi/SKHNm+elLUD1r7tC3+KVTtqSSw==\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/static/integration/expectedVerify.xml",
    "content": "<root><x xmlns=\"ns\" Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>K4dI497ZCxzweDIrbndUSmtoezY=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>sH1gxKve8wlU8LlFVa2l6w3HMJ0=</DigestValue></Reference></SignedInfo><SignatureValue>PI2xGt3XrVcxYZ34Kw7nFdq75c7Mmo7J0q7yeDhBprHuJal/KV9KyKG+Zy3bmQIxNwkPh0KMP5r1YMTKlyifwbWK0JitRCSa0Fa6z6+TgJi193yiR5S1MQ+esoQT0RzyIOBl9/GuJmXx/1rXnqrTxmL7UxtqKuM29/eHwF0QDUI=</SignatureValue></Signature></root>"
  },
  {
    "path": "test/static/integration/expectedVerifyComplex.xml",
    "content": "<library><book Id=\"_0\"><name>Harry Potter</name><author id=\"123456789\"><firstName>Joanne K</firstName><lastName>Rowling</lastName></author></book><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>VXkWV6BNrUKqdmwcxhIgRa86HUI=</DigestValue></Reference></SignedInfo><SignatureValue>Y71mpTZ0Ba5qED2TxHLp34tq8Pa9X41M5PuABwPq7r2GaL5Ib28ELkhMtnZuZboO50bxh/9fwK6DPApP92zUuOTZi4htlPcGJRP5kvHznbwzvq7aO5FWAcpUTX+yMrlERIutiJi7mjChX+mIKF5/4DK66JfIlY5vlq61TX2gaJw=</SignatureValue></Signature></library>"
  },
  {
    "path": "test/static/invalid_saml_no_signed_info.xml",
    "content": "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"pfx94e4a319-b6f7-4a40-25d1-01fcb642e4c5\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\" Destination=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n  <ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\n  <ds:SignatureValue>dkONrkxW+LSuDvnNMG/mWYFa47d2WGyapLhXSTYqrlT9Td+tT7ciojNJ55WTaPaCMt7IrGtIxxskPAZIjdIn5pRyDxHr0joWxzZ7oZHCOI1CnQV5HjOq+rzzmEN2LctCZ6S4hbL7SQ1qJ3vp2BCXAygy4tmJOURQdnk0KLwwRS8=</ds:SignatureValue>\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><saml:Assertion xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" ID=\"pfx66496e6c-3c29-230d-6d47-b245434b872d\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\n  <ds:Reference URI=\"#pfx66496e6c-3c29-230d-6d47-b245434b872d\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>RnNjoyUguwze5w2R+cboyTHlkQk=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>aw5711jKP7xragunjRRCAD4mT4xKHc37iohBpQDbdSomD3ksOSB96UZQp0MtaC3xlVSkMtYw85Om96T2q2xrxLLYVA50eFJEMMF7SCVPStWTVjBlaCuOPEQxIaHyJs9Sy3MCEfbBh4Pqn9IJBd1kzwdlCrWWjAmksbFFg5wHQJA=</ds:SignatureValue>\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID SPNameQualifier=\"passport-saml\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">_6c5dcaa3053321ff4d63785fbc3f67c59a129cde82</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2012-07-03T11:37:20Z\" Recipient=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2012-07-03T11:31:50Z\" NotOnOrAfter=\"2012-07-03T11:37:20Z\"><saml:AudienceRestriction><saml:Audience>passport-saml</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2012-07-03T11:32:20Z\" SessionNotOnOrAfter=\"2012-07-03T19:32:20Z\" SessionIndex=\"_c8e6823fe38ddbce125f9be6e5118b8c352d04bcae\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"uid\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"givenName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"sn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"cn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"mail\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonPrincipalName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonTargetedID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.1\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.42\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.4\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.6\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.10\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>"
  },
  {
    "path": "test/static/invalid_saml_sha256_rsa_mgf1.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Destination=\"https://acs.example.com/\" ID=\"_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\" InResponseTo=\"inResponseTo\" IssueInstant=\"2000-01-01T01:00:00Z\" Version=\"2.0\"><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n<ds:SignedInfo>\n<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n<ds:SignatureMethod Algorithm=\"http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1\"/>\n<ds:Reference URI=\"\">\n<ds:Transforms>\n<ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/>\n<ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n</ds:Transforms>\n<ds:DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\"/>\n<ds:DigestValue>bA/90zzLS/36DstvPJRrMNwGax5WQv8NneSuNdLnMYs=</ds:DigestValue>\n</ds:Reference>\n</ds:SignedInfo>\n<ds:SignatureValue>\n0fK5rJEtj0+JIL3hAuDsEAuKYoiwHzZTgQgspLyEe+XQan1FzT+qu3GBJSpSDfArBHjHXtizVfi8\nirId6a1kOj6ShEw2ZSGYD8Dh2d0HmrHqlOqpZ5eLiWeFA6VTtW1Cqmvr+x4Ndxcg0wWmmGr4hpSD\nYg8fkA8e32Fd2QxqLsQqVlCcuvJVCJ/12XSGcMW+Tse254fN6JENLLUdilu+14NNQKAHpKpjeajg\njG3fn0VNvyVQXKi2deYTWYaLRujBgv3Ncz8t9Hjthk+XxrRVHJiGc6HyVvqdpi5ChM41fjB1+eBo\nNkZ0Q73ZSCbTAqVduUWqL5pQzINq16kUm2ovkg7h3JoqSQr5yhoBJXZEf6FEyYdCCLd3rlIrkcvD\n+wfF2CwNRc6utgO/05JAA7Z1x2e0K6o2a6EQy93dkUIBhpxPYU/IdmGb15AfKJ3OrB1K/jTrxZ2q\nog/u0fJe0vU1sL4EDOXqVMj/unTZqDP/K1mOHK/eDWafs/IwMv65ebZUwTk74AMk/oOYV9mL8beY\nJAVYMN+xPA1cXnHlRgwATWLXjfiQcMXo44nhaw0YlOUGIoRLYURqHmXz0W3d8pXYdybLmdClkqLR\nvo1ryK1OC2paYG9qwk51QJ5wzMv6HRB5tDIL9/7mP7khlKgm4p+EZXFGYmvYDbk2x219SvxPmfY=\n</ds:SignatureValue>\n<ds:KeyInfo>\n<ds:KeyValue>\n<ds:RSAKeyValue>\n<ds:Modulus>\n16YEqKYde+lUD8PuHvdVAC+o9E2y/2iNwJo+tk1PdSjpOMYoMvvMRUnlNiAuuFu2m3xavtuSvtcm\nyZjAaveFCsimm+8nl5np9sSfT0+W6+E8J7G3gWa84l0kfLkxOtA3Vi2WCRAURILveiXhFi8z/9B3\n5xZZ7huZF5W+q6cu5e9t2Hg71PZb7JukY+OpuUfI+Aknpypi7B0iIZjT+fUrBKSdeg/kXynKyqsT\n8aerf6AhCl46ZjnhqF/Vk+VfVDMaxhYGNmC2m/bSwiCuPIuq4F6R1J2zKtl8gE+fG0hv04n/fYaI\nkNqL87FVK1XgmuP7lIP6a/sNW2ZyAZekfFlT01cIJmDfvFsNu2i4jZLAp+9Le+F2S6/cZ2J25499\nuAImafWePLwxApuNU3PlfXqhjTv+WC4GaqBk8uBJdwDHDRd5ZHnGdlGSjCN+NaSNbx8kRtIwq9mW\nKct9KWECnfmewL2SjFEyRUHwSDp981zekgPJVmSzzluFU3Tn3Bo0Io9wFA3k3opVIoKUYJE5fe1l\nKxn2rLy1zK3UaF2MYxj3vrOPrX/oJyoU1UOoesHviEmhVTnl6QqzlMGTNDnYpELSmIB9BvTqySsQ\n2Q5eGJJGBaqocsORLpvR2cDFPOt9ZZAUqjEYM/AF+ynQZ9T6xkusDqfhgtvC9SEnkcUa4lrWnl0=\n</ds:Modulus>\n<ds:Exponent>AQAB</ds:Exponent>\n</ds:RSAKeyValue>\n</ds:KeyValue>\n<ds:X509Data>\n<ds:X509Certificate>\nMIIFFzCCAv+gAwIBAgIUaAU88KUbZLe7NwTw+jdCHIDU6wIwDQYJKoZIhvcNAQELBQAwGjEYMBYG\nA1UEAwwPaWRwLmV4YW1wbGUuY29tMCAXDTI1MDkwODExMTUzMFoYDzIxMjUwODE1MTExNTMwWjAa\nMRgwFgYDVQQDDA9pZHAuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\nAQDXpgSoph176VQPw+4e91UAL6j0TbL/aI3Amj62TU91KOk4xigy+8xFSeU2IC64W7abfFq+25K+\n1ybJmMBq94UKyKab7yeXmen2xJ9PT5br4TwnsbeBZrziXSR8uTE60DdWLZYJEBREgu96JeEWLzP/\n0HfnFlnuG5kXlb6rpy7l723YeDvU9lvsm6Rj46m5R8j4CSenKmLsHSIhmNP59SsEpJ16D+RfKcrK\nqxPxp6t/oCEKXjpmOeGoX9WT5V9UMxrGFgY2YLab9tLCIK48i6rgXpHUnbMq2XyAT58bSG/Tif99\nhoiQ2ovzsVUrVeCa4/uUg/pr+w1bZnIBl6R8WVPTVwgmYN+8Ww27aLiNksCn70t74XZLr9xnYnbn\nj324AiZp9Z48vDECm41Tc+V9eqGNO/5YLgZqoGTy4El3AMcNF3lkecZ2UZKMI341pI1vHyRG0jCr\n2ZYpy30pYQKd+Z7AvZKMUTJFQfBIOn3zXN6SA8lWZLPOW4VTdOfcGjQij3AUDeTeilUigpRgkTl9\n7WUrGfasvLXMrdRoXYxjGPe+s4+tf+gnKhTVQ6h6we+ISaFVOeXpCrOUwZM0OdikQtKYgH0G9OrJ\nKxDZDl4YkkYFqqhyw5Eum9HZwMU8631lkBSqMRgz8AX7KdBn1PrGS6wOp+GC28L1ISeRxRriWtae\nXQIDAQABo1MwUTAdBgNVHQ4EFgQULRbUCREu3zQABqNW8LMOfraF5BMwHwYDVR0jBBgwFoAULRbU\nCREu3zQABqNW8LMOfraF5BMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAA6Jm\n3pll7XHBY/oXrtRAu60RpH4pcZBSf68zhCQKUnXALy2FWrUGU8uVCJJuxXIcxszTOCZmwVF12Yce\nIFpBrWHxKCDZWYDO6hrwZvsa2vh5mXDZo3c/HX6GmJR4f4oIIZnbxFhXR30419PlrwMW3Rk7rnVS\nDz/HpQfdS4y8jYgsm2dIRo+PXQytFRCDj4afsT3eZa27QjFxLTuK+SwkhupSH1WWYmqL9+iIJiLL\n/ntfM4MwtOUwcfqI0ttbvFZZIPneBCuEDLn/zJ/QBV3ZvjQDt53W21HaPGPHBBfVZVroZPvuGvul\nWRLeECI1Hmbl3al/2aOC0LWzPIk8dlTcN+EWcCEufpTOEgkob8waEyxlX0Z5OBjkCHpyDTPGkxBB\nOCJv88Frx7qdbu8eSV0OviuaM/B7ky2NbDMKIybX4tf/Q8FNfjPLvTv+8nbrMz6kTno3RR2YC7tt\nI7Glb/eOg3F/ouF4wcoPAj+OyU5Q5WJMMaZ9cXF9pwszsglLbFms+WD5PFxlloh6I1hO7TccWKTe\nUJ5fYZSYYm31JqWit3DBltXTyRyL7KFSdT/FyRBk62YLCJqJmcukIUJUTya73/RmjW1M4zMBNaIj\n/pH77opKWnVbm9F4XnBCG4r9+FRXdV2zKW6DgvDzQ6DaZ+0cwC36vSqkDyjZYv/tviuWfM8=\n</ds:X509Certificate>\n</ds:X509Data>\n</ds:KeyInfo>\n</ds:Signature>\n    <saml:Issuer>https://idp.example.com/</saml:Issuer>\n    <samlp:Status>\n        <samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/>\n    </samlp:Status>\n    <saml:Assertion xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ID=\"_bbbbbbbbbbbbbbbbbbbbbbbb\" IssueInstant=\"2000-01-01T01:00:00Z\" Version=\"2.0\">\n        <saml:Issuer>https://idp.example.com/</saml:Issuer>\n        <saml:Subject>\n            <saml:NameID Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\" SPNameQualifier=\"audience\">modifiedFakeNameId</saml:NameID>\n            <saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\">\n                <saml:SubjectConfirmationData InResponseTo=\"inResponseTo\" NotOnOrAfter=\"3000-01-01T01:00:00Z\" Recipient=\"https://acs.example.com/\"/>\n            </saml:SubjectConfirmation>\n        </saml:Subject>\n        <saml:Conditions NotBefore=\"2000-01-01T01:00:00Z\" NotOnOrAfter=\"3000-01-01T01:00:00Z\">\n            <saml:AudienceRestriction>\n                <saml:Audience>audience</saml:Audience>\n            </saml:AudienceRestriction>\n        </saml:Conditions>\n        <saml:AuthnStatement AuthnInstant=\"2000-01-01T01:00:00Z\" SessionIndex=\"42\" SessionNotOnOrAfter=\"3000-01-01T01:00:00Z\">\n            <saml:AuthnContext>\n                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>\n            </saml:AuthnContext>\n        </saml:AuthnStatement>\n    </saml:Assertion>\n</samlp:Response>"
  },
  {
    "path": "test/static/invalid_signature - changed content.xml",
    "content": "<root><x xmlns=\"ns\" Id=\"_0\"/><y z_attr=\"foofoo\" a_attr1=\"foo\" Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>K4dI497ZCxzweDIrbndUSmtoezY=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>sH1gxKve8wlU8LlFVa2l6w3HMJ0=</DigestValue></Reference></SignedInfo><SignatureValue>PI2xGt3XrVcxYZ34Kw7nFdq75c7Mmo7J0q7yeDhBprHuJal/KV9KyKG+Zy3bmQIxNwkPh0KMP5r1YMTKlyifwbWK0JitRCSa0Fa6z6+TgJi193yiR5S1MQ+esoQT0RzyIOBl9/GuJmXx/1rXnqrTxmL7UxtqKuM29/eHwF0QDUI=</SignatureValue><KeyInfo><dummyKey>1234</dummyKey></KeyInfo></Signature></root>"
  },
  {
    "path": "test/static/invalid_signature - hash.xml",
    "content": "<root><x xmlns=\"ns\" Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CPupQ=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>K4dI497ZCxzweDIrbndUSmtoezY=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>sH1gxKve8wlU8LlFVa2l6w3HMJ0=</DigestValue></Reference></SignedInfo><SignatureValue>PI2xGt3XrVcxYZ34Kw7nFdq75c7Mmo7J0q7yeDhBprHuJal/KV9KyKG+Zy3bmQIxNwkPh0KMP5r1YMTKlyifwbWK0JitRCSa0Fa6z6+TgJi193yiR5S1MQ+esoQT0RzyIOBl9/GuJmXx/1rXnqrTxmL7UxtqKuM29/eHwF0QDUI=</SignatureValue></Signature></root>"
  },
  {
    "path": "test/static/invalid_signature - non existing reference.xml",
    "content": "<root><x xmlns=\"ns\" Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</DigestValue></Reference><Reference URI=\"#_non_existing\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>K4dI497ZCxzweDIrbndUSmtoezY=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>sH1gxKve8wlU8LlFVa2l6w3HMJ0=</DigestValue></Reference></SignedInfo><SignatureValue>PI2xGt3XrVcxYZ34Kw7nFdq75c7Mmo7J0q7yeDhBprHuJal/KV9KyKG+Zy3bmQIxNwkPh0KMP5r1YMTKlyifwbWK0JitRCSa0Fa6z6+TgJi193yiR5S1MQ+esoQT0RzyIOBl9/GuJmXx/1rXnqrTxmL7UxtqKuM29/eHwF0QDUI=</SignatureValue></Signature></root>"
  },
  {
    "path": "test/static/invalid_signature - signature value.xml",
    "content": "<root><x xmlns=\"ns\" Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>K4dI497ZCxzweDIrbndUSmtoezY=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>sH1gxKve8wlU8LlFVa2l6w3HMJ0=</DigestValue></Reference></SignedInfo><SignatureValue>PI2xGt3XrVcxYZ34Kw7nFdq75c7Mmo7J0q7yeDhBprHuJal/KV9KyKG+Zy3bmQIxNwkPh0KMP5r1YMTKlyifwbWK0JitRCSa0Fa6z6+TgJi193yiR5S1MQ+esoQT0RzyIOBl9/GuJmXx/1rXnqrTxmL7UxtqKuM29/eHwF0Q1UI=</SignatureValue></Signature></root>"
  },
  {
    "path": "test/static/invalid_signature - wsu - changed content.xml",
    "content": "<root><x xmlns=\"ns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"bar\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>5jkdJLKVpfEiAQ0k5bnvfCQJKks=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>97gNxHth/Gc2wH4FiTiWJJrLaHI=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>mXRUtj7KJU3kMPLD9R30CGEiWio=</DigestValue></Reference></SignedInfo><SignatureValue>CRK8LTGiMM5p++3usB6Nxjg5WrPfvq97bFzHwtt9Sijqf1BqqCHLnQLxzhtPR7j6g0TJaQt4bmF8neO7IwgloSWX/ZXUl9dz5Ax9IMfESBI0L8Ew2BE1osZp3Nlc0xSSIVFKMfo9gvqi317jBjr/VklqjHXjMfhtGv8GATpdwPQ=</SignatureValue></Signature></root>"
  },
  {
    "path": "test/static/invalid_signature - wsu - hash.xml",
    "content": "<root><x xmlns=\"ns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>kapR1Bn68VZxlpAEcUqcpOiL1LQ=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>Ih44YjG8IC7apTJSIkMLSjiU0H0=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>3jbv3y5YtUUG6EIQSVL5faQorFY=</DigestValue></Reference></SignedInfo><SignatureValue>tk7uiJCzpfI9TUGAuZuLELPqN7LdVIhljaJRKHdaBpbgu3XH5YiGQXbOOmGbX6ghr2mabbMgw2kXQJbUATzqdQn+wRbeMRqFaj4vBpEoTohiwdoIw67zGbSCXKoGSZ7FxJADe53gS955wZgdcGt+Ni7ec5EbXb0XtzM6gDF+eUo=</SignatureValue></Signature></root>"
  },
  {
    "path": "test/static/invalid_signature - wsu - invalid signature value.xml",
    "content": "<root><x xmlns=\"ns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>5jkdJLKVpfEiAQ0k5bnvfCQJKks=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>97gNxHth/Gc2wH4FiTiWJJrLaHI=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>mXRUtj7KJU3kMPLD9R30CGEiWio=</DigestValue></Reference></SignedInfo><SignatureValue>CRK8LTGiMM5p++3usB6Nxjg5WrPfvq97bFzHwtt9Sijqf1BqqCHLnQLxzhtPR7j6g0TJaQt4bmF8neO7IwgloSWX/ZXUl9dz5Ax9IMfESBI0L8Ew2BE1osZp3Nlc0xSSIVFKMfo9gvqi317jBkr/VklqjHXjMfhtGv8GATpdwPQ=</SignatureValue></Signature></root>"
  },
  {
    "path": "test/static/invalid_signature - wsu - non existing reference.xml",
    "content": "<root><x xmlns=\"ns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_non_existing\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>kapR1Bn6OVZxlpAEcUqcpOiL1LQ=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>Ih44YjG8IC7apTJSIkMLSjiU0H0=</DigestValue></Reference><Reference URI=\"#_non_existing\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>3jbv3y5YtUUG6EIQSVL5faQorFY=</DigestValue></Reference></SignedInfo><SignatureValue>tk7uiJCzpfI9TUGAuZuLELPqN7LdVIhljaJRKHdaBpbgu3XH5YiGQXbOOmGbX6ghr2mabbMgw2kXQJbUATzqdQn+wRbeMRqFaj4vBpEoTohiwdoIw67zGbSCXKoGSZ7FxJADe53gS955wZgdcGt+Ni7ec5EbXb0XtzM6gDF+eUo=</SignatureValue></Signature></root>"
  },
  {
    "path": "test/static/invalid_signature_without_transforms_element.xml",
    "content": "<?xml version=\"1.0\"?>\n<library><book ID=\"bookid\"><name>some tampered text</name></book><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#bookid\"><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>LsMoqo1d6Sqh8DKLp00MK0fSBDA=</DigestValue></Reference></SignedInfo><SignatureValue>OR1SYcyU18qELj+3DX/bW/r5DqueuyPAnNFEh3hNKFaj8ZKLB/mdsR9w8GDBCmZ2\nlsCTEvJqWC37oF8rm2eBSonNbdBnA+TM6Y22C8rffVzaoM3zpNoeWMH2LwFmpdKB\nUXOMWVExEaz/s4fOcyv1ajVuk42I3nl0xcD95+i7PjY=</SignatureValue></Signature></library>"
  },
  {
    "path": "test/static/keyinfo - pretty-printed.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Destination=\"https://evil-corp.madness.com/sso/callback\" ID=\"pfx16b904df-7571-d25a-8694-23a70b1b2181\" InResponseTo=\"_e8df3fe5f04237d25670\" IssueInstant=\"2015-08-31T08:54:06+00:00\" Version=\"2.0\">\n    <saml:Issuer>https://evil-corp.com</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\n  <ds:Reference URI=\"#pfx16b904df-7571-d25a-8694-23a70b1b2181\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>uAP/VBhhaK2+Bn1lYjHB5tSHTcE=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>Q2F/63pvENmI+eURRIRmVI1fNpW+CxDan6YmGo2G5il+XOx72sBHS+FspoWDyezYUfO/Wfi+tBupK&#xd;\n    /9eHOeg60uPUkQFwkdPmUsH2hJAPVCatQReSUJDhHCO6a2rrQixecPDBhzJjstCpibgvgNzevVVu&#xd;\n    9h3eMH/BNzdwO5EbnVTcb2JQj2F18MAh1LlVMBWWDaZmIQTk7npMY/NVEajM1fbwXyrPdNRU8poK&#xd;\n    bjVoM7IL9s0TesQIeyQ01QOQQQ3kHZWnoqlWE6VbbTqHwuidfkqaQLLvF9sDneqXKBa7y2YEJXVm4&#xd;\n    GMzNoL/JOdSuNnU3rF0ET8UDSleV953/lbUA==</ds:SignatureValue>\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRMwE&#xd;\n    QYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMT&#xd;\n    UwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBFMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1&#xd;\n    TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEF&#xd;\n    AAOCAQ8AMIIBCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynXK&#xd;\n    sL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJyvO00YKBt+hHy83&#xd;\n    iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ&#xd;\n    4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWN&#xd;\n    uLD8326Mi/FE9cCRvFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdD&#xd;\n    gQWBBSVGgvoW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzHF6&#xd;\n    FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV&#xd;\n    0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD&#xd;\n    ggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEXmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nN&#xd;\n    XDuzg1oNZrPz5pJL/eCXPl7FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/T&#xd;\n    Zerm7qvesSiTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpRv5p&#xd;\n    Jo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9BfXNmcMambiS0pXhL2&#xd;\n    QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>\n    <samlp:Status>\n        <samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/>\n    </samlp:Status>\n    <saml:Assertion ID=\"_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\" IssueInstant=\"2020-09-25T16:00:00+00:00\" Version=\"2.0\">\n        <saml:Issuer>https://evil-corp.com</saml:Issuer>\n        <saml:Subject>\n            <saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">vincent.vega@evil-corp.com\n            </saml:NameID>\n            <saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\">\n                <saml:SubjectConfirmationData InResponseTo=\"_e8df3fe5f04237d25670\" NotOnOrAfter=\"2020-09-25T17:00:00+00:00\" Recipient=\"https://evil-corp.madness.com/sso/callback\"/>\n            </saml:SubjectConfirmation>\n        </saml:Subject>\n        <saml:Conditions NotBefore=\"2020-09-25T16:00:00+00:00\" NotOnOrAfter=\"2020-09-25T17:00:00+00:00\"/>\n        <saml:AuthnStatement AuthnInstant=\"2020-09-25T16:00:00+00:00\" SessionIndex=\"_9e315bdf7b1b6732be33c377cf6f5c4f\">\n            <saml:AuthnContext>\n                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport\n                </saml:AuthnContextClassRef>\n            </saml:AuthnContext>\n        </saml:AuthnStatement>\n        <saml:AttributeStatement>\n            <saml:Attribute Name=\"evil-corp.egroupid\">\n                <saml:AttributeValue xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">\n                    vincent.vega@evil-corp.com\n                </saml:AttributeValue>\n            </saml:Attribute>\n            <saml:Attribute Name=\"evilcorp.givenname\">\n                <saml:AttributeValue xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">Vincent\n                </saml:AttributeValue>\n            </saml:Attribute>\n            <saml:Attribute Name=\"evilcorp.sn\">\n                <saml:AttributeValue xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">VEGA\n                </saml:AttributeValue>\n            </saml:Attribute>\n            <saml:Attribute Name=\"evilcorp.addr\">\n                <saml:AttributeValue xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">123 Main St.&#xd;\nSuite 11\n                </saml:AttributeValue>\n            </saml:Attribute>\n        </saml:AttributeStatement>\n    </saml:Assertion>\n</samlp:Response>\n"
  },
  {
    "path": "test/static/keyinfo.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX\naWRnaXRzIFB0eSBMdGQwHhcNMTUwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBF\nMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50\nZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynX\nKsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJy\nvO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+\nDHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEs\nlqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCRvFlvAiMS\naebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdDgQWBBSVGgvo\nW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzH\nF6FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV\nBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQF\nMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEX\nmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nNXDuzg1oNZrPz5pJL/eCXPl7\nFhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/TZerm7qvesS\niTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpR\nv5pJo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9Bf\nXNmcMambiS0pXhL2QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/static/saml_external_ns.pem",
    "content": "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAoXoc7IFZQRv+SwJ15zjIl9touwY5e6b7H4vn3OtOUByjOKHUX8VX\n0TpbAV2ctZE2GSALx1AGuQAv6O4MVUH+qn/2IAiBY3a7zKN07UBsya7xFMQVHuGE\n6EiBAs9jpA9wjvYMPRkS5wYZcwjpTQSZK7zFPPtobG8K/1vDbm/tWZjNLmZmQePm\nXpwrQAuC0+NlzlmnjoQYB2xp2NaTUK9JnnmuB5qev3dpUwlYGSJpf+HUIoxuo8Ip\nxAXOymq1d6tEEJgU1kR2sa7o1sSRFo31YeW/qYCP/gcLJZo3MRUDFe0g5MHeliFu\ne9DsKYUsC6qwAD3gc+MI47buiD6Msu11cwIDAQAB\n-----END RSA PUBLIC KEY-----\n"
  },
  {
    "path": "test/static/saml_external_ns.xml",
    "content": "<samlp:Response xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"GOSAMLR13708454654483\" Version=\"2.0\" IssueInstant=\"2013-06-10T06:24:25Z\" Destination=\"ForNodeJS\"><saml:Issuer>https://app.onelogin.com/saml/metadata/164679</saml:Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><saml:Assertion xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" Version=\"2.0\" ID=\"pfx4790de7a-ba67-cdfe-122c-e557ad3b3743\" IssueInstant=\"2013-06-10T06:24:25Z\"><saml:Issuer>https://app.onelogin.com/saml/metadata/164679</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><ds:Reference URI=\"#pfx4790de7a-ba67-cdfe-122c-e557ad3b3743\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>Gx0mTydMn1k6804jZBrdUrZmbV4=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>oHEPKtwoCbfq1QRm2pjx35zVMqAsti4nQU+3ws8EUJUXHmPG2EoX3HBkb7D2wN4m+ZFrdwARUpNJlhhOIz/eG4jES6ar0tvlNN3qE5cqcQhwZHyRARLnTlERqyZU9Qm729DnAGBeXCdMb736zi16onOIVPNA63LRTzUIxhyZqypDCf1wd6me/ur6UUgH11nYOu4JDYx0iWNkXc1Nad7vkF9oMPeO1QsMxuZSIVH4tvdJkue+qAnu2l+dFJb0LPfm+xmIC0FBo+VX1ECCWRoUZIxjotQfAM6yZpHIi5fNqPXkVyN9fYoUEa9CafqHlc4tAAdgAgGeOqA3jWeC8ZnOVA==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbTAeFw0xMzA1MjcwODU1MTNaFw0xODA1MjcwODU1MTNaMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9uZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoXoc7IFZQRv+SwJ15zjIl9touwY5e6b7H4vn3OtOUByjOKHUX8VX0TpbAV2ctZE2GSALx1AGuQAv6O4MVUH+qn/2IAiBY3a7zKN07UBsya7xFMQVHuGE6EiBAs9jpA9wjvYMPRkS5wYZcwjpTQSZK7zFPPtobG8K/1vDbm/tWZjNLmZmQePmXpwrQAuC0+NlzlmnjoQYB2xp2NaTUK9JnnmuB5qev3dpUwlYGSJpf+HUIoxuo8IpxAXOymq1d6tEEJgU1kR2sa7o1sSRFo31YeW/qYCP/gcLJZo3MRUDFe0g5MHeliFue9DsKYUsC6qwAD3gc+MI47buiD6Msu11cwIDAQABo4HUMIHRMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFAAJFJRIlpQQSFsuNdeq7FkTJIH4MIGRBgNVHSMEgYkwgYaAFAAJFJRIlpQQSFsuNdeq7FkTJIH4oWukaTBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbYIBATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADggEBAB9zN+g6N4sUBE61RaMUH2LSHWwOtfhL64i7pjHjvZa47/qcV/S0Yyd4IE44ho9i2N+AM79d34mThc30oK5aVxOKphKf+xM/cOyVaWIeqr+dCbkY/0OpLEwWOh9VSgOizRO3evLMurbtR892LbSK/Td3hG5jfwoHD23nHH87Dv/3KyZox9MkJdY2DXOHGGIcsqoIifaTyNZyhW6RgwEujQ6LjsaolP1YoeV85TZFKTLa1Ta7ZLUVUC2UJWqz+kRlsyGxf+E/ZmJ7hSq0ZBVHrVOyXjCcFn6X0/W5SrpOmN3fZYcj8Bp6vhB0cJk9qpjgWOP2RCuBdHZVawjCjIaE+bc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">kartik.cds@gmail.com</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2013-06-10T06:27:25Z\" Recipient=\"ForNodeJS\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2013-06-10T06:21:25Z\" NotOnOrAfter=\"2013-06-10T06:27:25Z\"><saml:AudienceRestriction><saml:Audience>ForNodeJS</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2013-06-10T06:24:24Z\" SessionNotOnOrAfter=\"2013-06-11T06:24:25Z\" SessionIndex=\"_5246a870-b3c4-0130-1bcd-782bcb56fcaa\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"PersonImmutableID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">kartik.cds@gmail.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.FirstName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">KartikCDS</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.Username\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"office\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.LastName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"memberOf\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>"
  },
  {
    "path": "test/static/saml_multiple_signed_info_nodes.xml",
    "content": "<?xml version=\"1.0\"?><samlp:Response xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"GOSAMLR13708454654483\" Version=\"2.0\" IssueInstant=\"2013-06-10T06:24:25Z\" Destination=\"ForNodeJS\"><saml:Issuer>https://app.onelogin.com/saml/metadata/164679</saml:Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><saml:Assertion xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" Version=\"2.0\" ID=\"OUR_CUSTOM_ID\" IssueInstant=\"2013-06-10T06:24:25Z\"><saml:Issuer>https://app.onelogin.com/saml/metadata/164679</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><ds:Reference URI=\"#pfx4790de7a-ba67-cdfe-122c-e557ad3b3743\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>Gx0mTydMn1k6804jZBrdUrZmbV4=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignedInfo><ds:Reference URI=\"#OUR_CUSTOM_ID\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>jGst6BnAC9xOeqa6hKNPsoMm2TY=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>oHEPKtwoCbfq1QRm2pjx35zVMqAsti4nQU+3ws8EUJUXHmPG2EoX3HBkb7D2wN4m+ZFrdwARUpNJlhhOIz/eG4jES6ar0tvlNN3qE5cqcQhwZHyRARLnTlERqyZU9Qm729DnAGBeXCdMb736zi16onOIVPNA63LRTzUIxhyZqypDCf1wd6me/ur6UUgH11nYOu4JDYx0iWNkXc1Nad7vkF9oMPeO1QsMxuZSIVH4tvdJkue+qAnu2l+dFJb0LPfm+xmIC0FBo+VX1ECCWRoUZIxjotQfAM6yZpHIi5fNqPXkVyN9fYoUEa9CafqHlc4tAAdgAgGeOqA3jWeC8ZnOVA==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbTAeFw0xMzA1MjcwODU1MTNaFw0xODA1MjcwODU1MTNaMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9uZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoXoc7IFZQRv+SwJ15zjIl9touwY5e6b7H4vn3OtOUByjOKHUX8VX0TpbAV2ctZE2GSALx1AGuQAv6O4MVUH+qn/2IAiBY3a7zKN07UBsya7xFMQVHuGE6EiBAs9jpA9wjvYMPRkS5wYZcwjpTQSZK7zFPPtobG8K/1vDbm/tWZjNLmZmQePmXpwrQAuC0+NlzlmnjoQYB2xp2NaTUK9JnnmuB5qev3dpUwlYGSJpf+HUIoxuo8IpxAXOymq1d6tEEJgU1kR2sa7o1sSRFo31YeW/qYCP/gcLJZo3MRUDFe0g5MHeliFue9DsKYUsC6qwAD3gc+MI47buiD6Msu11cwIDAQABo4HUMIHRMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFAAJFJRIlpQQSFsuNdeq7FkTJIH4MIGRBgNVHSMEgYkwgYaAFAAJFJRIlpQQSFsuNdeq7FkTJIH4oWukaTBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbYIBATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADggEBAB9zN+g6N4sUBE61RaMUH2LSHWwOtfhL64i7pjHjvZa47/qcV/S0Yyd4IE44ho9i2N+AM79d34mThc30oK5aVxOKphKf+xM/cOyVaWIeqr+dCbkY/0OpLEwWOh9VSgOizRO3evLMurbtR892LbSK/Td3hG5jfwoHD23nHH87Dv/3KyZox9MkJdY2DXOHGGIcsqoIifaTyNZyhW6RgwEujQ6LjsaolP1YoeV85TZFKTLa1Ta7ZLUVUC2UJWqz+kRlsyGxf+E/ZmJ7hSq0ZBVHrVOyXjCcFn6X0/W5SrpOmN3fZYcj8Bp6vhB0cJk9qpjgWOP2RCuBdHZVawjCjIaE+bc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">anyone@gmail.com</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2013-06-10T06:27:25Z\" Recipient=\"ForNodeJS\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2013-06-10T06:21:25Z\" NotOnOrAfter=\"2013-06-10T06:27:25Z\"><saml:AudienceRestriction><saml:Audience>ForNodeJS</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2013-06-10T06:24:24Z\" SessionNotOnOrAfter=\"2013-06-11T06:24:25Z\" SessionIndex=\"_5246a870-b3c4-0130-1bcd-782bcb56fcaa\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"PersonImmutableID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">kartik.cds@gmail.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.FirstName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">KartikCDS</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.Username\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"office\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.LastName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"memberOf\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute></saml:AttributeStatement></saml:Assertion><a><saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" Version=\"2.0\" ID=\"pfx4790de7a-ba67-cdfe-122c-e557ad3b3743\" IssueInstant=\"2013-06-10T06:24:25Z\"><saml:Issuer>https://app.onelogin.com/saml/metadata/164679</saml:Issuer><saml:Subject><saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">kartik.cds@gmail.com</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2013-06-10T06:27:25Z\" Recipient=\"ForNodeJS\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2013-06-10T06:21:25Z\" NotOnOrAfter=\"2013-06-10T06:27:25Z\"><saml:AudienceRestriction><saml:Audience>ForNodeJS</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2013-06-10T06:24:24Z\" SessionNotOnOrAfter=\"2013-06-11T06:24:25Z\" SessionIndex=\"_5246a870-b3c4-0130-1bcd-782bcb56fcaa\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"PersonImmutableID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">kartik.cds@gmail.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.FirstName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">KartikCDS</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.Username\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"office\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.LastName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"memberOf\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute></saml:AttributeStatement></saml:Assertion></a></samlp:Response>"
  },
  {
    "path": "test/static/saml_wrapped_signed_info_node.xml",
    "content": "<samlp:Response xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"GOSAMLR13708454654483\" Version=\"2.0\" IssueInstant=\"2013-06-10T06:24:25Z\" Destination=\"ForNodeJS\"><saml:Issuer>https://app.onelogin.com/saml/metadata/164679</saml:Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><saml:Assertion xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" Version=\"2.0\" ID=\"OUR_CUSTOM_ID\" IssueInstant=\"2013-06-10T06:24:25Z\"><saml:Issuer>https://app.onelogin.com/saml/metadata/164679</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><WRAPPER><ds:SignedInfo><ds:Reference URI=\"#OUR_CUSTOM_ID\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>jGst6BnAC9xOeqa6hKNPsoMm2TY=</ds:DigestValue></ds:Reference></ds:SignedInfo></WRAPPER><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><ds:Reference URI=\"#pfx4790de7a-ba67-cdfe-122c-e557ad3b3743\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>Gx0mTydMn1k6804jZBrdUrZmbV4=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>oHEPKtwoCbfq1QRm2pjx35zVMqAsti4nQU+3ws8EUJUXHmPG2EoX3HBkb7D2wN4m+ZFrdwARUpNJlhhOIz/eG4jES6ar0tvlNN3qE5cqcQhwZHyRARLnTlERqyZU9Qm729DnAGBeXCdMb736zi16onOIVPNA63LRTzUIxhyZqypDCf1wd6me/ur6UUgH11nYOu4JDYx0iWNkXc1Nad7vkF9oMPeO1QsMxuZSIVH4tvdJkue+qAnu2l+dFJb0LPfm+xmIC0FBo+VX1ECCWRoUZIxjotQfAM6yZpHIi5fNqPXkVyN9fYoUEa9CafqHlc4tAAdgAgGeOqA3jWeC8ZnOVA==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbTAeFw0xMzA1MjcwODU1MTNaFw0xODA1MjcwODU1MTNaMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9uZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoXoc7IFZQRv+SwJ15zjIl9touwY5e6b7H4vn3OtOUByjOKHUX8VX0TpbAV2ctZE2GSALx1AGuQAv6O4MVUH+qn/2IAiBY3a7zKN07UBsya7xFMQVHuGE6EiBAs9jpA9wjvYMPRkS5wYZcwjpTQSZK7zFPPtobG8K/1vDbm/tWZjNLmZmQePmXpwrQAuC0+NlzlmnjoQYB2xp2NaTUK9JnnmuB5qev3dpUwlYGSJpf+HUIoxuo8IpxAXOymq1d6tEEJgU1kR2sa7o1sSRFo31YeW/qYCP/gcLJZo3MRUDFe0g5MHeliFue9DsKYUsC6qwAD3gc+MI47buiD6Msu11cwIDAQABo4HUMIHRMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFAAJFJRIlpQQSFsuNdeq7FkTJIH4MIGRBgNVHSMEgYkwgYaAFAAJFJRIlpQQSFsuNdeq7FkTJIH4oWukaTBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbYIBATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADggEBAB9zN+g6N4sUBE61RaMUH2LSHWwOtfhL64i7pjHjvZa47/qcV/S0Yyd4IE44ho9i2N+AM79d34mThc30oK5aVxOKphKf+xM/cOyVaWIeqr+dCbkY/0OpLEwWOh9VSgOizRO3evLMurbtR892LbSK/Td3hG5jfwoHD23nHH87Dv/3KyZox9MkJdY2DXOHGGIcsqoIifaTyNZyhW6RgwEujQ6LjsaolP1YoeV85TZFKTLa1Ta7ZLUVUC2UJWqz+kRlsyGxf+E/ZmJ7hSq0ZBVHrVOyXjCcFn6X0/W5SrpOmN3fZYcj8Bp6vhB0cJk9qpjgWOP2RCuBdHZVawjCjIaE+bc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">anyone@gmail.com</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2013-06-10T06:27:25Z\" Recipient=\"ForNodeJS\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2013-06-10T06:21:25Z\" NotOnOrAfter=\"2013-06-10T06:27:25Z\"><saml:AudienceRestriction><saml:Audience>ForNodeJS</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2013-06-10T06:24:24Z\" SessionNotOnOrAfter=\"2013-06-11T06:24:25Z\" SessionIndex=\"_5246a870-b3c4-0130-1bcd-782bcb56fcaa\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"PersonImmutableID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">kartik.cds@gmail.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.FirstName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">KartikCDS</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.Username\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"office\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.LastName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"memberOf\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute></saml:AttributeStatement></saml:Assertion><a><saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" Version=\"2.0\" ID=\"pfx4790de7a-ba67-cdfe-122c-e557ad3b3743\" IssueInstant=\"2013-06-10T06:24:25Z\"><saml:Issuer>https://app.onelogin.com/saml/metadata/164679</saml:Issuer><saml:Subject><saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">kartik.cds@gmail.com</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2013-06-10T06:27:25Z\" Recipient=\"ForNodeJS\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2013-06-10T06:21:25Z\" NotOnOrAfter=\"2013-06-10T06:27:25Z\"><saml:AudienceRestriction><saml:Audience>ForNodeJS</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2013-06-10T06:24:24Z\" SessionNotOnOrAfter=\"2013-06-11T06:24:25Z\" SessionIndex=\"_5246a870-b3c4-0130-1bcd-782bcb56fcaa\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"PersonImmutableID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">kartik.cds@gmail.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.FirstName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">KartikCDS</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"User.Username\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"office\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"User.LastName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute><saml:Attribute Name=\"memberOf\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\"/></saml:Attribute></saml:AttributeStatement></saml:Assertion></a></samlp:Response>"
  },
  {
    "path": "test/static/signature_with_inclusivenamespaces.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIICnTCCAgagAwIBAgIGAUBGHxqUMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYDVQQGEwJVUzETMBEG\r\nA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU\r\nMBIGA1UECwwLU1NPUHJvdmlkZXIxEjAQBgNVBAMMCWtsdWdsYWJzMjEcMBoGCSqGSIb3DQEJARYN\r\naW5mb0Bva3RhLmNvbTAeFw0xMzA4MDMyMTM4MzhaFw00MzA4MDMyMTM5MzhaMIGRMQswCQYDVQQG\r\nEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UE\r\nCgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEjAQBgNVBAMMCWtsdWdsYWJzMjEcMBoGCSqG\r\nSIb3DQEJARYNaW5mb0Bva3RhLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsCB9lJTH\r\nqB7vdM5jeOH84cW8u7IHYv4/OAPYF0fBYe9wJy19CgyM2OgiASuAcItnH4WhB+io2ZPwb/Xwl7Uu\r\n4XmUE0l+mkCNuDYp5fXTZxwv5G6HvkAxXZio0Rk9T0VETCroxgpS5LxQ/o/owjR39S7xzRnj6ddX\r\n3Mq2yGjKyBcCAwEAATANBgkqhkiG9w0BAQUFAAOBgQAB1qGNqSNLLWq+RPcP+wOaWtYpJOJ8/MbZ\r\nEWWm9/KKHKXM6J/zgUUIXZi3czMeO+Y+X14PR8lGXoAHf5b/JavG9FmFvRn4fGa45VTVo2GfMN6K\r\naIKF0obeCbYi/QUf8B+Xi1tSIJm1VCKRE7nnliQ/TzGaNulgWeyTbVkG0/X8LQ==\r\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/static/signature_with_inclusivenamespaces.xml",
    "content": "<saml2:Assertion xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"id8132302868541019755414121\" IssueInstant=\"2013-08-03T21:54:43.942Z\" Version=\"2.0\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"><saml2:Issuer Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:entity\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://www.okta.com/k7xkhq0jUHUPQAXVMUAN</saml2:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><ds:Reference URI=\"#id8132302868541019755414121\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"xs\"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>4G+uveKmtiB1EkY5BAt+8lmQwjI=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>Q80N6FUr5/YPtEzRlRdMoPu+bL0MssDxNUY+yxykzbmxsI0joEo/SmmSgZrDYQKTllZk/KfzBMPFV9yBH4+mEzCU5E3xuCs99jZzafcw3K8mIMTJy1YHxjc359d27R5s50i9w5PHsusRov0MjQIoJ2w48Gy4EnYaViqBR3UVEqE=</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICnTCCAgagAwIBAgIGAUBGHxqUMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYDVQQGEwJVUzETMBEG\r\nA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU\r\nMBIGA1UECwwLU1NPUHJvdmlkZXIxEjAQBgNVBAMMCWtsdWdsYWJzMjEcMBoGCSqGSIb3DQEJARYN\r\naW5mb0Bva3RhLmNvbTAeFw0xMzA4MDMyMTM4MzhaFw00MzA4MDMyMTM5MzhaMIGRMQswCQYDVQQG\r\nEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UE\r\nCgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEjAQBgNVBAMMCWtsdWdsYWJzMjEcMBoGCSqG\r\nSIb3DQEJARYNaW5mb0Bva3RhLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsCB9lJTH\r\nqB7vdM5jeOH84cW8u7IHYv4/OAPYF0fBYe9wJy19CgyM2OgiASuAcItnH4WhB+io2ZPwb/Xwl7Uu\r\n4XmUE0l+mkCNuDYp5fXTZxwv5G6HvkAxXZio0Rk9T0VETCroxgpS5LxQ/o/owjR39S7xzRnj6ddX\r\n3Mq2yGjKyBcCAwEAATANBgkqhkiG9w0BAQUFAAOBgQAB1qGNqSNLLWq+RPcP+wOaWtYpJOJ8/MbZ\r\nEWWm9/KKHKXM6J/zgUUIXZi3czMeO+Y+X14PR8lGXoAHf5b/JavG9FmFvRn4fGa45VTVo2GfMN6K\r\naIKF0obeCbYi/QUf8B+Xi1tSIJm1VCKRE7nnliQ/TzGaNulgWeyTbVkG0/X8LQ==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml2:Subject xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">admin@kluglabs.com</saml2:NameID><saml2:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml2:SubjectConfirmationData NotOnOrAfter=\"2013-08-03T21:59:43.942Z\" Recipient=\"https://auth0145.auth0.com\"/></saml2:SubjectConfirmation></saml2:Subject><saml2:Conditions NotBefore=\"2013-08-03T21:49:43.943Z\" NotOnOrAfter=\"2013-08-03T21:59:43.942Z\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:AudienceRestriction><saml2:Audience>https://auth0145.auth0.com</saml2:Audience></saml2:AudienceRestriction></saml2:Conditions><saml2:AuthnStatement AuthnInstant=\"2013-08-03T21:54:43.942Z\" SessionIndex=\"id1375566883942.687610437\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:AuthnContext><saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef></saml2:AuthnContext></saml2:AuthnStatement><saml2:AttributeStatement xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:Attribute Name=\"Role\" NameFormat=\"ns\"><saml2:AttributeValue xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">Admin</saml2:AttributeValue></saml2:Attribute></saml2:AttributeStatement></saml2:Assertion>"
  },
  {
    "path": "test/static/signature_with_inclusivenamespaces_lines.xml",
    "content": "<saml2:Assertion xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"id8132302868541019755414121\" IssueInstant=\"2013-08-03T21:54:43.942Z\" Version=\"2.0\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"><saml2:Issuer Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:entity\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://www.okta.com/k7xkhq0jUHUPQAXVMUAN</saml2:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><ds:Reference URI=\"#id8132302868541019755414121\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"xs\"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>4G+uveKmtiB1EkY5BAt+8lmQwjI=</ds:DigestValue></ds:Reference></ds:SignedInfo>\r\n<ds:SignatureValue>\r\nQ80N6FUr5/YPtEzRlRdMoPu+bL0MssDxNUY+yxykzbmxsI0joEo/SmmSgZrDYQKTllZk/KfzBMPF\r\nV9yBH4+mEzCU5E3xuCs99jZzafcw3K8mIMTJy1YHxjc359d27R5s50i9w5PHsusRov0MjQIoJ2w4\r\n8Gy4EnYaViqBR3UVEqE=\r\n</ds:SignatureValue>\r\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>\r\nMIICnTCCAgagAwIBAgIGAUBGHxqUMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYDVQQGEwJVUzETMBEG\r\nA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU\r\nMBIGA1UECwwLU1NPUHJvdmlkZXIxEjAQBgNVBAMMCWtsdWdsYWJzMjEcMBoGCSqGSIb3DQEJARYN\r\naW5mb0Bva3RhLmNvbTAeFw0xMzA4MDMyMTM4MzhaFw00MzA4MDMyMTM5MzhaMIGRMQswCQYDVQQG\r\nEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UE\r\nCgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEjAQBgNVBAMMCWtsdWdsYWJzMjEcMBoGCSqG\r\nSIb3DQEJARYNaW5mb0Bva3RhLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsCB9lJTH\r\nqB7vdM5jeOH84cW8u7IHYv4/OAPYF0fBYe9wJy19CgyM2OgiASuAcItnH4WhB+io2ZPwb/Xwl7Uu\r\n4XmUE0l+mkCNuDYp5fXTZxwv5G6HvkAxXZio0Rk9T0VETCroxgpS5LxQ/o/owjR39S7xzRnj6ddX\r\n3Mq2yGjKyBcCAwEAATANBgkqhkiG9w0BAQUFAAOBgQAB1qGNqSNLLWq+RPcP+wOaWtYpJOJ8/MbZ\r\nEWWm9/KKHKXM6J/zgUUIXZi3czMeO+Y+X14PR8lGXoAHf5b/JavG9FmFvRn4fGa45VTVo2GfMN6K\r\naIKF0obeCbYi/QUf8B+Xi1tSIJm1VCKRE7nnliQ/TzGaNulgWeyTbVkG0/X8LQ==</ds:X509Certificate></ds:X509Data></ds:KeyInfo>\r\n</ds:Signature><saml2:Subject xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">admin@kluglabs.com</saml2:NameID><saml2:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml2:SubjectConfirmationData NotOnOrAfter=\"2013-08-03T21:59:43.942Z\" Recipient=\"https://auth0145.auth0.com\"/></saml2:SubjectConfirmation></saml2:Subject><saml2:Conditions NotBefore=\"2013-08-03T21:49:43.943Z\" NotOnOrAfter=\"2013-08-03T21:59:43.942Z\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:AudienceRestriction><saml2:Audience>https://auth0145.auth0.com</saml2:Audience></saml2:AudienceRestriction></saml2:Conditions><saml2:AuthnStatement AuthnInstant=\"2013-08-03T21:54:43.942Z\" SessionIndex=\"id1375566883942.687610437\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:AuthnContext><saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef></saml2:AuthnContext></saml2:AuthnStatement><saml2:AttributeStatement xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:Attribute Name=\"Role\" NameFormat=\"ns\"><saml2:AttributeValue xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">Admin</saml2:AttributeValue></saml2:Attribute></saml2:AttributeStatement></saml2:Assertion>"
  },
  {
    "path": "test/static/signature_with_inclusivenamespaces_lines_windows.xml",
    "content": "<saml2:Assertion xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"id8132302868541019755414121\" IssueInstant=\"2013-08-03T21:54:43.942Z\" Version=\"2.0\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"><saml2:Issuer Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:entity\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://www.okta.com/k7xkhq0jUHUPQAXVMUAN</saml2:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><ds:Reference URI=\"#id8132302868541019755414121\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"xs\"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>4G+uveKmtiB1EkY5BAt+8lmQwjI=</ds:DigestValue></ds:Reference></ds:SignedInfo>\r\n<ds:SignatureValue>\r\nQ80N6FUr5/YPtEzRlRdMoPu+bL0MssDxNUY+yxykzbmxsI0joEo/SmmSgZrDYQKTllZk/KfzBMPF\r\nV9yBH4+mEzCU5E3xuCs99jZzafcw3K8mIMTJy1YHxjc359d27R5s50i9w5PHsusRov0MjQIoJ2w4\r\n8Gy4EnYaViqBR3UVEqE=\r\n</ds:SignatureValue>\r\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>\r\nMIICnTCCAgagAwIBAgIGAUBGHxqUMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYDVQQGEwJVUzETMBEG\r\nA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU\r\nMBIGA1UECwwLU1NPUHJvdmlkZXIxEjAQBgNVBAMMCWtsdWdsYWJzMjEcMBoGCSqGSIb3DQEJARYN\r\naW5mb0Bva3RhLmNvbTAeFw0xMzA4MDMyMTM4MzhaFw00MzA4MDMyMTM5MzhaMIGRMQswCQYDVQQG\r\nEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UE\r\nCgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEjAQBgNVBAMMCWtsdWdsYWJzMjEcMBoGCSqG\r\nSIb3DQEJARYNaW5mb0Bva3RhLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsCB9lJTH\r\nqB7vdM5jeOH84cW8u7IHYv4/OAPYF0fBYe9wJy19CgyM2OgiASuAcItnH4WhB+io2ZPwb/Xwl7Uu\r\n4XmUE0l+mkCNuDYp5fXTZxwv5G6HvkAxXZio0Rk9T0VETCroxgpS5LxQ/o/owjR39S7xzRnj6ddX\r\n3Mq2yGjKyBcCAwEAATANBgkqhkiG9w0BAQUFAAOBgQAB1qGNqSNLLWq+RPcP+wOaWtYpJOJ8/MbZ\r\nEWWm9/KKHKXM6J/zgUUIXZi3czMeO+Y+X14PR8lGXoAHf5b/JavG9FmFvRn4fGa45VTVo2GfMN6K\r\naIKF0obeCbYi/QUf8B+Xi1tSIJm1VCKRE7nnliQ/TzGaNulgWeyTbVkG0/X8LQ==</ds:X509Certificate></ds:X509Data></ds:KeyInfo>\r\n</ds:Signature><saml2:Subject xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">admin@kluglabs.com</saml2:NameID><saml2:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml2:SubjectConfirmationData NotOnOrAfter=\"2013-08-03T21:59:43.942Z\" Recipient=\"https://auth0145.auth0.com\"/></saml2:SubjectConfirmation></saml2:Subject><saml2:Conditions NotBefore=\"2013-08-03T21:49:43.943Z\" NotOnOrAfter=\"2013-08-03T21:59:43.942Z\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:AudienceRestriction><saml2:Audience>https://auth0145.auth0.com</saml2:Audience></saml2:AudienceRestriction></saml2:Conditions><saml2:AuthnStatement AuthnInstant=\"2013-08-03T21:54:43.942Z\" SessionIndex=\"id1375566883942.687610437\" xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:AuthnContext><saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef></saml2:AuthnContext></saml2:AuthnStatement><saml2:AttributeStatement xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\"><saml2:Attribute Name=\"Role\" NameFormat=\"ns\"><saml2:AttributeValue xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xs:string\">Admin</saml2:AttributeValue></saml2:Attribute></saml2:AttributeStatement></saml2:Assertion>\r\n"
  },
  {
    "path": "test/static/unsigned_saml_response.xml",
    "content": "<samlp:Response\r\n    xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"\r\n    xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\"\r\n    ID=\"_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\r\n    Version=\"2.0\"\r\n    IssueInstant=\"2000-01-01T01:00:00Z\"\r\n    Destination=\"https://acs.example.com/\"\r\n    InResponseTo=\"inResponseTo\">\r\n    <saml:Issuer>https://idp.example.com/</saml:Issuer>\r\n    <samlp:Status>\r\n        <samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/>\r\n    </samlp:Status>\r\n    <saml:Assertion\r\n        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n        xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\r\n        ID=\"_bbbbbbbbbbbbbbbbbbbbbbbb\"\r\n        Version=\"2.0\" IssueInstant=\"2000-01-01T01:00:00Z\">\r\n        <saml:Issuer>https://idp.example.com/</saml:Issuer>\r\n        <saml:Subject>\r\n            <saml:NameID\r\n                SPNameQualifier=\"audience\"\r\n                Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">nameId</saml:NameID>\r\n            <saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\">\r\n                <saml:SubjectConfirmationData\r\n                    NotOnOrAfter=\"3000-01-01T01:00:00Z\"\r\n                    Recipient=\"https://acs.example.com/\"\r\n                    InResponseTo=\"inResponseTo\"/>\r\n            </saml:SubjectConfirmation>\r\n        </saml:Subject>\r\n        <saml:Conditions\r\n            NotBefore=\"2000-01-01T01:00:00Z\"\r\n            NotOnOrAfter=\"3000-01-01T01:00:00Z\">\r\n            <saml:AudienceRestriction>\r\n                <saml:Audience>audience</saml:Audience>\r\n            </saml:AudienceRestriction>\r\n        </saml:Conditions>\r\n        <saml:AuthnStatement\r\n            AuthnInstant=\"2000-01-01T01:00:00Z\"\r\n            SessionNotOnOrAfter=\"3000-01-01T01:00:00Z\"\r\n            SessionIndex=\"42\">\r\n            <saml:AuthnContext>\r\n                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>\r\n            </saml:AuthnContext>\r\n        </saml:AuthnStatement>\r\n    </saml:Assertion>\r\n</samlp:Response>\r\n"
  },
  {
    "path": "test/static/valid_saml.xml",
    "content": "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"pfx94e4a319-b6f7-4a40-25d1-01fcb642e4c5\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\" Destination=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\r\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\r\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\r\n  <ds:Reference URI=\"#pfx94e4a319-b6f7-4a40-25d1-01fcb642e4c5\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>fc21hh1bKZpaMNjx9HfOfVelfWw=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>dkONrkxW+LSuDvnNMG/mWYFa47d2WGyapLhXSTYqrlT9Td+tT7ciojNJ55WTaPaCMt7IrGtIxxskPAZIjdIn5pRyDxHr0joWxzZ7oZHCOI1CnQV5HjOq+rzzmEN2LctCZ6S4hbL7SQ1qJ3vp2BCXAygy4tmJOURQdnk0KLwwRS8=</ds:SignatureValue>\r\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><saml:Assertion xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" ID=\"pfx66496e6c-3c29-230d-6d47-b245434b872d\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\r\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\r\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\r\n  <ds:Reference URI=\"#pfx66496e6c-3c29-230d-6d47-b245434b872d\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>RnNjoyUguwze5w2R+cboyTHlkQk=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>aw5711jKP7xragunjRRCAD4mT4xKHc37iohBpQDbdSomD3ksOSB96UZQp0MtaC3xlVSkMtYw85Om96T2q2xrxLLYVA50eFJEMMF7SCVPStWTVjBlaCuOPEQxIaHyJs9Sy3MCEfbBh4Pqn9IJBd1kzwdlCrWWjAmksbFFg5wHQJA=</ds:SignatureValue>\r\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID SPNameQualifier=\"passport-saml\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">_6c5dcaa3053321ff4d63785fbc3f67c59a129cde82</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2012-07-03T11:37:20Z\" Recipient=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2012-07-03T11:31:50Z\" NotOnOrAfter=\"2012-07-03T11:37:20Z\"><saml:AudienceRestriction><saml:Audience>passport-saml</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2012-07-03T11:32:20Z\" SessionNotOnOrAfter=\"2012-07-03T19:32:20Z\" SessionIndex=\"_c8e6823fe38ddbce125f9be6e5118b8c352d04bcae\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"uid\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"givenName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"sn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"cn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"mail\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonPrincipalName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonTargetedID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.1\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.42\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.4\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.6\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.10\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>\r\n"
  },
  {
    "path": "test/static/valid_saml_sha256_rsa_mgf1.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Destination=\"https://acs.example.com/\" ID=\"_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\" InResponseTo=\"inResponseTo\" IssueInstant=\"2000-01-01T01:00:00Z\" Version=\"2.0\"><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n<ds:SignedInfo>\n<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n<ds:SignatureMethod Algorithm=\"http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1\"/>\n<ds:Reference URI=\"\">\n<ds:Transforms>\n<ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/>\n<ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n</ds:Transforms>\n<ds:DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\"/>\n<ds:DigestValue>bA/90zzLS/36DstvPJRrMNwGax5WQv8NneSuNdLnMYs=</ds:DigestValue>\n</ds:Reference>\n</ds:SignedInfo>\n<ds:SignatureValue>\n0fK5rJEtj0+JIL3hAuDsEAuKYoiwHzZTgQgspLyEe+XQan1FzT+qu3GBJSpSDfArBHjHXtizVfi8\nirId6a1kOj6ShEw2ZSGYD8Dh2d0HmrHqlOqpZ5eLiWeFA6VTtW1Cqmvr+x4Ndxcg0wWmmGr4hpSD\nYg8fkA8e32Fd2QxqLsQqVlCcuvJVCJ/12XSGcMW+Tse254fN6JENLLUdilu+14NNQKAHpKpjeajg\njG3fn0VNvyVQXKi2deYTWYaLRujBgv3Ncz8t9Hjthk+XxrRVHJiGc6HyVvqdpi5ChM41fjB1+eBo\nNkZ0Q73ZSCbTAqVduUWqL5pQzINq16kUm2ovkg7h3JoqSQr5yhoBJXZEf6FEyYdCCLd3rlIrkcvD\n+wfF2CwNRc6utgO/05JAA7Z1x2e0K6o2a6EQy93dkUIBhpxPYU/IdmGb15AfKJ3OrB1K/jTrxZ2q\nog/u0fJe0vU1sL4EDOXqVMj/unTZqDP/K1mOHK/eDWafs/IwMv65ebZUwTk74AMk/oOYV9mL8beY\nJAVYMN+xPA1cXnHlRgwATWLXjfiQcMXo44nhaw0YlOUGIoRLYURqHmXz0W3d8pXYdybLmdClkqLR\nvo1ryK1OC2paYG9qwk51QJ5wzMv6HRB5tDIL9/7mP7khlKgm4p+EZXFGYmvYDbk2x219SvxPmfY=\n</ds:SignatureValue>\n<ds:KeyInfo>\n<ds:KeyValue>\n<ds:RSAKeyValue>\n<ds:Modulus>\n16YEqKYde+lUD8PuHvdVAC+o9E2y/2iNwJo+tk1PdSjpOMYoMvvMRUnlNiAuuFu2m3xavtuSvtcm\nyZjAaveFCsimm+8nl5np9sSfT0+W6+E8J7G3gWa84l0kfLkxOtA3Vi2WCRAURILveiXhFi8z/9B3\n5xZZ7huZF5W+q6cu5e9t2Hg71PZb7JukY+OpuUfI+Aknpypi7B0iIZjT+fUrBKSdeg/kXynKyqsT\n8aerf6AhCl46ZjnhqF/Vk+VfVDMaxhYGNmC2m/bSwiCuPIuq4F6R1J2zKtl8gE+fG0hv04n/fYaI\nkNqL87FVK1XgmuP7lIP6a/sNW2ZyAZekfFlT01cIJmDfvFsNu2i4jZLAp+9Le+F2S6/cZ2J25499\nuAImafWePLwxApuNU3PlfXqhjTv+WC4GaqBk8uBJdwDHDRd5ZHnGdlGSjCN+NaSNbx8kRtIwq9mW\nKct9KWECnfmewL2SjFEyRUHwSDp981zekgPJVmSzzluFU3Tn3Bo0Io9wFA3k3opVIoKUYJE5fe1l\nKxn2rLy1zK3UaF2MYxj3vrOPrX/oJyoU1UOoesHviEmhVTnl6QqzlMGTNDnYpELSmIB9BvTqySsQ\n2Q5eGJJGBaqocsORLpvR2cDFPOt9ZZAUqjEYM/AF+ynQZ9T6xkusDqfhgtvC9SEnkcUa4lrWnl0=\n</ds:Modulus>\n<ds:Exponent>AQAB</ds:Exponent>\n</ds:RSAKeyValue>\n</ds:KeyValue>\n<ds:X509Data>\n<ds:X509Certificate>\nMIIFFzCCAv+gAwIBAgIUaAU88KUbZLe7NwTw+jdCHIDU6wIwDQYJKoZIhvcNAQELBQAwGjEYMBYG\nA1UEAwwPaWRwLmV4YW1wbGUuY29tMCAXDTI1MDkwODExMTUzMFoYDzIxMjUwODE1MTExNTMwWjAa\nMRgwFgYDVQQDDA9pZHAuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\nAQDXpgSoph176VQPw+4e91UAL6j0TbL/aI3Amj62TU91KOk4xigy+8xFSeU2IC64W7abfFq+25K+\n1ybJmMBq94UKyKab7yeXmen2xJ9PT5br4TwnsbeBZrziXSR8uTE60DdWLZYJEBREgu96JeEWLzP/\n0HfnFlnuG5kXlb6rpy7l723YeDvU9lvsm6Rj46m5R8j4CSenKmLsHSIhmNP59SsEpJ16D+RfKcrK\nqxPxp6t/oCEKXjpmOeGoX9WT5V9UMxrGFgY2YLab9tLCIK48i6rgXpHUnbMq2XyAT58bSG/Tif99\nhoiQ2ovzsVUrVeCa4/uUg/pr+w1bZnIBl6R8WVPTVwgmYN+8Ww27aLiNksCn70t74XZLr9xnYnbn\nj324AiZp9Z48vDECm41Tc+V9eqGNO/5YLgZqoGTy4El3AMcNF3lkecZ2UZKMI341pI1vHyRG0jCr\n2ZYpy30pYQKd+Z7AvZKMUTJFQfBIOn3zXN6SA8lWZLPOW4VTdOfcGjQij3AUDeTeilUigpRgkTl9\n7WUrGfasvLXMrdRoXYxjGPe+s4+tf+gnKhTVQ6h6we+ISaFVOeXpCrOUwZM0OdikQtKYgH0G9OrJ\nKxDZDl4YkkYFqqhyw5Eum9HZwMU8631lkBSqMRgz8AX7KdBn1PrGS6wOp+GC28L1ISeRxRriWtae\nXQIDAQABo1MwUTAdBgNVHQ4EFgQULRbUCREu3zQABqNW8LMOfraF5BMwHwYDVR0jBBgwFoAULRbU\nCREu3zQABqNW8LMOfraF5BMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAA6Jm\n3pll7XHBY/oXrtRAu60RpH4pcZBSf68zhCQKUnXALy2FWrUGU8uVCJJuxXIcxszTOCZmwVF12Yce\nIFpBrWHxKCDZWYDO6hrwZvsa2vh5mXDZo3c/HX6GmJR4f4oIIZnbxFhXR30419PlrwMW3Rk7rnVS\nDz/HpQfdS4y8jYgsm2dIRo+PXQytFRCDj4afsT3eZa27QjFxLTuK+SwkhupSH1WWYmqL9+iIJiLL\n/ntfM4MwtOUwcfqI0ttbvFZZIPneBCuEDLn/zJ/QBV3ZvjQDt53W21HaPGPHBBfVZVroZPvuGvul\nWRLeECI1Hmbl3al/2aOC0LWzPIk8dlTcN+EWcCEufpTOEgkob8waEyxlX0Z5OBjkCHpyDTPGkxBB\nOCJv88Frx7qdbu8eSV0OviuaM/B7ky2NbDMKIybX4tf/Q8FNfjPLvTv+8nbrMz6kTno3RR2YC7tt\nI7Glb/eOg3F/ouF4wcoPAj+OyU5Q5WJMMaZ9cXF9pwszsglLbFms+WD5PFxlloh6I1hO7TccWKTe\nUJ5fYZSYYm31JqWit3DBltXTyRyL7KFSdT/FyRBk62YLCJqJmcukIUJUTya73/RmjW1M4zMBNaIj\n/pH77opKWnVbm9F4XnBCG4r9+FRXdV2zKW6DgvDzQ6DaZ+0cwC36vSqkDyjZYv/tviuWfM8=\n</ds:X509Certificate>\n</ds:X509Data>\n</ds:KeyInfo>\n</ds:Signature>\n    <saml:Issuer>https://idp.example.com/</saml:Issuer>\n    <samlp:Status>\n        <samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/>\n    </samlp:Status>\n    <saml:Assertion xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ID=\"_bbbbbbbbbbbbbbbbbbbbbbbb\" IssueInstant=\"2000-01-01T01:00:00Z\" Version=\"2.0\">\n        <saml:Issuer>https://idp.example.com/</saml:Issuer>\n        <saml:Subject>\n            <saml:NameID Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\" SPNameQualifier=\"audience\">nameId</saml:NameID>\n            <saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\">\n                <saml:SubjectConfirmationData InResponseTo=\"inResponseTo\" NotOnOrAfter=\"3000-01-01T01:00:00Z\" Recipient=\"https://acs.example.com/\"/>\n            </saml:SubjectConfirmation>\n        </saml:Subject>\n        <saml:Conditions NotBefore=\"2000-01-01T01:00:00Z\" NotOnOrAfter=\"3000-01-01T01:00:00Z\">\n            <saml:AudienceRestriction>\n                <saml:Audience>audience</saml:Audience>\n            </saml:AudienceRestriction>\n        </saml:Conditions>\n        <saml:AuthnStatement AuthnInstant=\"2000-01-01T01:00:00Z\" SessionIndex=\"42\" SessionNotOnOrAfter=\"3000-01-01T01:00:00Z\">\n            <saml:AuthnContext>\n                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>\n            </saml:AuthnContext>\n        </saml:AuthnStatement>\n    </saml:Assertion>\n</samlp:Response>"
  },
  {
    "path": "test/static/valid_saml_signature_wrapping.xml",
    "content": "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"pfx94e4a319-b6f7-4a40-25d1-01fcb642e4c5\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\" Destination=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status>\r\n<wrap>\r\n<saml:Assertion xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" ID=\"pfx66496e6c-3c29-230d-6d47-b245434b872d\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\r\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\r\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\r\n  <ds:Reference URI=\"#pfx66496e6c-3c29-230d-6d47-b245434b872d\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>RnNjoyUguwze5w2R+cboyTHlkQk=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>aw5711jKP7xragunjRRCAD4mT4xKHc37iohBpQDbdSomD3ksOSB96UZQp0MtaC3xlVSkMtYw85Om96T2q2xrxLLYVA50eFJEMMF7SCVPStWTVjBlaCuOPEQxIaHyJs9Sy3MCEfbBh4Pqn9IJBd1kzwdlCrWWjAmksbFFg5wHQJA=</ds:SignatureValue>\r\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID SPNameQualifier=\"passport-saml\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">_6c5dcaa3053321ff4d63785fbc3f67c59a129cde82</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2012-07-03T11:37:20Z\" Recipient=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2012-07-03T11:31:50Z\" NotOnOrAfter=\"2012-07-03T11:37:20Z\"><saml:AudienceRestriction><saml:Audience>passport-saml</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2012-07-03T11:32:20Z\" SessionNotOnOrAfter=\"2012-07-03T19:32:20Z\" SessionIndex=\"_c8e6823fe38ddbce125f9be6e5118b8c352d04bcae\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"uid\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"givenName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"sn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"cn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"mail\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonPrincipalName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonTargetedID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.1\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.42\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.4\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.6\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.10\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>\r\n</wrap>\r\n<saml:Assertion xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" ID=\"pfx66496e6c-3c29-230d-6d47-b245434b872d\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\r\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\r\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\r\n  <ds:Reference URI=\"#pfx66496e6c-3c29-230d-6d47-b245434b872d\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>RnNjoyUguwze5w2R+cboyTHlkQk=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>aw5711jKP7xragunjRRCAD4mT4xKHc37iohBpQDbdSomD3ksOSB96UZQp0MtaC3xlVSkMtYw85Om96T2q2xrxLLYVA50eFJEMMF7SCVPStWTVjBlaCuOPEQxIaHyJs9Sy3MCEfbBh4Pqn9IJBd1kzwdlCrWWjAmksbFFg5wHQJA=</ds:SignatureValue>\r\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature>\r\n================\r\nThis Assertion contains malicious data.\r\n================\r\n</saml:Assertion>\r\n</samlp:Response>\r\n"
  },
  {
    "path": "test/static/valid_saml_with_digest_comment.xml",
    "content": "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"pfx94e4a319-b6f7-4a40-25d1-01fcb642e4c5\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\" Destination=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status>\n<saml:Assertion xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" ID=\"pfx66496e6c-3c29-230d-6d47-b245434b872d\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\n  <ds:Reference URI=\"#pfx66496e6c-3c29-230d-6d47-b245434b872d\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue><!--6zWeUASlD8E73xzDn4ggf0r7ysQ=-->RnNjoyUguwze5w2R+cboyTHlkQk=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>aw5711jKP7xragunjRRCAD4mT4xKHc37iohBpQDbdSomD3ksOSB96UZQp0MtaC3xlVSkMtYw85Om96T2q2xrxLLYVA50eFJEMMF7SCVPStWTVjBlaCuOPEQxIaHyJs9Sy3MCEfbBh4Pqn9IJBd1kzwdlCrWWjAmksbFFg5wHQJA=</ds:SignatureValue>\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID SPNameQualifier=\"passport-saml\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">test@example.com</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2012-07-03T11:37:20Z\" Recipient=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2012-07-03T11:31:50Z\" NotOnOrAfter=\"2012-07-03T11:37:20Z\"><saml:AudienceRestriction><saml:Audience>passport-saml</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2012-07-03T11:32:20Z\" SessionNotOnOrAfter=\"2012-07-03T19:32:20Z\" SessionIndex=\"_c8e6823fe38ddbce125f9be6e5118b8c352d04bcae\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"uid\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"givenName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"sn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"cn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"mail\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonPrincipalName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonTargetedID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.1\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.42\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.4\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.6\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.10\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>\n</samlp:Response>"
  },
  {
    "path": "test/static/valid_saml_withcomments.xml",
    "content": "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"pfx94e4a319-b6f7-4a40-25d1-01fcb642e4c5\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\" Destination=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\r\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#WithComments\"/>\r\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\r\n  <ds:Reference URI=\"#pfx94e4a319-b6f7-4a40-25d1-01fcb642e4c5\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>fc21hh1bKZpaMNjx9HfOfVelfWw=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>dkONrkxW+LSuDvnNMG/mWYFa47d2WGyapLhXSTYqrlT9Td+tT7ciojNJ55WTaPaCMt7IrGtIxxskPAZIjdIn5pRyDxHr0joWxzZ7oZHCOI1CnQV5HjOq+rzzmEN2LctCZ6S4hbL7SQ1qJ3vp2BCXAygy4tmJOURQdnk0KLwwRS8=</ds:SignatureValue>\r\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><saml:Assertion xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" ID=\"pfx66496e6c-3c29-230d-6d47-b245434b872d\" Version=\"2.0\" IssueInstant=\"2012-07-03T11:32:20Z\"><saml:Issuer>https://openidp.feide.no</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\r\n  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\r\n    <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\r\n  <ds:Reference URI=\"#pfx66496e6c-3c29-230d-6d47-b245434b872d\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>RnNjoyUguwze5w2R+cboyTHlkQk=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>aw5711jKP7xragunjRRCAD4mT4xKHc37iohBpQDbdSomD3ksOSB96UZQp0MtaC3xlVSkMtYw85Om96T2q2xrxLLYVA50eFJEMMF7SCVPStWTVjBlaCuOPEQxIaHyJs9Sy3MCEfbBh4Pqn9IJBd1kzwdlCrWWjAmksbFFg5wHQJA=</ds:SignatureValue>\r\n<ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID SPNameQualifier=\"passport-saml\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">_6c5dcaa3053321ff4d63785fbc3f67c59a129cde82</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2012-07-03T11:37:20Z\" Recipient=\"http://localhost:3000/login/callback\" InResponseTo=\"_d766d16611ac0d14121b\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2012-07-03T11:31:50Z\" NotOnOrAfter=\"2012-07-03T11:37:20Z\"><saml:AudienceRestriction><saml:Audience>passport-saml</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2012-07-03T11:32:20Z\" SessionNotOnOrAfter=\"2012-07-03T19:32:20Z\" SessionIndex=\"_c8e6823fe38ddbce125f9be6e5118b8c352d04bcae\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"uid\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"givenName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"sn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"cn\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"mail\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonPrincipalName\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"eduPersonTargetedID\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.1\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.42\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.4\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:2.5.4.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">Henri Bergius</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:0.9.2342.19200300.100.1.3\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">henri.bergius@nemein.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.6\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">bergie@rnd.feide.no</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.3.6.1.4.1.5923.1.1.1.10\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"><saml:AttributeValue xsi:type=\"xs:string\">8216c78fe244502efa13f62e6615c94acb7bdf3e</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>\r\n"
  },
  {
    "path": "test/static/valid_signature wsu.xml",
    "content": "<root><x xmlns=\"ns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>5jkdJLKVpfEiAQ0k5bnvfCQJKks=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>97gNxHth/Gc2wH4FiTiWJJrLaHI=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>TUkwwDGRfgW3CORC9RvimMKtFpU=</DigestValue></Reference></SignedInfo><SignatureValue>V5wZiNWAzyQmAhm+F3ji0IIq9ariZ/ORCdHXjhwDU36yPUuRiyLoy7WJvl7tkyV/C/D7R2WiQ/TwbM3973ZWToKUwAM/FSzOTu+4P/ea8zZ6SDxYTFxDwvxSdtfiYqZ/C61EApnNU5haoyiZ6H9ZBeJaERWIDI+fpJcCA5c6sb0=</SignatureValue></Signature></root>"
  },
  {
    "path": "test/static/valid_signature.xml",
    "content": "<root><x xmlns=\"ns\" Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>K4dI497ZCxzweDIrbndUSmtoezY=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>sH1gxKve8wlU8LlFVa2l6w3HMJ0=</DigestValue></Reference></SignedInfo><SignatureValue>PI2xGt3XrVcxYZ34Kw7nFdq75c7Mmo7J0q7yeDhBprHuJal/KV9KyKG+Zy3bmQIxNwkPh0KMP5r1YMTKlyifwbWK0JitRCSa0Fa6z6+TgJi193yiR5S1MQ+esoQT0RzyIOBl9/GuJmXx/1rXnqrTxmL7UxtqKuM29/eHwF0QDUI=</SignatureValue><KeyInfo><dummyKey>1234</dummyKey></KeyInfo></Signature></root>"
  },
  {
    "path": "test/static/valid_signature_utf8.xml",
    "content": "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Version=\"2.0\" ID=\"_w014WYqtFGe3OCA7UIXqUKTj8Qmo2GHn\" IssueInstant=\"2013-06-14T16:50:21.848Z\"><saml:Issuer>urn:issuer</saml:Issuer><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\"/><Reference URI=\"#_w014WYqtFGe3OCA7UIXqUKTj8Qmo2GHn\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\"/><DigestValue>is/s3v+lPE4xdF9ImlbRMoXJjOPWKH8C/ixcfRaDPgU=</DigestValue></Reference></SignedInfo><SignatureValue>DgIb3UlS5p7j6iEUD1SsaPs2HqHnI3nC2ixw7CRebgcz8lG6o7AbgRsy57ePr1hX90lxOGvO8Txz8kJDq3vWH6g9fU0Nu+1QxCq4/mb3a2Jr84lFDivSUQa7YEugECH789EvRzEXRTseKx8XYKjlH6ffvai3Oqn9kSLWPQbY7xI=</SignatureValue><KeyInfo><X509Data><X509Certificate>MIIBxDCCAW6gAwIBAgIQxUSXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BAQQFADAWMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ3NTlaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0Q2xpZW50MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+L6aB9x928noY4+0QBsXnxkQE4quJl7c3PUPdVu7k9A02hRG481XIfWhrDY5i7OEB7KGW7qFJotLLeMec/UkKUwCgv3VvJrs2nE9xO3SSWIdNzADukYh+Cxt+FUU6tUkDeqg7dqwivOXhuOTRyOI3HqbWTbumaLdc8jufz2LhaQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcNAQEEBQADQQAfIbnMPVYkNNfX1tG1F+qfLhHwJdfDUZuPyRPucWF5qkh6sSdWVBY5sT/txBnVJGziyO8DPYdu2fPMER8ajJfl</X509Certificate></X509Data></KeyInfo></Signature><saml:Subject><saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">вКонтакте</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData NotOnOrAfter=\"2013-06-14T17:00:21.848Z\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2013-06-14T16:50:21.848Z\" NotOnOrAfter=\"2013-06-14T17:00:21.848Z\"><saml:AudienceRestriction><saml:Audience>urn:myapp</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AttributeStatement xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><saml:Attribute Name=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress\"><saml:AttributeValue xsi:type=\"xs:anyType\">сообщить@bar.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\"><saml:AttributeValue xsi:type=\"xs:anyType\">сообщить вКонтакте</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AuthnStatement AuthnInstant=\"2013-06-14T16:50:21.848Z\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion>"
  },
  {
    "path": "test/static/valid_signature_with_lowercase_id_attribute.xml",
    "content": "<root><x xmlns=\"ns\" id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>AAGWFnPFdPl0aU4854Deo+j9BmU=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>79MH3RaPsyFcSyrzl4Jrpwp/lgo=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>MEdYYk8XXRBbW5Hlo8GlIO9J0fc=</DigestValue></Reference></SignedInfo><SignatureValue>aFMgQTWuz+T0AzqERRTq/+XAxZmIs+ff031I579zfDTD/PjrCOhb4TVAkgydZajUkZwbOc5/mnBs9S/nqfABh1JXvqO/a+U+AzgSDoZesJ3OMHcPPSFt+5iYASjsV0B3MLUds4iNl76ETcwp1HC6u8rRspQ3uWzFt2zBzfEvmtY=</SignatureValue><KeyInfo><dummyKey>1234</dummyKey></KeyInfo></Signature></root>"
  },
  {
    "path": "test/static/valid_signature_with_reference_keyInfo.xml",
    "content": "<root><x xmlns=\"ns\" Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>K4dI497ZCxzweDIrbndUSmtoezY=</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>sH1gxKve8wlU8LlFVa2l6w3HMJ0=</DigestValue></Reference></SignedInfo><SignatureValue>PI2xGt3XrVcxYZ34Kw7nFdq75c7Mmo7J0q7yeDhBprHuJal/KV9KyKG+Zy3bmQIxNwkPh0KMP5r1YMTKlyifwbWK0JitRCSa0Fa6z6+TgJi193yiR5S1MQ+esoQT0RzyIOBl9/GuJmXx/1rXnqrTxmL7UxtqKuM29/eHwF0QDUI=</SignatureValue><KeyInfo xmlns:o=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\"><o:SecurityTokenReference><o:Reference URI=\"#sec_0\" ValueType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3\"/></o:SecurityTokenReference></KeyInfo></Signature></root>"
  },
  {
    "path": "test/static/valid_signature_with_root_level_sig_namespace.xml",
    "content": "<root xmlns:ns1=\"http://www.w3.org/2000/09/xmldsig#\"><x xmlns=\"ns\" Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" Id=\"_2\"/></z><ns1:Signature><ns1:SignedInfo><ns1:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><ns1:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><ns1:Reference URI=\"#_0\"><ns1:Transforms><ns1:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ns1:Transforms><ns1:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ns1:DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</ns1:DigestValue></ns1:Reference><ns1:Reference URI=\"#_1\"><ns1:Transforms><ns1:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ns1:Transforms><ns1:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ns1:DigestValue>K4dI497ZCxzweDIrbndUSmtoezY=</ns1:DigestValue></ns1:Reference><ns1:Reference URI=\"#_2\"><ns1:Transforms><ns1:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ns1:Transforms><ns1:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ns1:DigestValue>sH1gxKve8wlU8LlFVa2l6w3HMJ0=</ns1:DigestValue></ns1:Reference></ns1:SignedInfo><ns1:SignatureValue>rR8+4xHiI8GQJ9Wty2TUbNI7Dd4uc89/BsAygYfeobEjmt4awzg6bQNA0nuQ+VggiPCYdKuKL8cPI7FUhk8osbVKdLPdy+rdJnibsyNpV87R7W5GZlFBEu/NqG6EYOMTHjpD4hq+H8ZeHC5YZDHPknPzJV8+A1UKN/BL2oWMQcg=</ns1:SignatureValue><ns1:KeyInfo><ns1:dummyKey>1234</ns1:dummyKey></ns1:KeyInfo></ns1:Signature></root>\r\n"
  },
  {
    "path": "test/static/valid_signature_with_unused_prefixes.xml",
    "content": "<soapenv:Envelope xmlns:eg=\"http://www.example.com\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"><wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"><ds:Signature Id=\"SIG-14\" xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces PrefixList=\"wsa eg soapenv\" xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><ds:Reference URI=\"#id-9\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces PrefixList=\"eg\" xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>GAEFzMhRbXD8lZeTd5GwSqkB73Q=</ds:DigestValue></ds:Reference><ds:Reference URI=\"#id-10\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces PrefixList=\"eg soapenv\" xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>c2bqLRa0Q+/P7+vuXZHO8/iiac8=</ds:DigestValue></ds:Reference><ds:Reference URI=\"#id-11\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces PrefixList=\"eg soapenv\" xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>95WoCzf9J63UgdLCj/05PYaJIAw=</ds:DigestValue></ds:Reference><ds:Reference URI=\"#TS-8\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces PrefixList=\"wsse wsa eg soapenv\" xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>pa04vRHbAdvfr6Re5wgx2qFQepE=</ds:DigestValue></ds:Reference><ds:Reference URI=\"#id-12\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces PrefixList=\"eg soapenv\" xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>YYNZUGNHN8uRGzMqPVC2n5XODP8=</ds:DigestValue></ds:Reference><ds:Reference URI=\"#id-13\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces PrefixList=\"eg soapenv\" xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><ds:DigestValue>GvVowT6jH/4fExGYfFzDbzhSwTs=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>F8Lm5aUouA5FtxQ1krQ3unE9NFh0QSl+QscEyTcK3FrIpWCB195Z7cbmYa9RsiYMdr2wTHHmou/+wrjpk9pZFJq+b0tpHKCpfj6B302Rexb5f+cDpUjBB/NGb11qaUiM65keVIWzmYnHC0iCxsCaG3lwHMELNr7GxNun1U7LzzI=</ds:SignatureValue><ds:KeyInfo Id=\"KI-7E559E62741B121FC215529264679845\"><wsse:SecurityTokenReference wsu:Id=\"STR-7E559E62741B121FC215529264679846\"><wsse:KeyIdentifier EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\" ValueType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3\">MIIBxDCCAW6gAwIBAgIQxUSXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BAQQFADAWMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ3NTlaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0Q2xpZW50MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+L6aB9x928noY4+0QBsXnxkQE4quJl7c3PUPdVu7k9A02hRG481XIfWhrDY5i7OEB7KGW7qFJotLLeMec/UkKUwCgv3VvJrs2nE9xO3SSWIdNzADukYh+Cxt+FUU6tUkDeqg7dqwivOXhuOTRyOI3HqbWTbumaLdc8jufz2LhaQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcNAQEEBQADQQAfIbnMPVYkNNfX1tG1F+qfLhHwJdfDUZuPyRPucWF5qkh6sSdWVBY5sT/txBnVJGziyO8DPYdu2fPMER8ajJfl</wsse:KeyIdentifier></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature><wsu:Timestamp wsu:Id=\"TS-8\"><wsu:Created>2019-03-18T16:27:47.984Z</wsu:Created><wsu:Expires>2019-03-19T04:27:47.984Z</wsu:Expires></wsu:Timestamp></wsse:Security><wsa:Action wsu:Id=\"id-13\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">http://www.example.com/testAction</wsa:Action><wsa:From wsu:Id=\"id-12\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"><wsa:Address>client</wsa:Address></wsa:From><wsa:MessageID wsu:Id=\"id-11\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">uuid:c519e597-0570-4d35-92e5-0df733a17cc1</wsa:MessageID><wsa:To wsu:Id=\"id-10\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">test</wsa:To></soapenv:Header><soapenv:Body wsu:Id=\"id-9\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"><eg:node1>testMessage</eg:node1></soapenv:Body></soapenv:Envelope>"
  },
  {
    "path": "test/static/valid_signature_with_whitespace_in_digestvalue.xml",
    "content": "<root><x xmlns=\"ns\" Id=\"_0\"/><y z_attr=\"value\" a_attr1=\"foo\" Id=\"_1\"/><z><ns:w ns:attr=\"value\" xmlns:ns=\"myns\" Id=\"_2\"/></z><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=\r\n</DigestValue></Reference><Reference URI=\"#_1\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>K4dI497ZCxzweDIrbndUSmtoezY=\r\n</DigestValue></Reference><Reference URI=\"#_2\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>sH1gxKve8wlU8LlFVa2l6w3HMJ0=\r\n</DigestValue></Reference></SignedInfo><SignatureValue>gGp+jskU2HohMdhaeGTdJBbN/rngzWrQs0+N4bqJDzHQEqUm6rVk0mDoFybJaW0AEXf/dSVhM0faYTwQK0p9aipsAORTaPq677GcdKwyEHHRnly064D8GlikyQ49451SEViy89kYZO1yf+x5MNHNyCi7VVRIixbsSLOUgu0A9Yo=</SignatureValue></Signature></root>\r\n"
  },
  {
    "path": "test/static/valid_signature_without_transforms_element.xml",
    "content": "<?xml version=\"1.0\"?>\n<library><book ID=\"bookid\"><name>some text</name></book><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#bookid\"><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>LsMoqo1d6Sqh8DKLp00MK0fSBDA=</DigestValue></Reference></SignedInfo><SignatureValue>OR1SYcyU18qELj+3DX/bW/r5DqueuyPAnNFEh3hNKFaj8ZKLB/mdsR9w8GDBCmZ2\nlsCTEvJqWC37oF8rm2eBSonNbdBnA+TM6Y22C8rffVzaoM3zpNoeWMH2LwFmpdKB\nUXOMWVExEaz/s4fOcyv1ajVuk42I3nl0xcD95+i7PjY=</SignatureValue></Signature></library>"
  },
  {
    "path": "test/static/windows_store_certificate.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDyTCCArGgAwIBAgIQNP+YKvSo8IVArhlhpgc/xjANBgkqhkiG9w0BAQsFADCB\njjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1Jl\nZG1vbmQxHjAcBgNVBAoMFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEWMBQGA1UECwwN\nV2luZG93cyBTdG9yZTEgMB4GA1UEAwwXV2luZG93cyBTdG9yZSBMaWNlbnNpbmcw\nHhcNMTExMTE3MjMwNTAyWhcNMzYxMTEwMjMxMzQ0WjCBjjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1JlZG1vbmQxHjAcBgNVBAoM\nFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEWMBQGA1UECwwNV2luZG93cyBTdG9yZTEg\nMB4GA1UEAwwXV2luZG93cyBTdG9yZSBMaWNlbnNpbmcwggEiMA0GCSqGSIb3DQEB\nAQUAA4IBDwAwggEKAoIBAQCcr4/vgqZFtzMqy3jO0XHjBUNx6j7ZTXEnNpLl2VSe\nzVQA9KK2RlvroXKhYMUUdJpw+txm1mqi/W7D9QOYTq1e83GLhWC9IRh/OSmSYt0e\nkgVLB+icyRH3dtpYcJ5sspU2huPf4I/Nc06OuXlMsD9MU4Ug9IBD2HSDBEquhGRo\nxV64YuEH4645oB14LlEay0+JZlkKZ/mVhx/sdzSBfrda1X/Ckc7SOgnTSM3d/DnO\n5DKwV2WYn+7i/rBqe4/op6IqQMrPpHyem9Sny+i0xiUMA+1IwkX0hs0gvHM6zDww\nTMDiTapbCy9LnmMx65oMq56hhsQydLEmquq8lVYUDEzLAgMBAAGjITAfMB0GA1Ud\nDgQWBBREzrOBz7zw+HWskxonOXAPMa6+NzANBgkqhkiG9w0BAQsFAAOCAQEAeVtN\n4c6muxO6yfht9SaxEfleUBIjGfe0ewLBp00Ix7b7ldJ/lUQcA6y+Drrl7vjmkHQK\nOU3uZiFbCxTvgTcoz9o+1rzR/WPXmqH5bqu6ua/UrobGKavAScqqI/G6o56Xmx/y\noErWN0VapN370crKJvNWxh3yw8DCl+W0EcVRiWX5lFsMBNBbVpK4Whp+VhkSJilu\niRpe1B35Q8EqOz/4RQkOpVI0dREnuSYkBy/h2ggCtiQ5yfvH5zCdcfhFednYDevS\naxmt3W5WuHz8zglkg+OQ3qpXaXySRlrmLdxEmWu2MOiZbQkU2ZjBSQmvFAOy0dd6\nP1YLS4+Eyh5drQJc0Q==\n-----END CERTIFICATE-----"
  },
  {
    "path": "test/static/windows_store_signature.xml",
    "content": "<Receipt Version=\"1.0\" ReceiptDate=\"2012-08-30T23:10:05Z\" CertificateId=\"b809e47cd0110a4db043b3f73e83acd917fe1336\" ReceiptDeviceId=\"4e362949-acc3-fe3a-e71b-89893eb4f528\">\r\n\t<AppReceipt Id=\"8ffa256d-eca8-712a-7cf8-cbf5522df24b\" AppId=\"55428GreenlakeApps.CurrentAppSimulatorEventTest_z7q3q7z11crfr\" PurchaseDate=\"2012-06-04T23:07:24Z\" LicenseType=\"Full\" />\r\n\t<ProductReceipt Id=\"6bbf4366-6fb2-8be8-7947-92fd5f683530\" ProductId=\"Product1\" PurchaseDate=\"2012-08-30T23:08:52Z\" ExpirationDate=\"2012-09-02T23:08:49Z\" ProductType=\"Durable\" AppId=\"55428GreenlakeApps.CurrentAppSimulatorEventTest_z7q3q7z11crfr\" />\r\n\t<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">\r\n\t\t<SignedInfo>\r\n\t\t\t<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" />\r\n\t\t\t<SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\" />\r\n\t\t\t<Reference URI=\"\">\r\n\t\t\t\t<Transforms>\r\n\t\t\t\t\t<Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\" />\r\n\t\t\t\t</Transforms>\r\n\t\t\t\t<DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\" />\r\n\t\t\t\t<DigestValue>cdiU06eD8X/w1aGCHeaGCG9w/kWZ8I099rw4mmPpvdU=</DigestValue>\r\n\t\t\t</Reference>\r\n\t\t</SignedInfo>\r\n\t\t<SignatureValue>SjRIxS/2r2P6ZdgaR9bwUSa6ZItYYFpKLJZrnAa3zkMylbiWjh9oZGGng2p6/gtBHC2dSTZlLbqnysJjl7mQp/A3wKaIkzjyRXv3kxoVaSV0pkqiPt04cIfFTP0JZkE5QD/vYxiWjeyGp1dThEM2RV811sRWvmEs/hHhVxb32e8xCLtpALYx3a9lW51zRJJN0eNdPAvNoiCJlnogAoTToUQLHs72I1dECnSbeNPXiG7klpy5boKKMCZfnVXXkneWvVFtAA1h2sB7ll40LEHO4oYN6VzD+uKd76QOgGmsu9iGVyRvvmMtahvtL1/pxoxsTRedhKq6zrzCfT8qfh3C1w==</SignatureValue>\r\n\t</Signature>\r\n</Receipt>"
  },
  {
    "path": "test/static/wsfederation_metadata.pem",
    "content": "-----BEGIN CERTIFICATE-----\r\nMIIC4jCCAcqgAwIBAgIQQNXrmzhLN4VGlUXDYCRT3zANBgkqhkiG9w0BAQsFADAt\r\nMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4X\r\nDTE0MTAyODAwMDAwMFoXDTE2MTAyNzAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3Vu\r\ndHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQAD\r\nggEPADCCAQoCggEBALyKs/uPhEf7zVizjfcr/ISGFe9+yUOqwpel38zgutvLHmFD\r\n39E2hpPdQhcXn4c4dt1fU5KvkbcDdVbP8+e4TvNpJMy/nEB2V92zCQ/hhBjilwhF\r\n1ETe1TMmVjALs0KFvbxW9ZN3EdUVvxFvz/gvG29nQhl4QWKj3x8opr89lmq14Z7T\r\n0mzOV8kub+cgsOU/1bsKqrIqN1fMKKFhjKaetctdjYTfGzVQ0AJAzzbtg0/Q1wdY\r\nNAnhSDafygEv6kNiquk0r0RyasUUevEXs2LY3vSgKsKseI8ZZlQEMtE9/k/iAG7J\r\nNcEbVg53YTurNTrPnXJOU88mf3TToX14HpYsS1ECAwEAATANBgkqhkiG9w0BAQsF\r\nAAOCAQEAfolx45w0i8CdAUjjeAaYdhG9+NDHxop0UvNOqlGqYJexqPLuvX8iyUaY\r\nxNGzZxFgGI3GpKfmQP2JQWQ1E5JtY/n8iNLOKRMwqkuxSCKJxZJq4Sl/m/Yv7TS1\r\nP5LNgAj8QLCypxsWrTAmq2HSpkeSk4JBtsYxX6uhbGM/K1sEktKybVTHu22/7TmR\r\nqWTmOUy9wQvMjJb2IXdMGLG3hVntN/WWcs5w8vbt1i8Kk6o19W2MjZ95JaECKjBD\r\nYRlhG1KmSBtrsKsCBQoBzwH/rXfksTO9JoUYLXiW0IppB7DhNH4PJ5hZI91R8rR0\r\nH3/bKkLSuDaKLWSqMhozdhXsIIKvJQ==\r\n-----END CERTIFICATE-----\r\n"
  },
  {
    "path": "test/static/wsfederation_metadata.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?><EntityDescriptor ID=\"_8d1dcc18-2f1e-4a93-850b-e3a3081b3ca1\" entityID=\"https://sts.windows.net/8bd6e98d-e212-4022-b13f-a244fab4c253/\" xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\"><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /><ds:SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\" /><ds:Reference URI=\"#_8d1dcc18-2f1e-4a93-850b-e3a3081b3ca1\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\" /><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" /></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\" /><ds:DigestValue>qIVhfzD3HVMA4BUQZ+zUF6AlFgcL7FyQ8tN35NZWFJs=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>HxgwvF+xtlUb4Qa9AzEiti4X3rHu6xWOmew2sVH+BBWpuwhDWWPxK9hHVhYYcuCHZDBnN7LLTY1L80/D2+KruNug9B1kOb6c3S/VWV09wbmIyocG1nH4/FGQf8+AU7ajFizG+ODhfJY0xEOag1E5cwXqrM4ULu6HBSAkLDNBA85m8qi/UAd6INyel0DzwfANvjz34VZOLMX+rydyXoKhSpKoBlip1eHdUdzOM4HtlnemIZhMkgofNjxbFjRNwPclizwWJuF0I0Xj1jwT8wR4X7wWvPO9JgxgR6CixveZRt/is5IVgKl/UeqHCzS/a5tYatoF0o35byC0E2ehOJGCBw==</ds:SignatureValue><KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><X509Data><X509Certificate>MIIC4jCCAcqgAwIBAgIQQNXrmzhLN4VGlUXDYCRT3zANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE0MTAyODAwMDAwMFoXDTE2MTAyNzAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALyKs/uPhEf7zVizjfcr/ISGFe9+yUOqwpel38zgutvLHmFD39E2hpPdQhcXn4c4dt1fU5KvkbcDdVbP8+e4TvNpJMy/nEB2V92zCQ/hhBjilwhF1ETe1TMmVjALs0KFvbxW9ZN3EdUVvxFvz/gvG29nQhl4QWKj3x8opr89lmq14Z7T0mzOV8kub+cgsOU/1bsKqrIqN1fMKKFhjKaetctdjYTfGzVQ0AJAzzbtg0/Q1wdYNAnhSDafygEv6kNiquk0r0RyasUUevEXs2LY3vSgKsKseI8ZZlQEMtE9/k/iAG7JNcEbVg53YTurNTrPnXJOU88mf3TToX14HpYsS1ECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAfolx45w0i8CdAUjjeAaYdhG9+NDHxop0UvNOqlGqYJexqPLuvX8iyUaYxNGzZxFgGI3GpKfmQP2JQWQ1E5JtY/n8iNLOKRMwqkuxSCKJxZJq4Sl/m/Yv7TS1P5LNgAj8QLCypxsWrTAmq2HSpkeSk4JBtsYxX6uhbGM/K1sEktKybVTHu22/7TmRqWTmOUy9wQvMjJb2IXdMGLG3hVntN/WWcs5w8vbt1i8Kk6o19W2MjZ95JaECKjBDYRlhG1KmSBtrsKsCBQoBzwH/rXfksTO9JoUYLXiW0IppB7DhNH4PJ5hZI91R8rR0H3/bKkLSuDaKLWSqMhozdhXsIIKvJQ==</X509Certificate></X509Data></KeyInfo></ds:Signature><RoleDescriptor xsi:type=\"fed:SecurityTokenServiceType\" protocolSupportEnumeration=\"http://docs.oasis-open.org/wsfed/federation/200706\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:fed=\"http://docs.oasis-open.org/wsfed/federation/200706\"><KeyDescriptor use=\"signing\"><KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><X509Data><X509Certificate>MIIDPjCCAiqgAwIBAgIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTQwMTAxMDcwMDAwWhcNMTYwMTAxMDcwMDAwWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS/AHsBeQPqYygfYVJL6/EgzVuwRk5txr9e3n1uml94fLyq/AXbwo9yAduf4dCHTP8CWR1dnDR+Qnz/4PYlWVEuuHHONOw/blbfdMjhY+C/BYM2E3pRxbohBb3x//CfueV7ddz2LYiH3wjz0QS/7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd/GTgWN8A+6SN1r4hzpjFKFLbZnBt77ACSiYx+IHK4Mp+NaVEi5wQtSsjQtI++XsokxRDqYLwus1I1SihgbV/STTg5enufuwIDAQABo2IwYDBeBgNVHQEEVzBVgBDLebM6bK3BjWGqIBrBNFeNoS8wLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAA4IBAQCJ4JApryF77EKC4zF5bUaBLQHQ1PNtA1uMDbdNVGKCmSf8M65b8h0NwlIjGGGy/unK8P6jWFdm5IlZ0YPTOgzcRZguXDPj7ajyvlVEQ2K2ICvTYiRQqrOhEhZMSSZsTKXFVwNfW6ADDkN3bvVOVbtpty+nBY5UqnI7xbcoHLZ4wYD251uj5+lo13YLnsVrmQ16NCBYq2nQFNPuNJw6t3XUbwBHXpF46aLT1/eGf/7Xx6iy8yPJX4DyrpFTutDz882RWofGEO5t4Cw+zZg70dJ/hH/ODYRMorfXEW+8uKmXMKmX2wyxMKvfiPbTy5LmAU8Jvjs2tLg4rOBcXWLAIarZ</X509Certificate></X509Data></KeyInfo></KeyDescriptor><KeyDescriptor use=\"signing\"><KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><X509Data><X509Certificate>MIIC4jCCAcqgAwIBAgIQQNXrmzhLN4VGlUXDYCRT3zANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE0MTAyODAwMDAwMFoXDTE2MTAyNzAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALyKs/uPhEf7zVizjfcr/ISGFe9+yUOqwpel38zgutvLHmFD39E2hpPdQhcXn4c4dt1fU5KvkbcDdVbP8+e4TvNpJMy/nEB2V92zCQ/hhBjilwhF1ETe1TMmVjALs0KFvbxW9ZN3EdUVvxFvz/gvG29nQhl4QWKj3x8opr89lmq14Z7T0mzOV8kub+cgsOU/1bsKqrIqN1fMKKFhjKaetctdjYTfGzVQ0AJAzzbtg0/Q1wdYNAnhSDafygEv6kNiquk0r0RyasUUevEXs2LY3vSgKsKseI8ZZlQEMtE9/k/iAG7JNcEbVg53YTurNTrPnXJOU88mf3TToX14HpYsS1ECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAfolx45w0i8CdAUjjeAaYdhG9+NDHxop0UvNOqlGqYJexqPLuvX8iyUaYxNGzZxFgGI3GpKfmQP2JQWQ1E5JtY/n8iNLOKRMwqkuxSCKJxZJq4Sl/m/Yv7TS1P5LNgAj8QLCypxsWrTAmq2HSpkeSk4JBtsYxX6uhbGM/K1sEktKybVTHu22/7TmRqWTmOUy9wQvMjJb2IXdMGLG3hVntN/WWcs5w8vbt1i8Kk6o19W2MjZ95JaECKjBDYRlhG1KmSBtrsKsCBQoBzwH/rXfksTO9JoUYLXiW0IppB7DhNH4PJ5hZI91R8rR0H3/bKkLSuDaKLWSqMhozdhXsIIKvJQ==</X509Certificate></X509Data></KeyInfo></KeyDescriptor><fed:ClaimTypesOffered><auth:ClaimType Uri=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Name</auth:DisplayName><auth:Description>The mutable display name of the user.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Subject</auth:DisplayName><auth:Description>An immutable, globally unique, non-reusable identifier of the user that is unique to the application for which a token is issued.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Given Name</auth:DisplayName><auth:Description>First name of the user.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Surname</auth:DisplayName><auth:Description>Last name of the user.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/identity/claims/displayname\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Display Name</auth:DisplayName><auth:Description>Display name of the user.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/identity/claims/nickname\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Nick Name</auth:DisplayName><auth:Description>Nick name of the user.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Authentication Instant</auth:DisplayName><auth:Description>The time (UTC) when the user is authenticated to Windows Azure Active Directory.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Authentication Method</auth:DisplayName><auth:Description>The method that Windows Azure Active Directory uses to authenticate users.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/identity/claims/objectidentifier\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>ObjectIdentifier</auth:DisplayName><auth:Description>Primary identifier for the user in the directory. Immutable, globally unique, non-reusable.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/identity/claims/tenantid\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>TenantId</auth:DisplayName><auth:Description>Identifier for the user's tenant.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/identity/claims/identityprovider\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>IdentityProvider</auth:DisplayName><auth:Description>Identity provider for the user.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Email</auth:DisplayName><auth:Description>Email address of the user.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/ws/2008/06/identity/claims/groups\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Groups</auth:DisplayName><auth:Description>Groups of the user.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/identity/claims/accesstoken\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>External Access Token</auth:DisplayName><auth:Description>Access token issued by external identity provider.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>External Access Token Expiration</auth:DisplayName><auth:Description>UTC expiration time of access token issued by external identity provider.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/identity/claims/openid2_id\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>External OpenID 2.0 Identifier</auth:DisplayName><auth:Description>OpenID 2.0 identifier issued by external identity provider.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/claims/groups.link\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>GroupsOverageClaim</auth:DisplayName><auth:Description>Issued when number of user's group claims exceeds return limit.</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/ws/2008/06/identity/claims/role\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>Role Claim</auth:DisplayName><auth:Description>Roles that the user or Service Principal is attached to</auth:Description></auth:ClaimType><auth:ClaimType Uri=\"http://schemas.microsoft.com/ws/2008/06/identity/claims/wids\" Optional=\"true\" xmlns:auth=\"http://docs.oasis-open.org/wsfed/authorization/200706\"><auth:DisplayName>RoleTemplate Id Claim</auth:DisplayName><auth:Description>Role template id of the Built-in Directory Roles that the user is a member of</auth:Description></auth:ClaimType></fed:ClaimTypesOffered><fed:SecurityTokenServiceEndpoint><EndpointReference xmlns=\"http://www.w3.org/2005/08/addressing\"><Address>https://login.windows.net/8bd6e98d-e212-4022-b13f-a244fab4c253/wsfed</Address></EndpointReference></fed:SecurityTokenServiceEndpoint><fed:PassiveRequestorEndpoint><EndpointReference xmlns=\"http://www.w3.org/2005/08/addressing\"><Address>https://login.windows.net/8bd6e98d-e212-4022-b13f-a244fab4c253/wsfed</Address></EndpointReference></fed:PassiveRequestorEndpoint></RoleDescriptor><RoleDescriptor xsi:type=\"fed:ApplicationServiceType\" protocolSupportEnumeration=\"http://docs.oasis-open.org/wsfed/federation/200706\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:fed=\"http://docs.oasis-open.org/wsfed/federation/200706\"><KeyDescriptor use=\"signing\"><KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><X509Data><X509Certificate>MIIDPjCCAiqgAwIBAgIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTQwMTAxMDcwMDAwWhcNMTYwMTAxMDcwMDAwWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS/AHsBeQPqYygfYVJL6/EgzVuwRk5txr9e3n1uml94fLyq/AXbwo9yAduf4dCHTP8CWR1dnDR+Qnz/4PYlWVEuuHHONOw/blbfdMjhY+C/BYM2E3pRxbohBb3x//CfueV7ddz2LYiH3wjz0QS/7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd/GTgWN8A+6SN1r4hzpjFKFLbZnBt77ACSiYx+IHK4Mp+NaVEi5wQtSsjQtI++XsokxRDqYLwus1I1SihgbV/STTg5enufuwIDAQABo2IwYDBeBgNVHQEEVzBVgBDLebM6bK3BjWGqIBrBNFeNoS8wLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAA4IBAQCJ4JApryF77EKC4zF5bUaBLQHQ1PNtA1uMDbdNVGKCmSf8M65b8h0NwlIjGGGy/unK8P6jWFdm5IlZ0YPTOgzcRZguXDPj7ajyvlVEQ2K2ICvTYiRQqrOhEhZMSSZsTKXFVwNfW6ADDkN3bvVOVbtpty+nBY5UqnI7xbcoHLZ4wYD251uj5+lo13YLnsVrmQ16NCBYq2nQFNPuNJw6t3XUbwBHXpF46aLT1/eGf/7Xx6iy8yPJX4DyrpFTutDz882RWofGEO5t4Cw+zZg70dJ/hH/ODYRMorfXEW+8uKmXMKmX2wyxMKvfiPbTy5LmAU8Jvjs2tLg4rOBcXWLAIarZ</X509Certificate></X509Data></KeyInfo></KeyDescriptor><KeyDescriptor use=\"signing\"><KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><X509Data><X509Certificate>MIIC4jCCAcqgAwIBAgIQQNXrmzhLN4VGlUXDYCRT3zANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE0MTAyODAwMDAwMFoXDTE2MTAyNzAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALyKs/uPhEf7zVizjfcr/ISGFe9+yUOqwpel38zgutvLHmFD39E2hpPdQhcXn4c4dt1fU5KvkbcDdVbP8+e4TvNpJMy/nEB2V92zCQ/hhBjilwhF1ETe1TMmVjALs0KFvbxW9ZN3EdUVvxFvz/gvG29nQhl4QWKj3x8opr89lmq14Z7T0mzOV8kub+cgsOU/1bsKqrIqN1fMKKFhjKaetctdjYTfGzVQ0AJAzzbtg0/Q1wdYNAnhSDafygEv6kNiquk0r0RyasUUevEXs2LY3vSgKsKseI8ZZlQEMtE9/k/iAG7JNcEbVg53YTurNTrPnXJOU88mf3TToX14HpYsS1ECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAfolx45w0i8CdAUjjeAaYdhG9+NDHxop0UvNOqlGqYJexqPLuvX8iyUaYxNGzZxFgGI3GpKfmQP2JQWQ1E5JtY/n8iNLOKRMwqkuxSCKJxZJq4Sl/m/Yv7TS1P5LNgAj8QLCypxsWrTAmq2HSpkeSk4JBtsYxX6uhbGM/K1sEktKybVTHu22/7TmRqWTmOUy9wQvMjJb2IXdMGLG3hVntN/WWcs5w8vbt1i8Kk6o19W2MjZ95JaECKjBDYRlhG1KmSBtrsKsCBQoBzwH/rXfksTO9JoUYLXiW0IppB7DhNH4PJ5hZI91R8rR0H3/bKkLSuDaKLWSqMhozdhXsIIKvJQ==</X509Certificate></X509Data></KeyInfo></KeyDescriptor><fed:TargetScopes><EndpointReference xmlns=\"http://www.w3.org/2005/08/addressing\"><Address>https://sts.windows.net/8bd6e98d-e212-4022-b13f-a244fab4c253/</Address></EndpointReference></fed:TargetScopes><fed:ApplicationServiceEndpoint><EndpointReference xmlns=\"http://www.w3.org/2005/08/addressing\"><Address>https://login.windows.net/8bd6e98d-e212-4022-b13f-a244fab4c253/wsfed</Address></EndpointReference></fed:ApplicationServiceEndpoint><fed:PassiveRequestorEndpoint><EndpointReference xmlns=\"http://www.w3.org/2005/08/addressing\"><Address>https://login.windows.net/8bd6e98d-e212-4022-b13f-a244fab4c253/wsfed</Address></EndpointReference></fed:PassiveRequestorEndpoint></RoleDescriptor><IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"><KeyDescriptor use=\"signing\"><KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><X509Data><X509Certificate>MIIDPjCCAiqgAwIBAgIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTQwMTAxMDcwMDAwWhcNMTYwMTAxMDcwMDAwWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS/AHsBeQPqYygfYVJL6/EgzVuwRk5txr9e3n1uml94fLyq/AXbwo9yAduf4dCHTP8CWR1dnDR+Qnz/4PYlWVEuuHHONOw/blbfdMjhY+C/BYM2E3pRxbohBb3x//CfueV7ddz2LYiH3wjz0QS/7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd/GTgWN8A+6SN1r4hzpjFKFLbZnBt77ACSiYx+IHK4Mp+NaVEi5wQtSsjQtI++XsokxRDqYLwus1I1SihgbV/STTg5enufuwIDAQABo2IwYDBeBgNVHQEEVzBVgBDLebM6bK3BjWGqIBrBNFeNoS8wLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAA4IBAQCJ4JApryF77EKC4zF5bUaBLQHQ1PNtA1uMDbdNVGKCmSf8M65b8h0NwlIjGGGy/unK8P6jWFdm5IlZ0YPTOgzcRZguXDPj7ajyvlVEQ2K2ICvTYiRQqrOhEhZMSSZsTKXFVwNfW6ADDkN3bvVOVbtpty+nBY5UqnI7xbcoHLZ4wYD251uj5+lo13YLnsVrmQ16NCBYq2nQFNPuNJw6t3XUbwBHXpF46aLT1/eGf/7Xx6iy8yPJX4DyrpFTutDz882RWofGEO5t4Cw+zZg70dJ/hH/ODYRMorfXEW+8uKmXMKmX2wyxMKvfiPbTy5LmAU8Jvjs2tLg4rOBcXWLAIarZ</X509Certificate></X509Data></KeyInfo></KeyDescriptor><KeyDescriptor use=\"signing\"><KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><X509Data><X509Certificate>MIIC4jCCAcqgAwIBAgIQQNXrmzhLN4VGlUXDYCRT3zANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE0MTAyODAwMDAwMFoXDTE2MTAyNzAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALyKs/uPhEf7zVizjfcr/ISGFe9+yUOqwpel38zgutvLHmFD39E2hpPdQhcXn4c4dt1fU5KvkbcDdVbP8+e4TvNpJMy/nEB2V92zCQ/hhBjilwhF1ETe1TMmVjALs0KFvbxW9ZN3EdUVvxFvz/gvG29nQhl4QWKj3x8opr89lmq14Z7T0mzOV8kub+cgsOU/1bsKqrIqN1fMKKFhjKaetctdjYTfGzVQ0AJAzzbtg0/Q1wdYNAnhSDafygEv6kNiquk0r0RyasUUevEXs2LY3vSgKsKseI8ZZlQEMtE9/k/iAG7JNcEbVg53YTurNTrPnXJOU88mf3TToX14HpYsS1ECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAfolx45w0i8CdAUjjeAaYdhG9+NDHxop0UvNOqlGqYJexqPLuvX8iyUaYxNGzZxFgGI3GpKfmQP2JQWQ1E5JtY/n8iNLOKRMwqkuxSCKJxZJq4Sl/m/Yv7TS1P5LNgAj8QLCypxsWrTAmq2HSpkeSk4JBtsYxX6uhbGM/K1sEktKybVTHu22/7TmRqWTmOUy9wQvMjJb2IXdMGLG3hVntN/WWcs5w8vbt1i8Kk6o19W2MjZ95JaECKjBDYRlhG1KmSBtrsKsCBQoBzwH/rXfksTO9JoUYLXiW0IppB7DhNH4PJ5hZI91R8rR0H3/bKkLSuDaKLWSqMhozdhXsIIKvJQ==</X509Certificate></X509Data></KeyInfo></KeyDescriptor><SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://login.windows.net/8bd6e98d-e212-4022-b13f-a244fab4c253/saml2\" /><SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://login.windows.net/8bd6e98d-e212-4022-b13f-a244fab4c253/saml2\" /><SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" Location=\"https://login.windows.net/8bd6e98d-e212-4022-b13f-a244fab4c253/saml2\" /></IDPSSODescriptor></EntityDescriptor>"
  },
  {
    "path": "test/utils-tests.spec.ts",
    "content": "import * as fs from \"fs\";\nimport * as utils from \"../src/utils\";\nimport { expect } from \"chai\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as xpath from \"xpath\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\ndescribe(\"Utils tests\", function () {\n  describe(\"derToPem\", function () {\n    it(\"will return a normalized PEM format when given an non-normalized PEM format\", function () {\n      const normalizedPem = fs.readFileSync(\"./test/static/client_public.pem\", \"latin1\");\n      const pemAsArray = normalizedPem.trim().split(\"\\n\");\n      const base64String = pemAsArray.slice(1, -1).join(\"\");\n      const nonNormalizedPem = `${pemAsArray[0]}\\n${base64String}\\n${\n        pemAsArray[pemAsArray.length - 1]\n      }`;\n\n      expect(utils.derToPem(nonNormalizedPem)).to.equal(normalizedPem);\n    });\n\n    it(\"will return a normalized PEM format when given a base64 string\", function () {\n      const normalizedPem = fs.readFileSync(\"./test/static/client_public.pem\", \"latin1\");\n      const pemAsArray = normalizedPem.trim().split(\"\\n\");\n      const base64String = pemAsArray.slice(1, -1).join(\"\");\n\n      expect(utils.derToPem(base64String, \"CERTIFICATE\")).to.equal(normalizedPem);\n    });\n\n    it(\"will throw if the format is neither PEM nor DER\", function () {\n      expect(() => utils.derToPem(\"not a pem\")).to.throw();\n    });\n\n    it(\"will return a normalized PEM format when given a DER Buffer\", function () {\n      const normalizedPem = fs.readFileSync(\"./test/static/client_public.pem\", \"latin1\");\n      const derBuffer = fs.readFileSync(\"./test/static/client_public.der\");\n\n      expect(utils.derToPem(derBuffer, \"CERTIFICATE\")).to.equal(normalizedPem);\n    });\n\n    it(\"will return a normalized PEM format when given a base64 string with line breaks\", function () {\n      const normalizedPem = fs.readFileSync(\"./test/static/client_public.pem\", \"latin1\");\n      const base64String = fs.readFileSync(\"./test/static/client_public.der\", \"base64\");\n\n      expect(utils.derToPem(base64String, \"CERTIFICATE\")).to.equal(normalizedPem);\n    });\n\n    it(\"will return a normalized PEM format when given a base64 string with line breaks and spaces at the line breaks\", function () {\n      const xml = new xmldom.DOMParser().parseFromString(\n        fs.readFileSync(\"./test/static/keyinfo - pretty-printed.xml\", \"latin1\"),\n      );\n      const cert = xpath.select1(\".//*[local-name(.)='X509Certificate']\", xml);\n      isDomNode.assertIsNodeLike(cert);\n\n      const normalizedPem = fs.readFileSync(\"./test/static/keyinfo.pem\", \"latin1\");\n\n      expect(utils.derToPem(cert.textContent ?? \"\", \"CERTIFICATE\")).to.equal(normalizedPem);\n    });\n\n    it(\"will throw if the DER string is not base64 encoded\", function () {\n      expect(() => utils.derToPem(\"not base64\", \"CERTIFICATE\")).to.throw();\n    });\n\n    it(\"will throw if the PEM label is not provided\", function () {\n      const derBuffer = fs.readFileSync(\"./test/static/client_public.der\");\n      expect(() => utils.derToPem(derBuffer)).to.throw();\n    });\n  });\n\n  describe(\"pemToDer\", function () {\n    it(\"will return a Buffer of binary DER when given a normalized PEM format\", function () {\n      const pem = fs.readFileSync(\"./test/static/client_public.pem\", \"latin1\");\n      const derBuffer = fs.readFileSync(\"./test/static/client_public.der\");\n\n      const result = utils.pemToDer(pem);\n      expect(result).to.be.instanceOf(Buffer);\n      expect(result).to.deep.equal(derBuffer);\n    });\n\n    it(\"will throw if the format is not PEM\", function () {\n      expect(() => utils.pemToDer(\"not a pem\")).to.throw();\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators/XmlCryptoJava/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <name>XML Crypto Java Tests</name>\n    <groupId>org.nodejs</groupId>\n    <artifactId>xml-crypto-java</artifactId>\n    <version>1.0.0-SNAPSHOT</version>\n    <packaging>jar</packaging>\n    <inceptionYear>2015</inceptionYear>\n    <licenses>\n        <license>\n            <name>MIT License</name>\n            <url>http://www.opensource.org/licenses/mit-license.php</url>\n        </license>\n    </licenses>\n    <developers>\n        <developer>\n            <id>fcorneli</id>\n            <name>Frank Cornelis</name>\n            <email>info@e-contract.be</email>\n        </developer>\n    </developers>\n    <dependencies>\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <version>4.13.1</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n            <version>1.7.12</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-log4j12</artifactId>\n            <version>1.7.12</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>log4j</groupId>\n            <artifactId>log4j</artifactId>\n            <version>1.2.17</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>commons-io</groupId>\n            <artifactId>commons-io</artifactId>\n            <version>2.7</version>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <version>3.3</version>\n                <configuration>\n                    <source>1.7</source>\n                    <target>1.7</target>\n                    <encoding>UTF-8</encoding>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n    </properties>\n</project>\n"
  },
  {
    "path": "test/validators/XmlCryptoJava/src/test/java/org/nodejs/xmlcrypto/HMACTest.java",
    "content": "package org.nodejs.xmlcrypto;\n\nimport java.io.File;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport javax.crypto.KeyGenerator;\nimport javax.crypto.SecretKey;\nimport javax.xml.crypto.dsig.CanonicalizationMethod;\nimport javax.xml.crypto.dsig.DigestMethod;\nimport javax.xml.crypto.dsig.Reference;\nimport javax.xml.crypto.dsig.SignatureMethod;\nimport javax.xml.crypto.dsig.SignedInfo;\nimport javax.xml.crypto.dsig.Transform;\nimport javax.xml.crypto.dsig.XMLSignature;\nimport javax.xml.crypto.dsig.XMLSignatureFactory;\nimport javax.xml.crypto.dsig.dom.DOMSignContext;\nimport javax.xml.crypto.dsig.keyinfo.KeyInfo;\nimport javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;\nimport javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;\nimport javax.xml.parsers.DocumentBuilder;\nimport javax.xml.parsers.DocumentBuilderFactory;\nimport javax.xml.transform.Transformer;\nimport javax.xml.transform.TransformerFactory;\nimport javax.xml.transform.dom.DOMSource;\nimport javax.xml.transform.stream.StreamResult;\nimport org.apache.commons.io.FileUtils;\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.w3c.dom.Document;\nimport org.w3c.dom.Element;\nimport org.w3c.dom.Node;\n\npublic class HMACTest {\n    \n    public static final String NamespaceSpecNS = \"http://www.w3.org/2000/xmlns/\";\n    \n    private static final Logger LOGGER = LoggerFactory\n            .getLogger(HMACTest.class);\n    \n    @Test\n    public void testCreateHMACSignature() throws Exception {\n        // generate key\n        KeyGenerator keyGenerator = KeyGenerator.getInstance(\"HmacSHA1\");\n        SecretKey secretKey = keyGenerator.generateKey();\n\n        // generate DOM document\n        DocumentBuilderFactory documentBuilderFactory\n                = DocumentBuilderFactory.newInstance();\n        documentBuilderFactory.setNamespaceAware(true);\n        DocumentBuilder documentBuilder = documentBuilderFactory\n                .newDocumentBuilder();\n        Document document = documentBuilder.newDocument();\n        Element rootElement = document.createElementNS(\"urn:test\",\n                \"test:Root\");\n        rootElement.setAttributeNS(NamespaceSpecNS,\n                \"xmlns:test\", \"urn:test\");\n        document.appendChild(rootElement);\n        \n        XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory\n                .getInstance(\"DOM\");\n\n        // XML Signature references\n        List<Reference> references = new LinkedList<>();\n        List<Transform> transforms = new LinkedList<>();\n        Transform envTransform = xmlSignatureFactory.newTransform(\n                CanonicalizationMethod.ENVELOPED,\n                (C14NMethodParameterSpec) null);\n        transforms.add(envTransform);\n        Transform exclTransform = xmlSignatureFactory.newTransform(\n                CanonicalizationMethod.EXCLUSIVE,\n                (C14NMethodParameterSpec) null);\n        transforms.add(exclTransform);\n        Reference reference = xmlSignatureFactory.newReference(\"\",\n                xmlSignatureFactory.newDigestMethod(DigestMethod.SHA256,\n                        null), transforms, null, null);\n        references.add(reference);\n\n        // XML Signature SignedInfo\n        SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(\n                xmlSignatureFactory.newCanonicalizationMethod(\n                        CanonicalizationMethod.EXCLUSIVE,\n                        (C14NMethodParameterSpec) null),\n                xmlSignatureFactory.newSignatureMethod(\n                        SignatureMethod.HMAC_SHA1,\n                        null), references);\n\n        // XML Signature KeyInfo\n        KeyInfoFactory keyInfoFactory\n                = xmlSignatureFactory.getKeyInfoFactory();\n        KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections\n                .singletonList(keyInfoFactory.newKeyName(\"some-key-name\")));\n        \n        Element parentElement = document.getDocumentElement();\n        DOMSignContext domSignContext = new DOMSignContext(\n                secretKey, parentElement);\n        domSignContext.setDefaultNamespacePrefix(\"ds\");\n        XMLSignature xmlSignature = xmlSignatureFactory.newXMLSignature(\n                signedInfo, keyInfo);\n        xmlSignature.sign(domSignContext);\n        \n        File tmpFile = File.createTempFile(\"xml-signature-hmac-\", \".xml\");\n        LOGGER.debug(\"XML signature file: {}\", tmpFile.getAbsolutePath());\n        toFile(document, tmpFile);\n        \n        File tmpKeyFile = File.createTempFile(\"hmac-\", \".key\");\n        FileUtils.writeByteArrayToFile(tmpKeyFile, secretKey.getEncoded());\n        LOGGER.debug(\"key file: {}\", tmpKeyFile.getAbsolutePath());\n        \n    }\n    \n    private void toFile(Node node, File file) throws Exception {\n        TransformerFactory transformerFactory = TransformerFactory\n                .newInstance();\n        Transformer transformer = transformerFactory.newTransformer();\n        transformer.transform(new DOMSource(node), new StreamResult(file));\n    }\n}\n"
  },
  {
    "path": "test/validators/XmlCryptoJava/src/test/resources/log4j.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">\n<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\"\n                     debug=\"false\">\n    <appender name=\"CONSOLE\" class=\"org.apache.log4j.ConsoleAppender\">\n        <param name=\"Target\" value=\"System.out\" />\n        <param name=\"Threshold\" value=\"DEBUG\" />\n        <layout class=\"org.apache.log4j.PatternLayout\">\n            <param name=\"ConversionPattern\"\n                   value=\"%-5p [%c{1}] %m%n\" />\n        </layout>\n    </appender>\n    <root>\n        <appender-ref ref=\"CONSOLE\" />\n    </root>\n</log4j:configuration>"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities/Program.cs",
    "content": "//\n// This example signs an XML file using an\n// envelope signature. It then verifies the \n// signed XML.\n//\nusing System;\nusing System.Security.Cryptography;\nusing System.Security.Cryptography.X509Certificates;\nusing System.Security.Cryptography.Xml;\nusing System.Text;\nusing System.Xml;\nusing System.IO;\nusing System.Reflection;\n\npublic class SignVerifyEnvelope\n{\n\n    public static void Main(String[] args)\n    {\n        var exe = Assembly.GetExecutingAssembly().Location;\n        var folder = Path.GetDirectoryName(exe);\n        var pfx = Path.Combine(folder, \"ClientPrivate.pfx\");\n        var c = new X509Certificate2(File.ReadAllBytes(pfx), \"wse2qs\");\n\n        if (args[0] == \"verify\")\n        {\n            Console.WriteLine(\"verifying signature...\");\n            var file = Path.Combine(folder, \"SignedExample.xml\");\n            bool b = VerifyXmlFile(file, (RSA)c.PublicKey.Key);\n            Console.WriteLine(\"signature is \" + (b ? \"valid\" : \"not valid!\"));\n            if (!b) Environment.Exit(-1);\n        }\n        else if (args[0] == \"sign\")\n        {\n            Console.WriteLine(\"generating signature...\");\n            var xmlFile = Path.Combine(folder, \"Example.xml\");\n            var sigFile = Path.Combine(folder, \"signedExample.xml\");\n            CreateSomeXml(xmlFile);\n            SignXmlFile(xmlFile, sigFile, (RSA)c.PrivateKey);\n            Console.WriteLine(\"done\");\n        }\n    }\n\n    // Sign an XML file and save the signature in a new file. This method does not  \n    // save the public key within the XML file.  This file cannot be verified unless  \n    // the verifying code has the key with which it was signed.\n    public static void SignXmlFile(string FileName, string SignedFileName, RSA Key)\n    {\n        // Create a new XML document.\n        XmlDocument doc = new XmlDocument();\n\n        // Load the passed XML file using its name.\n        doc.Load(new XmlTextReader(FileName));\n\n        // Create a SignedXml object.\n        SignedXml signedXml = new SignedXml(doc);\n\n        // Add the key to the SignedXml document. \n        signedXml.SigningKey = Key;\n\n        // Create a reference to be signed.\n        Reference reference = new Reference();\n        reference.Uri = \"\";\n\n        // Add an enveloped transformation to the reference.\n        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();\n        reference.AddTransform(env);\n\n        // Add the reference to the SignedXml object.\n        signedXml.AddReference(reference);\n\n        // Compute the signature.\n        signedXml.ComputeSignature();\n\n        // Get the XML representation of the signature and save\n        // it to an XmlElement object.\n        XmlElement xmlDigitalSignature = signedXml.GetXml();\n\n        // Append the element to the XML document.\n        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));\n\n        if (doc.FirstChild is XmlDeclaration)\n        {\n            doc.RemoveChild(doc.FirstChild);\n        }\n\n        // Save the signed XML document to a file specified\n        // using the passed string.\n        XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));\n        doc.WriteTo(xmltw);\n        xmltw.Close();\n    }\n\n    // Verify the signature of an XML file against an asymetric \n    // algorithm and return the result.\n    public static Boolean VerifyXmlFile(String Name, RSA Key)\n    {\n        // Create a new XML document.\n        XmlDocument xmlDocument = new XmlDocument();\n\n        // Load the passed XML file into the document. \n        xmlDocument.Load(Name);\n\n        // Create a new SignedXml object and pass it\n        // the XML document class.\n        SignedXml signedXml = new SignedXml(xmlDocument);\n\n        // Find the \"Signature\" node and create a new\n        // XmlNodeList object.\n        XmlNodeList nodeList = xmlDocument.GetElementsByTagName(\"Signature\");\n\n        // Load the signature node.\n        signedXml.LoadXml((XmlElement)nodeList[0]);\n\n        // Check the signature and return the result.\n        return signedXml.CheckSignature(Key);\n    }\n\n\n    // Create example data to sign.\n    public static void CreateSomeXml(string FileName)\n    {\n        // Create a new XmlDocument object.\n        XmlDocument document = new XmlDocument();\n\n        // Create a new XmlNode object.\n        XmlNode node = document.CreateNode(XmlNodeType.Element, \"\", \"MyElement\", \"samples\");\n\n        // Add some text to the node.\n        node.InnerText = \"Example text to be signed.\";\n\n        // Append the node to the document.\n        document.AppendChild(node);\n\n        // Save the XML document to the file name specified.\n        XmlTextWriter xmltw = new XmlTextWriter(FileName, new UTF8Encoding(false));\n        document.WriteTo(xmltw);\n        xmltw.Close();\n    }\n}\n"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Information about an assembly is controlled through the following \n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n[assembly: AssemblyTitle(\"XmlCryptoUtilities\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"Microsoft\")]\n[assembly: AssemblyProduct(\"XmlCryptoUtilities\")]\n[assembly: AssemblyCopyright(\"Copyright © Microsoft 2012\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n// Setting ComVisible to false makes the types in this assembly not visible \n// to COM components.  If you need to access a type in this assembly from \n// COM, set the ComVisible attribute to true on that type.\n[assembly: ComVisible(false)]\n\n// The following GUID is for the ID of the typelib if this project is exposed to COM\n[assembly: Guid(\"8305ddd7-a079-45b3-8db1-83728172475e\")]\n\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version \n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Build and Revision Numbers \n// by using the '*' as shown below:\n// [assembly: AssemblyVersion(\"1.0.*\")]\n[assembly: AssemblyVersion(\"1.0.0.0\")]\n[assembly: AssemblyFileVersion(\"1.0.0.0\")]\n"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities/ValidateSignature.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">x86</Platform>\n    <ProductVersion>8.0.30703</ProductVersion>\n    <SchemaVersion>2.0</SchemaVersion>\n    <ProjectGuid>{CAA449E3-720D-4CD6-B03B-94991E11FF25}</ProjectGuid>\n    <OutputType>Exe</OutputType>\n    <AppDesignerFolder>Properties</AppDesignerFolder>\n    <RootNamespace>XmlCryptoUtilities</RootNamespace>\n    <AssemblyName>XmlCryptoUtilities</AssemblyName>\n    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>\n    <TargetFrameworkProfile>Client</TargetFrameworkProfile>\n    <FileAlignment>512</FileAlignment>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|x86' \">\n    <PlatformTarget>x86</PlatformTarget>\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>false</Optimize>\n    <OutputPath>bin\\Debug\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x86' \">\n    <PlatformTarget>x86</PlatformTarget>\n    <DebugType>pdbonly</DebugType>\n    <Optimize>true</Optimize>\n    <OutputPath>bin\\Release\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <ItemGroup>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.Core\" />\n    <Reference Include=\"System.Security\" />\n    <Reference Include=\"System.Xml.Linq\" />\n    <Reference Include=\"System.Data.DataSetExtensions\" />\n    <Reference Include=\"Microsoft.CSharp\" />\n    <Reference Include=\"System.Data\" />\n    <Reference Include=\"System.Xml\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"Program.cs\" />\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\n    <Compile Include=\"utilities.cs\" />\n  </ItemGroup>\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\n  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \n       Other similar extension points exist, see Microsoft.Common.targets.\n  <Target Name=\"BeforeBuild\">\n  </Target>\n  <Target Name=\"AfterBuild\">\n  </Target>\n  -->\n</Project>"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities/bin/Debug/Example.xml",
    "content": "<MyElement xmlns=\"samples\">Example text to be signed.</MyElement>"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities/bin/Debug/XmlCryptoUtilities.vshost.exe.manifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n  <assemblyIdentity version=\"1.0.0.0\" name=\"MyApplication.app\"/>\n  <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">\n    <security>\n      <requestedPrivileges xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n        <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"/>\n      </requestedPrivileges>\n    </security>\n  </trustInfo>\n</assembly>\n"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities/bin/Debug/signedExample.xml",
    "content": "<library><book Id=\"_0\"><name>Harry Potter</name><author id=\"123456789\"><firstName>Joanne K</firstName><lastName>Rowling</lastName></author></book><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#_0\"><Transforms><Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>VXkWV6BNrUKqdmwcxhIgRa86HUI=</DigestValue></Reference></SignedInfo><SignatureValue>Y71mpTZ0Ba5qED2TxHLp34tq8Pa9X41M5PuABwPq7r2GaL5Ib28ELkhMtnZuZboO50bxh/9fwK6DPApP92zUuOTZi4htlPcGJRP5kvHznbwzvq7aO5FWAcpUTX+yMrlERIutiJi7mjChX+mIKF5/4DK66JfIlY5vlq61TX2gaJw=</SignatureValue></Signature></library>"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities/obj/x86/Debug/ValidateSignature.csproj.FileListAbsolute.txt",
    "content": "C:\\Users\\naveh\\Documents\\features\\projects\\xml-crypto\\test\\validators\\XmlCryptoUtilities\\XmlCryptoUtilities\\bin\\Debug\\XmlCryptoUtilities.exe\nC:\\Users\\naveh\\Documents\\features\\projects\\xml-crypto\\test\\validators\\XmlCryptoUtilities\\XmlCryptoUtilities\\bin\\Debug\\XmlCryptoUtilities.pdb\nC:\\Users\\naveh\\Documents\\features\\projects\\xml-crypto\\test\\validators\\XmlCryptoUtilities\\XmlCryptoUtilities\\obj\\x86\\Debug\\ResolveAssemblyReference.cache\nC:\\Users\\naveh\\Documents\\features\\projects\\xml-crypto\\test\\validators\\XmlCryptoUtilities\\XmlCryptoUtilities\\obj\\x86\\Debug\\XmlCryptoUtilities.exe\nC:\\Users\\naveh\\Documents\\features\\projects\\xml-crypto\\test\\validators\\XmlCryptoUtilities\\XmlCryptoUtilities\\obj\\x86\\Debug\\XmlCryptoUtilities.pdb\n"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities/program-repro-misc-validation-and-canon.cs",
    "content": "//\n// This example signs an XML file using an\n// envelope signature. It then verifies the \n// signed XML.\n//\nusing System;\nusing System.Security.Cryptography;\nusing System.Security.Cryptography.X509Certificates;\nusing System.Security.Cryptography.Xml;\nusing System.Text;\nusing System.Xml;\nusing System.IO;\nusing System.Reflection;\n\npublic class SignVerifyEnvelope\n{\n    public sealed class RSAPKCS1SHA256SignatureDescription : SignatureDescription\n    {\n        public RSAPKCS1SHA256SignatureDescription()\n        {\n            base.KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName;\n            base.DigestAlgorithm = typeof(SHA256Managed).FullName;\n            base.FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName;\n            base.DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName;\n        }\n\n        public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)\n        {\n            if (key == null)\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n\n            RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);\n            deformatter.SetHashAlgorithm(\"SHA256\");\n            return deformatter;\n        }\n\n        public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)\n        {\n            if (key == null)\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n\n            RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);\n            formatter.SetHashAlgorithm(\"SHA256\");\n            return formatter;\n        }\n\n    }\n\n\n    static bool ValidateXml(XmlDocument receipt, X509Certificate2 certificate)\n    {\n        // Create the signed XML object.\n        SignedXml sxml = new SignedXml(receipt);\n\n        // Get the XML Signature node and load it into the signed XML object.\n        XmlNode dsig = receipt.GetElementsByTagName(\"Signature\", SignedXml.XmlDsigNamespaceUrl)[0];\n        if (dsig == null)\n        {\n            // If signature is not found return false\n            System.Console.WriteLine(\"Signature not found.\");\n            return false;\n        }\n\n        sxml.LoadXml((XmlElement)dsig);\n        \n        // Check the signature\n        bool isValid = sxml.CheckSignature(certificate, true);\n\n\n        FieldInfo field = sxml.GetType().GetField(\"m_signature\",\n                       BindingFlags.NonPublic |\n                       BindingFlags.Instance);\n\n        var sig = (Signature)field.GetValue(sxml);\n        var _ref = (Reference)sig.SignedInfo.References[0];\n\n        //var pre = Type.GetType(\"System.Security.Cryptography.Xml.Utils\").GetMethod(\"PreProcessDocumentInput\");\n        //pre.Invoke(null, new[] { });\n\n\n        var enveloped = (XmlDsigEnvelopedSignatureTransform)_ref.TransformChain[0];\n\n        enveloped.LoadInput(receipt);\n        var outputstream = enveloped.GetOutput();\n\n        var securityUrl = receipt.BaseURI;\n        var resolver = new XmlSecureResolver(new XmlUrlResolver(), securityUrl);\n        //TransformToOctetStream(Stream input, XmlResolver resolver, string baseUri)\n        MethodInfo trans = _ref.TransformChain.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)[2];\n        \n        var stream = trans.Invoke(_ref.TransformChain, new object[] {receipt, resolver, securityUrl});\n\n\n        var canontype = sig.GetType().Assembly.GetType(\"System.Security.Cryptography.Xml.CanonicalXml\");\n        var foo = Activator.CreateInstance(canontype, BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] {receipt, resolver}, null);\n        \n\n\n\n\n\n        MethodInfo method = _ref.GetType().GetMethod(\"CalculateHashValue\",\n                       BindingFlags.NonPublic |\n                       BindingFlags.Instance);\n\n        FieldInfo refs = sig.GetType().GetField(\"m_referencedItems\",\n                       BindingFlags.NonPublic |\n                       BindingFlags.Instance);\n        var refs1 = refs.GetValue(sig);\n\n        var res = method.Invoke(_ref, new [] {receipt, refs1});\n        var str = Convert.ToBase64String((byte[])res);\n\n        return isValid;\n    }\n\n\n    public static void Main(String[] args)\n    {\n\n\n        //calculate caninicalized xml\n        \n        var t = new XmlDsigEnvelopedSignatureTransform(false);\n        XmlDocument doc = new XmlDocument();\n        //doc.PreserveWhitespace = true;\n        doc.Load(@\"c:\\temp\\x.xml\");\n        t.LoadInput(doc);\n\n        \n        FieldInfo field = t.GetType().GetField(\"_signaturePosition\", \n                         BindingFlags.NonPublic |\n                         BindingFlags.Instance);\n\n\n        field.SetValue(t, 1);        \n        \n        var res = (XmlDocument)t.GetOutput();\n        var s = res.OuterXml;\n\n        var c14 = new XmlDsigC14NTransform();\n        c14.LoadInput(res);\n        var mem = (MemoryStream)c14.GetOutput();\n\n        var sha = new SHA256Managed();\n        \n        var byte1 = c14.GetDigestedOutput(new SHA256Managed());\n        var digest1 = Convert.ToBase64String(byte1);                \n        var byte2 = sha.ComputeHash(mem.ToArray());\n        var digest2 = Convert.ToBase64String(byte2);\n        \n\n        var s1 = System.Text.Encoding.UTF8.GetString(mem.ToArray());        \n        var byte3 = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(s1));\n        var digest3 = Convert.ToBase64String(byte3);\n\n        //return;\n        \n\n        \n        //validate signature        \n        \n        CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), \"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\");\n        XmlDocument xmlDoc = new XmlDocument();        \n        xmlDoc.Load(@\"c:\\temp\\x.xml\");\n        XmlNode node = xmlDoc.DocumentElement;\n        X509Certificate2 cert = new X509Certificate2(File.ReadAllBytes(@\"c:\\temp\\x.cer\"));\n        bool isValid = ValidateXml(xmlDoc, cert);        \n        //return;\n        \n\n        //calc hash\n        var sha1 = new SHA256Managed();\n        var b1 = sha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(@\"c:\\temp\\x_no_sig.xml\")));\n        var b64 = Convert.ToBase64String(b1);\n    }\n\n    // Sign an XML file and save the signature in a new file. This method does not  \n    // save the public key within the XML file.  This file cannot be verified unless  \n    // the verifying code has the key with which it was signed.\n    public static void SignXmlFile(string FileName, string SignedFileName, RSA Key)\n    {\n        // Create a new XML document.\n        XmlDocument doc = new XmlDocument();\n\n        // Load the passed XML file using its name.\n        doc.Load(new XmlTextReader(FileName));\n\n        // Create a SignedXml object.\n        SignedXml signedXml = new SignedXml(doc);\n\n        // Add the key to the SignedXml document. \n        signedXml.SigningKey = Key;\n\n        // Create a reference to be signed.\n        Reference reference = new Reference();\n        reference.Uri = \"\";\n\n        // Add an enveloped transformation to the reference.\n        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();\n        reference.AddTransform(env);\n\n        // Add the reference to the SignedXml object.\n        signedXml.AddReference(reference);\n\n        // Compute the signature.\n        signedXml.ComputeSignature();\n\n        // Get the XML representation of the signature and save\n        // it to an XmlElement object.\n        XmlElement xmlDigitalSignature = signedXml.GetXml();\n\n        // Append the element to the XML document.\n        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));\n\n        if (doc.FirstChild is XmlDeclaration)\n        {\n            doc.RemoveChild(doc.FirstChild);\n        }\n\n        // Save the signed XML document to a file specified\n        // using the passed string.\n        XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));\n        doc.WriteTo(xmltw);\n        xmltw.Close();\n    }\n\n    // Verify the signature of an XML file against an asymetric \n    // algorithm and return the result.\n    public static Boolean VerifyXmlFile(String Name, RSA Key)\n    {\n        // Create a new XML document.\n        XmlDocument xmlDocument = new XmlDocument();\n\n        // Load the passed XML file into the document. \n        xmlDocument.Load(Name);\n\n        // Create a new SignedXml object and pass it\n        // the XML document class.\n        SignedXml signedXml = new SignedXml(xmlDocument);\n\n        // Find the \"Signature\" node and create a new\n        // XmlNodeList object.\n        XmlNodeList nodeList = xmlDocument.GetElementsByTagName(\"Signature\");\n\n        // Load the signature node.\n        signedXml.LoadXml((XmlElement)nodeList[0]);\n\n        // Check the signature and return the result.\n        return signedXml.CheckSignature(Key);\n    }\n\n\n    // Create example data to sign.\n    public static void CreateSomeXml(string FileName)\n    {\n        // Create a new XmlDocument object.\n        XmlDocument document = new XmlDocument();\n\n        // Create a new XmlNode object.\n        XmlNode node = document.CreateNode(XmlNodeType.Element, \"\", \"MyElement\", \"samples\");\n\n        // Add some text to the node.\n        node.InnerText = \"Example text to be signed.\";\n\n        // Append the node to the document.\n        document.AppendChild(node);\n\n        // Save the XML document to the file name specified.\n        XmlTextWriter xmltw = new XmlTextWriter(FileName, new UTF8Encoding(false));\n        document.WriteTo(xmltw);\n        xmltw.Close();\n    }\n}\n"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities/utilities.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Security.Cryptography.Xml;\nusing System.Security.Cryptography;\nusing System.Security.Cryptography.X509Certificates;\nusing System.Xml;\nusing System.IO;\n\nnamespace ConsoleApplication31\n{\n    /*\n    class Program\n    {\n        static void Main(string[] args)\n        {\n            GetCanonization();\n            //GetSignature();\n\n        }\n\n        static void GetSignature()\n        {\n            XmlDocument doc = new XmlDocument();\n            //doc.LoadXml(\"<root><x xmlns=\\\"ns\\\" Id=\\\"_0\\\"></x><y attr=\\\"value\\\" Id=\\\"_1\\\"></y><z><w Id=\\\"_2\\\"></w></z></root>\");\n            doc.LoadXml(\"<root><x xmlns=\\\"ns\\\" Id=\\\"_0\\\"></x><y attr=\\\"value\\\" Id=\\\"_1\\\"></y><z><w Id=\\\"_2\\\"></w></z></root>\");\n            SignedXml signedXml = new SignedXml(doc);\n\n            var c = new X509Certificate2(\n                File.ReadAllBytes(@\"C:\\Program Files\\Microsoft WSE\\v2.0\\Samples\\Sample Test Certificates\\Client Private.pfx\"), \"wse2qs\");\n\n            signedXml.SigningKey = c.PrivateKey;\n            signedXml.Signature.SignedInfo.CanonicalizationMethod = \"http://www.w3.org/2001/10/xml-exc-c14n#\";\n\n            Reference ref0 = new Reference();\n            ref0.Uri = \"#_0\";\n            Reference ref1 = new Reference();\n            ref1.Uri = \"#_1\";\n            Reference ref2 = new Reference();\n            ref2.Uri = \"#_2\";\n\n            var t = new XmlDsigExcC14NTransform();\n            ref0.AddTransform(t);\n            ref1.AddTransform(t);\n            ref2.AddTransform(t);\n\n            signedXml.AddReference(ref0);\n            signedXml.AddReference(ref1);\n            signedXml.AddReference(ref2);\n\n            signedXml.ComputeSignature();\n            var xmlDigitalSignature = signedXml.GetXml();\n            var s = xmlDigitalSignature.OuterXml;\n        }\n\n        static void GetCanonization()\n        {\n            var c = new XmlDsigExcC14NTransform(true, \"\");\n            var doc = new XmlDocument();\n            doc.PreserveWhitespace = true;\n            doc.LoadXml(\"<x xmlns=\\\"ns\\\" xmlns:wsu=\\\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\\\" wsu:Id=\\\"_0\\\"/>\");\n            var node = doc.SelectSingleNode(\"//*[local-name(.)='x']\");\n            var nodes = node.SelectNodes(\".|.//*|.//text()|.//@*\");\n            c.LoadInput(nodes);\n\n            var h = new SHA1CryptoServiceProvider();\n            var b = c.GetDigestedOutput(h);\n            var b64 = Convert.ToBase64String(b);\n\n            var res = c.GetOutput() as MemoryStream;\n            string s2 = System.Text.Encoding.UTF8.GetString(res.ToArray());\n        }\n    }*/\n}\n"
  },
  {
    "path": "test/validators/XmlCryptoUtilities/XmlCryptoUtilities.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"ValidateSignature\", \"XmlCryptoUtilities\\ValidateSignature.csproj\", \"{CAA449E3-720D-4CD6-B03B-94991E11FF25}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{CAA449E3-720D-4CD6-B03B-94991E11FF25}.Debug|x86.ActiveCfg = Debug|x86\n\t\t{CAA449E3-720D-4CD6-B03B-94991E11FF25}.Debug|x86.Build.0 = Debug|x86\n\t\t{CAA449E3-720D-4CD6-B03B-94991E11FF25}.Release|x86.ActiveCfg = Release|x86\n\t\t{CAA449E3-720D-4CD6-B03B-94991E11FF25}.Release|x86.Build.0 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "test/wsfed-metadata-tests.spec.ts",
    "content": "import { SignedXml } from \"../src/index\";\nimport * as xpath from \"xpath\";\nimport * as xmldom from \"@xmldom/xmldom\";\nimport * as fs from \"fs\";\nimport { expect } from \"chai\";\nimport * as isDomNode from \"@xmldom/is-dom-node\";\n\ndescribe(\"WS-Fed Metadata tests\", function () {\n  it(\"test validating WS-Fed Metadata\", function () {\n    const xml = fs.readFileSync(\"./test/static/wsfederation_metadata.xml\", \"utf-8\");\n    const doc = new xmldom.DOMParser().parseFromString(xml);\n    const signature = xpath.select1(\n      \"/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']\",\n      doc,\n    );\n    isDomNode.assertIsNodeLike(signature);\n    const sig = new SignedXml();\n    sig.publicCert = fs.readFileSync(\"./test/static/wsfederation_metadata.pem\");\n    sig.loadSignature(signature);\n    const result = sig.checkSignature(xml);\n\n    expect(result).to.be.true;\n    expect(sig.getSignedReferences().length).to.equal(1);\n  });\n});\n"
  },
  {
    "path": "tsconfig.eslint.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"exclude\": [],\n  \"include\": [\"test\", \"src\"]\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    /* Visit https://aka.ms/tsconfig.json to read more about this file */\n\n    /* Basic Options */\n    // \"incremental\": true,                   /* Enable incremental compilation */\n    \"target\": \"es2020\" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,\n    \"module\": \"commonjs\" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,\n    \"lib\": [\"es2020\"] /* Specify library files to be included in the compilation. */,\n    \"allowJs\": true /* Allow javascript files to be compiled. */,\n    // \"checkJs\": true,                       /* Report errors in .js files. */\n    // \"jsx\": \"preserve\",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */\n    \"declaration\": true /* Generates corresponding '.d.ts' file. */,\n    // \"declarationMap\": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */\n    \"sourceMap\": true /* Generates corresponding '.map' file. */,\n    // \"outFile\": \"./\",                       /* Concatenate and emit output to single file. */\n    \"outDir\": \"./lib\" /* Redirect output structure to the directory. */,\n    \"rootDir\": \"./src\" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,\n    // \"composite\": true,                     /* Enable project compilation */\n    // \"tsBuildInfoFile\": \"./\",               /* Specify file to store incremental compilation information */\n    // \"removeComments\": true,                /* Do not emit comments to output. */\n    // \"noEmit\": true,                        /* Do not emit outputs. */\n    // \"importHelpers\": true,                 /* Import emit helpers from 'tslib'. */\n    // \"downlevelIteration\": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */\n    // \"isolatedModules\": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */\n\n    /* Strict Type-Checking Options */\n    \"strict\": true /* Enable all strict type-checking options. */,\n    \"noImplicitAny\": false /* Raise error on expressions and declarations with an implied 'any' type. */,\n    // \"strictNullChecks\": true,              /* Enable strict null checks. */\n    // \"strictFunctionTypes\": true,           /* Enable strict checking of function types. */\n    // \"strictBindCallApply\": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */\n    // \"strictPropertyInitialization\": true,  /* Enable strict checking of property initialization in classes. */\n    // \"noImplicitThis\": true,                /* Raise error on 'this' expressions with an implied 'any' type. */\n    // \"alwaysStrict\": true,                  /* Parse in strict mode and emit \"use strict\" for each source file. */\n\n    /* Additional Checks */\n    // \"noUnusedLocals\": true,                /* Report errors on unused locals. */\n    // \"noUnusedParameters\": true,            /* Report errors on unused parameters. */\n    // \"noImplicitReturns\": true,             /* Report error when not all code paths in function return a value. */\n    // \"noFallthroughCasesInSwitch\": true,    /* Report errors for fallthrough cases in switch statement. */\n\n    /* Module Resolution Options */\n    // \"moduleResolution\": \"node\",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */\n    // \"baseUrl\": \"./\",                       /* Base directory to resolve non-absolute module names. */\n    // \"paths\": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */\n    // \"typeRoots\": [],                       /* List of folders to include type definitions from. */\n    // \"types\": [],                           /* Type declaration files to be included in compilation. */\n    // \"allowSyntheticDefaultImports\": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */\n    // \"esModuleInterop\": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */\n    // \"preserveSymlinks\": true,              /* Do not resolve the real path of symlinks. */\n    // \"allowUmdGlobalAccess\": true,          /* Allow accessing UMD globals from modules. */\n\n    /* Source Map Options */\n    // \"sourceRoot\": \"\",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */\n    // \"mapRoot\": \"\",                         /* Specify the location where debugger should locate map files instead of generated locations. */\n    // \"inlineSourceMap\": true,               /* Emit a single file with source maps instead of having a separate file. */\n    \"inlineSources\": true /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */,\n\n    /* Experimental Options */\n    // \"experimentalDecorators\": true,        /* Enables experimental support for ES7 decorators. */\n    // \"emitDecoratorMetadata\": true,         /* Enables experimental support for emitting type metadata for decorators. */\n\n    /* Advanced Options */\n    \"skipLibCheck\": true /* Skip type checking of declaration files. */,\n    \"forceConsistentCasingInFileNames\": true /* Disallow inconsistently-cased references to the same file. */\n  },\n  \"exclude\": [\"node_modules\", \"docs\", \"lib\", \"test\", \"coverage\", \"example\"],\n  \"include\": [\"src\"]\n}\n"
  }
]