├── .clang-format ├── .codecov.yml ├── .github └── workflows │ ├── codeql-analysis.yml │ ├── coverity.yml │ ├── format.yml │ ├── license.yml │ ├── push.yml │ └── release.yml ├── .gitignore ├── .reuse └── dep5 ├── .sonar-project.properties ├── .whitesource ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSES ├── Apache-2.0.txt └── MIT.txt ├── NOTICE ├── README.md ├── examples └── basic │ ├── es_example.c │ ├── hs_example.c │ ├── ps_example.c │ └── rs_example.c ├── include └── cjwt │ ├── cjwt.h │ ├── cjwtver.h.in │ └── meson.build ├── meson.build ├── src ├── cjwt.c ├── jws.h ├── jws_openssl_1.c ├── jws_openssl_3.c ├── print.c ├── utils.c └── utils.h ├── subprojects ├── cjson.wrap └── trower-base64.wrap └── tests ├── inputs ├── badkey4.pem ├── badkey5.pem ├── badkey6.pem ├── jwt1.txt ├── jwt10_hs512.txt ├── jwt11.txt ├── jwt12.txt ├── jwt13.txt ├── jwt1l.txt ├── jwt1x.txt ├── jwt1y.txt ├── jwt2.txt ├── jwt2l.txt ├── jwt2x.txt ├── jwt2y.txt ├── jwt3.txt ├── jwt3l.txt ├── jwt3x.txt ├── jwt3y.txt ├── jwt4.txt ├── jwt4l.txt ├── jwt4x.txt ├── jwt4y.txt ├── jwt5.txt ├── jwt5l.txt ├── jwt5x.txt ├── jwt5y.txt ├── jwt6.txt ├── jwt6l.txt ├── jwt6x.txt ├── jwt6y.txt ├── jwt8_hs256.txt ├── jwt9_hs384.txt ├── jwt_r11.pem ├── jwt_r11.txt ├── jwtbadalg.txt ├── jwtia.txt ├── jwtib.txt ├── jwtic.txt ├── jwtid.txt ├── jwtie.txt ├── jwtif.txt ├── jwtn.txt ├── jwtnx.txt ├── jwtny.txt ├── jwtr1.txt ├── jwtr2.txt ├── key10_hs512.pem ├── key4.pem ├── key5.pem ├── key6.pem ├── key8_hs256.pem ├── key9_hs384.pem ├── pubkey4.pem ├── pubkey5.pem ├── pubkey6.pem └── pubkey_jwr1.pem ├── new_inputs ├── es256.jwt ├── es256.jwt.pub ├── es384.jwt ├── es384.jwt.pub ├── es512.jwt ├── es512.jwt.pub ├── hdr_b64.inv ├── hs256.jwt ├── hs384.jwt ├── hs512.jwt ├── ps.pub ├── ps256.jwt ├── ps384.jwt ├── ps512.jwt ├── rs-alt.key ├── rs-alt.pub ├── rs.partial ├── rs.pub ├── rs256.jwt ├── rs384.jwt ├── rs512.jwt ├── sig_b64.inv ├── try_1.inv ├── try_2.inv ├── try_4.inv └── try_5.inv ├── test_cjwt.c ├── test_cjwt_new.c ├── test_map.c ├── test_print.c └── test_utils.c /.clang-format: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | # Version 1 4 | # Requires clang-format v13 due to AlignArrayOfStructures 5 | 6 | --- 7 | Language: Cpp 8 | 9 | BasedOnStyle: WebKit 10 | AlignConsecutiveAssignments: Consecutive 11 | AlignAfterOpenBracket: Align 12 | AlignArrayOfStructures: Right 13 | AlignConsecutiveMacros: Consecutive 14 | AlignEscapedNewlines: Left 15 | AlignTrailingComments: true 16 | AllowShortCaseLabelsOnASingleLine: true 17 | AllowShortIfStatementsOnASingleLine: WithoutElse 18 | AlwaysBreakBeforeMultilineStrings: true 19 | BreakBeforeBraces: Custom 20 | BraceWrapping: 21 | AfterCaseLabel: false 22 | AfterClass: false 23 | AfterControlStatement: MultiLine 24 | AfterEnum: false 25 | AfterFunction: true 26 | AfterNamespace: false 27 | AfterObjCDeclaration: false 28 | AfterStruct: false 29 | AfterUnion: false 30 | AfterExternBlock: false 31 | BeforeCatch: false 32 | BeforeElse: false 33 | BeforeLambdaBody: false 34 | BeforeWhile: false 35 | IndentBraces: false 36 | SplitEmptyFunction: true 37 | SplitEmptyRecord: true 38 | SplitEmptyNamespace: true 39 | ConstructorInitializerIndentWidth: 4 40 | DerivePointerAlignment: false 41 | MaxEmptyLinesToKeep: 2 42 | IndentCaseLabels: true 43 | IndentWidth: 4 44 | TabWidth: 4 45 | PointerAlignment: Right 46 | SpaceAfterCStyleCast: true 47 | SpaceBeforeCpp11BracedList: false 48 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | coverage: 5 | range: 50..80 6 | round: down 7 | precision: 2 8 | 9 | ignore: 10 | - "tests" 11 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | name: LGTM Analysis 5 | 6 | on: 7 | create: 8 | pull_request: 9 | branches: 10 | - main 11 | push: 12 | branches: 13 | - main 14 | schedule: 15 | - cron: '12 9 * * 3' 16 | 17 | jobs: 18 | codeql: 19 | uses: xmidt-org/.github/.github/workflows/codeql-c-analysis.yml@main 20 | with: 21 | packages: libcjson-dev libcurl4-openssl-dev 22 | -------------------------------------------------------------------------------- /.github/workflows/coverity.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | name: Coverity Check 5 | 6 | on: 7 | push: 8 | paths-ignore: 9 | - 'AUTHORS' 10 | - 'LICENSE' 11 | - 'NOTICE' 12 | - '**.md' 13 | - '.gitignore' 14 | tags-ignore: 15 | - 'v[0-9]+.[0-9]+.[0-9]+' 16 | branches: 17 | - main 18 | schedule: 19 | - cron: '12 9 * * 3' 20 | 21 | jobs: 22 | test: 23 | uses: xmidt-org/.github/.github/workflows/meson-coverity.yml@main 24 | with: 25 | repo: $GITHUB_REPOSITORY 26 | sha: $GITHUB_SHA 27 | packages: libcjson-dev libcurl4-openssl-dev 28 | secrets: 29 | coverity_key: ${{ secrets.COVERITY_KEY }} 30 | -------------------------------------------------------------------------------- /.github/workflows/format.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | name: Code Format Check 5 | 6 | on: 7 | pull_request: 8 | push: 9 | paths-ignore: 10 | - 'AUTHORS' 11 | - 'LICENSE' 12 | - 'NOTICE' 13 | - '**.md' 14 | - '.gitignore' 15 | tags-ignore: 16 | - 'v[0-9]+.[0-9]+.[0-9]+' 17 | branches: 18 | - main 19 | schedule: 20 | - cron: '12 9 * * 3' 21 | 22 | jobs: 23 | test: 24 | uses: xmidt-org/.github/.github/workflows/c-code-format.yml@main 25 | -------------------------------------------------------------------------------- /.github/workflows/license.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | name: REUSE Compliance Check 5 | 6 | on: 7 | pull_request: 8 | push: 9 | tags-ignore: 10 | - 'v[0-9]+.[0-9]+.[0-9]+' 11 | branches: 12 | - main 13 | schedule: 14 | - cron: '12 9 * * 3' 15 | 16 | jobs: 17 | test: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: REUSE Compliance Check 22 | uses: fsfe/reuse-action@v1 23 | -------------------------------------------------------------------------------- /.github/workflows/push.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | name: CI 5 | 6 | on: 7 | pull_request: 8 | push: 9 | paths-ignore: 10 | - 'AUTHORS' 11 | - 'LICENSE' 12 | - 'NOTICE' 13 | - '**.md' 14 | - '.gitignore' 15 | tags-ignore: 16 | - 'v[0-9]+.[0-9]+.[0-9]+' 17 | branches: 18 | - main 19 | workflow_dispatch: 20 | 21 | jobs: 22 | test-openssl-1_1: 23 | uses: xmidt-org/.github/.github/workflows/meson-unit-test.yml@main 24 | with: 25 | # cjson & openssl 26 | packages: libcjson-dev libssl-dev 27 | brew-packages: cjson openssl@1.1 28 | brew-extra: PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig" 29 | runner-ubuntu: ubuntu-20.04 30 | sonarcloud-skip: true 31 | 32 | secrets: 33 | sonar_login: ${{ secrets.SONAR_TOKEN }} 34 | codecov_token: ${{ secrets.CODECOV_TOKEN }} 35 | 36 | test-openssl-3_x: 37 | uses: xmidt-org/.github/.github/workflows/meson-unit-test.yml@main 38 | with: 39 | # cjson & openssl 40 | packages: libcjson-dev libssl-dev 41 | brew-packages: cjson openssl@3 42 | macos-openssl-fix: true 43 | sonarcloud-skip: true 44 | 45 | secrets: 46 | sonar_login: ${{ secrets.SONAR_TOKEN }} 47 | codecov_token: ${{ secrets.CODECOV_TOKEN }} 48 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | name: release 5 | 6 | on: 7 | push: 8 | paths: 9 | - "CHANGELOG.md" # only try to tag if the CHANGELOG has been updated. 10 | branches: 11 | - main 12 | workflow_dispatch: 13 | 14 | jobs: 15 | release: 16 | uses: xmidt-org/.github/.github/workflows/meson-release.yml@main 17 | secrets: inherit 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2017-2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | build 5 | builddir 6 | tags 7 | 8 | # ignore subproject objects (keep the .wrap) 9 | subprojects/cJSON-* 10 | subprojects/trower-base64-* 11 | subprojects/packagecache 12 | 13 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 14 | *.o 15 | *.a 16 | *.so 17 | 18 | # Folders 19 | _obj 20 | _test 21 | 22 | # Architecture specific extensions/prefixes 23 | *.[568vq] 24 | [568vq].out 25 | 26 | *.cgo1.go 27 | *.cgo2.c 28 | _cgo_defun.c 29 | _cgo_gotypes.go 30 | _cgo_export.* 31 | *.zip 32 | *.tar.gz 33 | 34 | _testmain.go 35 | 36 | *.exe 37 | *.test 38 | *.prof 39 | *.xml 40 | 41 | *.gcov 42 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: cjwt 3 | Upstream-Contact: Weston Schmidt 4 | Source: https://github.com/xmidt-org/cjwt\ 5 | 6 | Files: .whitesource 7 | Copyright: 2021 Unknown 8 | License: Apache-2.0 9 | 10 | Files: NOTICE 11 | Copyright: 2017-2021 Comcast Cable Communications Management, LLC 12 | License: Apache-2.0 13 | 14 | Files: tests/inputs/* 15 | Copyright: 2017-2021 Comcast Cable Communications Management, LLC 16 | License: Apache-2.0 17 | 18 | Files: tests/new_inputs/* 19 | Copyright: 2021 Comcast Cable Communications Management, LLC 20 | License: Apache-2.0 21 | 22 | Files: subprojects/cjson.wrap 23 | Copyright: 2021 Comcast Cable Communications Management, LLC 24 | License: MIT 25 | -------------------------------------------------------------------------------- /.sonar-project.properties: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | # Reference: 5 | # https://github.com/SonarSource/sonarcloud_example_go-sqscanner-travis/blob/master/sonar-project.properties 6 | 7 | 8 | # ===================================================== 9 | # Standard properties 10 | # ===================================================== 11 | 12 | sonar.organization=xmidt-org 13 | sonar.projectKey=xmidt-org_cjwt 14 | sonar.projectName=cjwt 15 | sonar.branch.name=main 16 | sonar.branch.target=main 17 | 18 | sonar.sources=src 19 | 20 | # ===================================================== 21 | # Meta-data for the project 22 | # ===================================================== 23 | 24 | sonar.links.homepage=https://github.com/xmidt-org/cjwt 25 | sonar.links.ci=https://travis-ci.org/xmidt-org/cjwt 26 | sonar.links.scm=https://github.com/xmidt-org/cjwt 27 | sonar.links.issue=https://github.com/xmidt-org/cjwt/issues 28 | 29 | # ===================================================== 30 | # Properties specific to C 31 | # ===================================================== 32 | sonar.cfamily.build-wrapper-output=build/bw-output 33 | sonar.cfamily.threads=2 34 | sonar.cfamily.cache.enabled=false 35 | sonar.coverageReportPaths=build/sonarqube.xml 36 | 37 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "scanSettings": { 3 | "baseBranches": [] 4 | }, 5 | "checkRunSettings": { 6 | "vulnerableCheckRunConclusionLevel": "failure", 7 | "displayMode": "diff" 8 | }, 9 | "issueSettings": { 10 | "minSeverityLevel": "LOW" 11 | } 12 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 5 | # Changelog 6 | All notable changes to this project will be documented in this file. 7 | 8 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 9 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 10 | 11 | ## [Unreleased] 12 | 13 | ## [v2.3.0] 14 | - Fix for CVE-2024-54150: https://github.com/xmidt-org/cjwt/commit/096ab3e37f73c914b716e7259589179f363265fd 15 | - When using HSxxx signing types, the new option `OPT_ALLOW_ONLY_HS_ALG` is required. 16 | This ensures that public/private keys can't be mistakenly accepted as symmetric 17 | algorithem ciphers. 18 | 19 | ## [v2.2.1] 20 | - Bump the version to trigger a full release. 21 | 22 | ## [v2.2.0] 23 | - Add support for openssl v3 as well as v1 APIs. 24 | - Add support for private jwt headers and the `kid` standard header. 25 | - Require meson 0.60.3 or newer. 26 | 27 | ## [v2.1.1] 28 | - Fix a few compiler warnings in the example code. 29 | 30 | ## [v2.1.0] 31 | - Add string to alg type mapping function. 32 | - Allow use of `num_algorithms`. 33 | 34 | ## [v2.0.1] 35 | - Upgrade the build system to use meson. 36 | - Improve the CI pipeline. 37 | 38 | ## [v2.0.0] 39 | - Update the interface to not use strlen() for lengths but expect them to be 40 | passed in. This reduces the likelihood of this library being exploited by 41 | a long string. 42 | - Add the cjwt_printf() function to the interface. 43 | - Remove the alg mapping function that was mistakenly provided in the 1.x.x API. 44 | - Add a few worked examples. 45 | 46 | ## [v1.0.4] 47 | - Move to use internal base64 decoding with stricter processing rules 48 | - Major refactor to use a specified length and not '\0' terminated strings internally. 49 | - A number of failures that may not have been detected now have tests and are covered. 50 | - Bridge the new implementation to use the existing API. 51 | 52 | ## [v1.0.3] 53 | - Move to use Github Actions for building 54 | - Improve the cmake files to support the new build system better 55 | - Bump to a known new version 56 | 57 | ## [1.0.2] 58 | 59 | It is unclear what is exactly in 1.0.0 through 1.0.2. 60 | 61 | ### Added 62 | - Valgrind checking and fixes. 63 | - Algorithms that are unsupported now are not mapped to alg=none to prevent untrusted 64 | accidental acceptance of JWT. 65 | 66 | ### Changed 67 | - Fixed memory leaks. 68 | - Updated the CONTRIBUTION document. 69 | - Updated the cjwt_decode() documentation to be accurate and consistent. 70 | 71 | ## [1.0.1] 72 | ### Added 73 | - First stable release 74 | 75 | [Unreleased]: https://github.com/xmidt-org/cjwt/compare/v2.2.1...HEAD 76 | [v2.2.1]: https://github.com/xmidt-org/cjwt/compare/v2.2.1...v2.2.0 77 | [v2.2.0]: https://github.com/xmidt-org/cjwt/compare/v2.2.0...v2.1.1 78 | [v2.1.1]: https://github.com/xmidt-org/cjwt/compare/v2.1.1...v2.1.0 79 | [v2.1.0]: https://github.com/xmidt-org/cjwt/compare/v2.0.1...v2.1.0 80 | [v2.0.1]: https://github.com/xmidt-org/cjwt/compare/v2.0.0...v2.0.1 81 | [v2.0.0]: https://github.com/xmidt-org/cjwt/compare/v1.0.4...v2.0.0 82 | [v1.0.4]: https://github.com/xmidt-org/cjwt/compare/v1.0.3...v1.0.4 83 | [v1.0.3]: https://github.com/xmidt-org/cjwt/compare/1.0.2...v1.0.3 84 | [1.0.2]: https://github.com/xmidt-org/cjwt/compare/1.0.1...1.0.2 85 | [1.0.1]: https://github.com/xmidt-org/cjwt/compare/5d07465b61c7787e1ae8491c320a93cf3a1f531c...1.0.1 86 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 5 | Contribution Guidelines 6 | ======================= 7 | 8 | We love to see contributions to the project and have tried to make it easy to 9 | do so. If you would like to contribute code to this project you can do so 10 | through GitHub by [forking the repository and sending a pull request](http://gun.io/blog/how-to-github-fork-branch-and-pull-request/). 11 | 12 | Before Comcast merges your code into the project you must sign the 13 | [Comcast Contributor License Agreement (CLA)](https://gist.github.com/ComcastOSS/a7b8933dd8e368535378cda25c92d19a). 14 | 15 | If you haven't previously signed a Comcast CLA, you'll automatically be asked 16 | to when you open a pull request. Alternatively, we can e-mail you a PDF that 17 | you can sign and scan back to us. Please send us an e-mail or create a new 18 | GitHub issue to request a PDF version of the CLA. 19 | 20 | If you have a trivial fix or improvement, please create a pull request and 21 | request a review from a [maintainer](MAINTAINERS.md) of this repository. 22 | 23 | If you plan to do something more involved, that involves a new feature or 24 | changing functionality, please first create an [issue](#issues) so a discussion of 25 | your idea can happen, avoiding unnecessary work and clarifying implementation. 26 | 27 | Documentation 28 | ------------- 29 | 30 | If you contribute anything that changes the behavior of the application, 31 | document it in the follow places as applicable: 32 | * the code itself, through clear comments and unit tests 33 | * [README](README.md) 34 | 35 | This includes new features, additional variants of behavior, and breaking 36 | changes. 37 | 38 | Testing 39 | ------- 40 | 41 | Tests are written using cunit, and are run prior to the PR being accepted. 42 | 43 | Issues 44 | ------ 45 | 46 | For creating an issue: 47 | * **Bugs:** please be as thorough as possible, with steps to recreate the issue 48 | and any other relevant information. 49 | * **Feature Requests:** please include functionality and use cases. If this is 50 | an extension of a current feature, please include whether or not this would 51 | be a breaking change or how to extend the feature with backwards 52 | compatibility. 53 | * **Security Vulnerability:** please report it at 54 | https://my.xfinity.com/vulnerabilityreport and contact the [maintainers](MAINTAINERS.md). 55 | 56 | If you wish to work on an issue, please assign it to yourself. If you have any 57 | questions regarding implementation, feel free to ask clarifying questions on 58 | the issue itself. 59 | 60 | Pull Requests 61 | ------------- 62 | 63 | * should be narrowly focused with no more than 3 or 4 logical commits 64 | * when possible, address no more than one issue 65 | * should be reviewable in the GitHub code review tool 66 | * should be linked to any issues it relates to (i.e. issue number after (#) in commit messages or pull request message) 67 | * should conform to existing code style 68 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 30 | 31 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 32 | 33 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 34 | 35 | (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and 36 | 37 | (b) You must cause any modified files to carry prominent notices stating that You changed the files; and 38 | 39 | (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 40 | 41 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 42 | 43 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 44 | 45 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 46 | 47 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 48 | 49 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 50 | 51 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 52 | 53 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 54 | 55 | END OF TERMS AND CONDITIONS 56 | 57 | APPENDIX: How to apply the Apache License to your work. 58 | 59 | To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. 60 | 61 | Copyright [yyyy] [name of copyright owner] 62 | 63 | Licensed under the Apache License, Version 2.0 (the "License"); 64 | you may not use this file except in compliance with the License. 65 | You may obtain a copy of the License at 66 | 67 | http://www.apache.org/licenses/LICENSE-2.0 68 | 69 | Unless required by applicable law or agreed to in writing, software 70 | distributed under the License is distributed on an "AS IS" BASIS, 71 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 72 | See the License for the specific language governing permissions and 73 | limitations under the License. 74 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | cjwt 2 | Copyright 2017 Comcast Cable Communications Management, LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | This product includes software developed at Comcast (http://www.comcast.com/). 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 5 | # cjwt 6 | 7 | A C JWT Implementation 8 | 9 | [![Build Status](https://github.com/xmidt-org/cjwt/workflows/CI/badge.svg)](https://github.com/xmidt-org/cjwt/actions) 10 | [![codecov](https://codecov.io/github/xmidt-org/cjwt/graph/badge.svg?token=DUB8zMsJtB)](https://codecov.io/github/xmidt-org/cjwt) 11 | [![Coverity](https://img.shields.io/coverity/scan/23236.svg)](https://scan.coverity.com/projects/xmidt-org-cjwt) 12 | [![Apache V2 License](http://img.shields.io/badge/license-Apache%20V2-blue.svg)](https://github.com/xmidt-org/cjwt/blob/main/LICENSES/Apache-2.0.txt) 13 | [![GitHub release](https://img.shields.io/github/release/xmidt-org/cjwt.svg)](CHANGELOG.md) 14 | [![JWT.io](http://jwt.io/img/badge.svg)](https://jwt.io/) 15 | 16 | `cjwt` is a small JWT handler designed to allow consumers of JWTs of the JWS variant 17 | the ability to securely and easily get claims and data from a JWT. This particular 18 | JWT implementation uses [cJSON](https://github.com/DaveGamble/cJSON) and is designed 19 | to support multiple different crypto libraries in the future. 20 | 21 | ## API 22 | 23 | The API is meant to be fairly small & leverage what cJSON already provides nicely. 24 | 25 | [Here are the details](https://github.com/xmidt-org/cjwt/blob/main/src/cjwt.h) 26 | 27 | There are 3 function: 28 | 29 | - `cjwt_decode()` that decodes successfully or fails with a more detailed reason 30 | - `cjwt_destroy()` that destroys the `cjwt_t` object cleanly 31 | - `cjwt_print()` that prints the `cjwt_t` object to a stream (generally for debugging) 32 | 33 | Otherwise you get a simple C struct to work with in your code. 34 | 35 | ## Dependencies 36 | 37 | - [cJSON](https://github.com/DaveGamble/cJSON) 38 | - [openssl](https://github.com/openssl/openssl) 39 | - [trower-base64](https://github.com/xmidt-org/trower-base64) 40 | 41 | 42 | ## Opinionated Default Secure 43 | 44 | To help adopters not make costly security mistakes, cjwt tries to default to 45 | secure wherever possible. If you **must** use an insecure feature there are 46 | option flags that let you do so, but use them sparingly and with care. 47 | 48 | 49 | # Examples: 50 | 51 | - [HS](https://github.com/xmidt-org/cjwt/blob/main/examples/basic/hs_example.c) 52 | - [RS / PS](https://github.com/xmidt-org/cjwt/blob/main/examples/basic/rs_example.c) 53 | - [ES](https://github.com/xmidt-org/cjwt/blob/main/examples/basic/es_example.c) 54 | 55 | ## Inline 56 | 57 | Using the decoder: 58 | 59 | ```c 60 | #include 61 | #include 62 | #include 63 | 64 | #include 65 | 66 | int main( int argc, char *argv[] ) 67 | { 68 | cjwt_t *jwt = NULL; 69 | cjwt_code_t rv; 70 | 71 | const char *hs_text = 72 | /* header */ 73 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." 74 | /* payload */ 75 | "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaGVsbG8i" 76 | "OiJ3b3JsZCIsImJvYiI6WyJkb2ciLDEyM10sImNhdCI6eyJtb3VzZSI6eyJj" 77 | "aGVlc2UiOiJsb3RzIn19LCJpYXQiOjE1MTYyMzkwMjJ9." 78 | /* signature */ 79 | "mJYSucD6RRg6zdPcSKvb5-LKFDJzRvdKqTlqAvDBknU"; 80 | 81 | const char *hs_key = "hs256-secret"; 82 | 83 | rv = cjwt_decode( hs_text, 84 | strlen(hs_text), 85 | OPT_ALLOW_ONLY_HS_ALG, 86 | (uint8_t*) hs_key, 87 | strlen(hs_key), 0, 0, &jwt ); 88 | if( CJWTE_OK != rv ) { 89 | printf( "There was an error processing the text: %d\n", rv ); 90 | return -1; 91 | } 92 | 93 | cjwt_print( stdout, jwt ); 94 | 95 | cjwt_destroy( jwt ); 96 | 97 | return 0; 98 | } 99 | ``` 100 | 101 | Gives you this output: 102 | 103 | ```txt 104 | ===================== 105 | header 106 | --------------------- 107 | alg: HS256 108 | 109 | payload 110 | --------------------- 111 | iat: 1516239022 112 | 113 | exp: NULL 114 | nbf: NULL 115 | 116 | iss: NULL 117 | sub: 1234567890 118 | jti: NULL 119 | aud: NULL 120 | 121 | private claims 122 | --------------------- 123 | { 124 | "name": "John Doe", 125 | "hello": "world", 126 | "bob": ["dog", 123], 127 | "cat": { 128 | "mouse": { 129 | "cheese": "lots" 130 | } 131 | } 132 | } 133 | ``` 134 | 135 | # Building and Testing Instructions 136 | 137 | ``` 138 | meson setup --warnlevel 3 --werror build 139 | cd build 140 | ninja all test coverage 141 | firefox ./meson-logs/coveragereport/index.html 142 | ``` 143 | -------------------------------------------------------------------------------- /examples/basic/es_example.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "cjwt.h" 9 | 10 | /* 11 | * The output of the program should be as following (the private claims 12 | * formatting may vary. 13 | * 14 | * ===================== 15 | * header 16 | * --------------------- 17 | * alg: HS256 18 | * 19 | * payload 20 | * --------------------- 21 | * iat: 1516239022 22 | * 23 | * exp: NULL 24 | * nbf: NULL 25 | * 26 | * iss: NULL 27 | * sub: 1234567890 28 | * jti: NULL 29 | * aud: NULL 30 | * 31 | * private claims 32 | * --------------------- 33 | * { 34 | * "library": "https://github.com/xmidt-org/cjwt" 35 | * } 36 | * ===================== 37 | */ 38 | 39 | int main(void) 40 | { 41 | cjwt_t *jwt = NULL; 42 | cjwt_code_t rv; 43 | 44 | const char *es_text = 45 | /* header */ 46 | "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9." 47 | /* payload */ 48 | "eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l" 49 | "0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0." 50 | /* signature */ 51 | "dVNftrYfhBrS7tNzJj5UKM-GTzFfZpL7rTUsrYUFn9m0EFPtFT85DVcW" 52 | "I5mYrkms7TMhcU9i18CAna_Xd0qCBA"; 53 | 54 | const char *es_pub_key = 55 | "-----BEGIN PUBLIC KEY-----\n" 56 | "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs/o5+uQbTjL3chynL4wXgUg2R9\n" 57 | "q9UU8I5mEovUf86QZ7kOBIjJwqnzD1omageEHWwHdBO6B+dFabmdT9POxg==\n" 58 | "-----END PUBLIC KEY-----"; 59 | 60 | rv = cjwt_decode(es_text, strlen(es_text), 0, 61 | (uint8_t *) es_pub_key, strlen(es_pub_key), 0, 0, &jwt); 62 | 63 | if (CJWTE_OK != rv) { 64 | printf("There was an error processing the text: %d\n", rv); 65 | return -1; 66 | } 67 | 68 | cjwt_print(stdout, jwt); 69 | 70 | cjwt_destroy(jwt); 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /examples/basic/hs_example.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "cjwt.h" 9 | 10 | /* 11 | * The output of the program should be as following (the private claims 12 | * formatting may vary. 13 | * 14 | * ===================== 15 | * header 16 | * --------------------- 17 | * alg: HS256 18 | * 19 | * payload 20 | * --------------------- 21 | * iat: 1516239022 22 | * 23 | * exp: NULL 24 | * nbf: NULL 25 | * 26 | * iss: NULL 27 | * sub: 1234567890 28 | * jti: NULL 29 | * aud: NULL 30 | * 31 | * private claims 32 | * --------------------- 33 | * { 34 | * "name": "John Doe", 35 | * "hello": "world", 36 | * "bob": ["dog", 123], 37 | * "cat": { 38 | * "mouse": { 39 | * "cheese": "lots" 40 | * } 41 | * } 42 | * } 43 | * ===================== 44 | */ 45 | 46 | int main(void) 47 | { 48 | cjwt_t *jwt = NULL; 49 | cjwt_code_t rv; 50 | 51 | const char *hs_text = 52 | /* header */ 53 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." 54 | /* payload */ 55 | "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaGVsbG8i" 56 | "OiJ3b3JsZCIsImJvYiI6WyJkb2ciLDEyM10sImNhdCI6eyJtb3VzZSI6eyJj" 57 | "aGVlc2UiOiJsb3RzIn19LCJpYXQiOjE1MTYyMzkwMjJ9." 58 | /* signature */ 59 | "mJYSucD6RRg6zdPcSKvb5-LKFDJzRvdKqTlqAvDBknU"; 60 | 61 | const char *hs_key = "hs256-secret"; 62 | 63 | rv = cjwt_decode(hs_text, strlen(hs_text), 0, (uint8_t *) hs_key, strlen(hs_key), 0, 0, &jwt); 64 | if (CJWTE_OK != rv) { 65 | printf("There was an error processing the text: %d\n", rv); 66 | return -1; 67 | } 68 | 69 | cjwt_print(stdout, jwt); 70 | 71 | cjwt_destroy(jwt); 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /examples/basic/ps_example.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2023 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "cjwt.h" 9 | 10 | /* 11 | * The output of the program should be as following (the private claims 12 | * formatting may vary. 13 | * 14 | * ===================== 15 | * header 16 | * --------------------- 17 | * alg: PS384 18 | * 19 | * payload 20 | * --------------------- 21 | * iat: 1516239022 22 | * 23 | * exp: NULL 24 | * nbf: NULL 25 | * 26 | * iss: NULL 27 | * sub: 1234567890 28 | * jti: NULL 29 | * aud: NULL 30 | * 31 | * private claims 32 | * --------------------- 33 | * { 34 | * "library": "https://github.com/xmidt-org/cjwt" 35 | * } 36 | * ===================== 37 | */ 38 | 39 | int main(void) 40 | { 41 | cjwt_t *jwt = NULL; 42 | cjwt_code_t rv; 43 | 44 | /* the rs variant is very similar */ 45 | const char *ps_text = 46 | /* header */ 47 | "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9." 48 | /* payload */ 49 | "eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l" 50 | "0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0." 51 | /* signature */ 52 | "Jt2SaHKp56wizHwwzomeRo-9a4M6ODg02sB7cZUZslEg-1QtoDTGHXZv" 53 | "F73KmG8AJ9S2r4FbhZ9mmP_wL4OJs2fObA3RdMkyd2P1rpdXfXpK7mXU" 54 | "10fzQzT-l7RHQ3MqKkALs1iaczSp-rUOB-FiekkrAGSca0K02oHM9rpX" 55 | "xICL4Gc_nV-mk32e-R7jihV3BCX_8zpQoBt0cUwufW6R1GyD6DdmOErU" 56 | "0cTqa6t0oTmZIFNARCZ4AXj-GRajwN5meEwFjtmyGAXCL9bZl8Sv_7Fs" 57 | "NEnscW8UaL9CWIz_4CInAdFnWFj4EGNKfKt60lfdNPUAxZYPERXFkxBb" 58 | "cqQXBg"; 59 | 60 | const char *ps_pub_key = 61 | "-----BEGIN PUBLIC KEY-----\n" 62 | "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv\n" 63 | "vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc\n" 64 | "aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy\n" 65 | "tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0\n" 66 | "e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb\n" 67 | "V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9\n" 68 | "MwIDAQAB\n" 69 | "-----END PUBLIC KEY-----"; 70 | 71 | rv = cjwt_decode(ps_text, strlen(ps_text), 0, 72 | (uint8_t *) ps_pub_key, strlen(ps_pub_key), 0, 0, &jwt); 73 | 74 | if (CJWTE_OK != rv) { 75 | printf("There was an error processing the text: %d\n", rv); 76 | return -1; 77 | } 78 | 79 | cjwt_print(stdout, jwt); 80 | 81 | cjwt_destroy(jwt); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /examples/basic/rs_example.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "cjwt.h" 9 | 10 | /* 11 | * The output of the program should be as following (the private claims 12 | * formatting may vary. 13 | * 14 | * ===================== 15 | * header 16 | * --------------------- 17 | * alg: HS256 18 | * 19 | * payload 20 | * --------------------- 21 | * iat: 1516239022 22 | * 23 | * exp: NULL 24 | * nbf: NULL 25 | * 26 | * iss: NULL 27 | * sub: 1234567890 28 | * jti: NULL 29 | * aud: NULL 30 | * 31 | * private claims 32 | * --------------------- 33 | * { 34 | * "library": "https://github.com/xmidt-org/cjwt" 35 | * } 36 | * ===================== 37 | */ 38 | 39 | int main(void) 40 | { 41 | cjwt_t *jwt = NULL; 42 | cjwt_code_t rv; 43 | 44 | /* the ps variant is very similar */ 45 | const char *rs_text = 46 | /* header */ 47 | "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9." 48 | /* payload */ 49 | "eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l" 50 | "0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0." 51 | /* signature */ 52 | "e-pFjFcKyrWa6ODgkclHe26EEF6AkI-xaW6J-Z37IdfygRKmgqy5cIz" 53 | "hjIGBPQg2aJGrPmCc5zP-zeK1M98odo5OCxCDdfQsKTtJJlCIVC2Iv1" 54 | "CaZDc-dTNnmjZE6PBM9fzwhXd5ESNjSxhtHSt8_9gFmogaixcxD1D7A" 55 | "nSJ1kl-o9yVK2vBRTHfFEyx5npUGbuNGSdIcoUHQUvL3B55XhQW_IlT" 56 | "moYUjBKAg0Mqk1HAhzQ-ZXz2C6Ptopx9ga3ccK4QmXnUHwo_bRF7eIh" 57 | "WweMfy_JM7pNGZc1VGa0hCpp-Axwq3CZfwLL0DY7ohcSYfJN_4d4Qn7" 58 | "2S8EHKg_E5Ng"; 59 | const char *rs_pub_key = 60 | "-----BEGIN PUBLIC KEY-----\n" 61 | "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv\n" 62 | "vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc\n" 63 | "aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy\n" 64 | "tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0\n" 65 | "e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb\n" 66 | "V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9\n" 67 | "MwIDAQAB\n" 68 | "-----END PUBLIC KEY-----"; 69 | 70 | rv = cjwt_decode(rs_text, strlen(rs_text), 0, 71 | (uint8_t *) rs_pub_key, strlen(rs_pub_key), 0, 0, &jwt); 72 | 73 | if (CJWTE_OK != rv) { 74 | printf("There was an error processing the text: %d\n", rv); 75 | return -1; 76 | } 77 | 78 | cjwt_print(stdout, jwt); 79 | 80 | cjwt_destroy(jwt); 81 | 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /include/cjwt/cjwt.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2017-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | #ifndef __CJWT_H__ 4 | #define __CJWT_H__ 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | /*----------------------------------------------------------------------------*/ 12 | /* Macros */ 13 | /*----------------------------------------------------------------------------*/ 14 | 15 | /* If you specify OPT_ALLOW_ALG_NONE as part of the options bitmask you 16 | * are allowing `alg_none` to be supported. 17 | * 18 | * ---ALG_NONE IS INSECURE AND SHOULD NEVER BE USED IN PRODUCTION--- 19 | */ 20 | #define OPT_ALLOW_ALG_NONE (1 << 0) 21 | 22 | 23 | /* If you specify OPT_ALLOW_ANY_TIME as part of the options bitmask you 24 | * are telling cjwt to ignore enforcing the 'nbf' and 'exp' declarations 25 | * from the JWT and always accept the JWT. 26 | * 27 | * ---ACCEPTING TOKENS OUTSIDE THEIR INTENDED WINDOW IS DANGEROUS--- 28 | */ 29 | #define OPT_ALLOW_ANY_TIME (1 << 1) 30 | 31 | 32 | /* If you specify OPT_ALLOW_ANY_TYP as part of the options bitmask you 33 | * are telling cjwt to not strictly enforce the 'typ' processing rules for 34 | * that header. CJWT already ignores the case of 'JWT', but this disables 35 | * the check entirely. 36 | * 37 | * This is mainly a strict compliance option & does not impact security. 38 | */ 39 | #define OPT_ALLOW_ANY_TYP (1 << 2) 40 | 41 | /* If you specify OPT_ALLOW_ONLY_HS_ALG as part of the options bitmask you 42 | * are allowing only the use of HMAC-SHA algorithms (HS256, HS384, HS512). 43 | * Otherwise only public key algorithms are allowed. 44 | * 45 | * Symmetric algorithms and the unknown key type passed in pose a security 46 | * risk since an attacker can treate the provided public key as the secret 47 | * key and sign their own JWTs with the public key as a symmetric key. 48 | */ 49 | #define OPT_ALLOW_ONLY_HS_ALG (1 << 3) 50 | 51 | /*----------------------------------------------------------------------------*/ 52 | /* Data Structures */ 53 | /*----------------------------------------------------------------------------*/ 54 | 55 | 56 | /* All possible error codes from all the cjwt functions. Future versions may 57 | * return other values. 58 | * 59 | * Always add new return codes last. Do not remove any. The return codes 60 | * must remain the same. 61 | */ 62 | typedef enum { 63 | CJWTE_OK = 0, 64 | CJWTE_INVALID_PARAMETERS, /* 1 */ 65 | CJWTE_INVALID_SECTIONS, /* 2 */ 66 | CJWTE_OUT_OF_MEMORY, /* 3 */ 67 | CJWTE_LIBRARY_BUG_SHA, /* 4 */ 68 | CJWTE_LIBRARY_BUG_RSA, /* 5 */ 69 | CJWTE_HEADER_MISSING, /* 6 */ 70 | CJWTE_HEADER_INVALID_BASE64, /* 7 */ 71 | CJWTE_HEADER_INVALID_JSON, /* 8 */ 72 | CJWTE_HEADER_MISSING_ALG, /* 9 */ 73 | CJWTE_HEADER_UNSUPPORTED_ALG, /* 10 */ 74 | CJWTE_PAYLOAD_MISSING, /* 11 */ 75 | CJWTE_PAYLOAD_INVALID_BASE64, /* 12 */ 76 | CJWTE_PAYLOAD_INVALID_JSON, /* 13 */ 77 | CJWTE_PAYLOAD_AUD_NOT_VALID, /* 14 */ 78 | CJWTE_PAYLOAD_EXPECTED_STRING, /* 15 */ 79 | CJWTE_PAYLOAD_EXPECTED_NUMBER, /* 16 */ 80 | CJWTE_SIGNATURE_MISSING, /* 17 */ 81 | CJWTE_SIGNATURE_INVALID_BASE64, /* 18 */ 82 | CJWTE_SIGNATURE_UNSUPPORTED_ALG, /* 19 */ 83 | CJWTE_SIGNATURE_VALIDATION_FAILED, /* 20 */ 84 | CJWTE_SIGNATURE_MISSING_KEY, /* 21 */ 85 | CJWTE_SIGNATURE_INVALID_KEY, /* 22 */ 86 | CJWTE_TIME_BEFORE_NBF, /* 23 */ 87 | CJWTE_TIME_AFTER_EXP, /* 24 */ 88 | CJWTE_HEADER_UNSUPPORTED_TYP, /* 25 */ 89 | CJWTE_HEADER_UNSUPPORTED_UNKNOWN, /* 26 */ 90 | CJWTE_KEY_TOO_LARGE, /* 27 */ 91 | CJWTE_SIGNATURE_KEY_TOO_LARGE, /* 28 */ 92 | CJWTE_UNKNOWN_ALG, /* 29 */ 93 | 94 | CJWTE_LAST /* never use! */ 95 | } cjwt_code_t; 96 | 97 | 98 | /** 99 | * The jwt defined algorithms. 100 | */ 101 | typedef enum { 102 | alg_none = 0, /* Only allowed if an option is set to prevent dangerous 103 | * conditions where an attacker could bypass security 104 | * checks. DO NOT USE THIS IN A PRODUCTION ENVIRONMENT. */ 105 | alg_es256, 106 | alg_es384, 107 | alg_es512, 108 | alg_hs256, 109 | alg_hs384, 110 | alg_hs512, 111 | alg_ps256, 112 | alg_ps384, 113 | alg_ps512, 114 | alg_rs256, 115 | alg_rs384, 116 | alg_rs512, 117 | 118 | num_algorithms 119 | } cjwt_alg_t; 120 | 121 | typedef struct { 122 | cjwt_alg_t alg; 123 | 124 | char *kid; 125 | 126 | cJSON *private_headers; 127 | 128 | /* Unsupported: 129 | * jku 130 | * jwk 131 | * x5u 132 | * x5c 133 | * x5t 134 | * x5ts256 135 | * cty 136 | * crit 137 | */ 138 | } cjwt_header_t; 139 | 140 | typedef struct cjwt_aud_list { 141 | int count; 142 | char **names; 143 | } cjwt_aud_list_t; 144 | 145 | typedef struct { 146 | cjwt_header_t header; 147 | 148 | char *iss; 149 | char *sub; 150 | char *jti; 151 | cjwt_aud_list_t aud; 152 | 153 | int64_t *exp; /* Time is seconds since Jan 1, 1970 */ 154 | int64_t *nbf; /* Time is seconds since Jan 1, 1970 */ 155 | int64_t *iat; /* Time is seconds since Jan 1, 1970 */ 156 | 157 | cJSON *private_claims; 158 | } cjwt_t; 159 | 160 | /*----------------------------------------------------------------------------*/ 161 | /* External Functions */ 162 | /*----------------------------------------------------------------------------*/ 163 | 164 | 165 | /** 166 | * The function to use to decode and validate a JWT. 167 | * 168 | * @note This function allocates memory associated with the output jwt that 169 | * must be freed. cjwt_destroy() must be called to destroy the object 170 | * when it is no longer needed. 171 | * 172 | * @note This code defaults secure so `alg_none` is not allowed unless 173 | * OPT_ALLOW_ALG_NONE is specified as an option. 174 | * 175 | * @note This code defaults strict so only claims with a valid time window 176 | * are accepted unless OPT_ALLOW_ANY_TIME is specified as an option. 177 | * 178 | * @note The key for HS signed JWTs is the plain text secret. 179 | * 180 | * @note To accept HS signed JWTs, OPT_ALLOW_ONLY_HS_ALG must be specified as 181 | * an option. This option disables the use of public key algorithms. 182 | * This is done to prevent an attacker from using a public key as a 183 | * symmetric key and signing their own JWTs. 184 | * 185 | * @note The key for PS, RS and EC signed JWTs expect the text from the PEM 186 | * file including the -----BEGIN PUBLIC KEY----- and 187 | * -----END PUBLIC KEY----- lines. 188 | * 189 | * @note The 'time' parameter is seconds since Jan 1, 1970. 190 | * 191 | * @note It is strongly encouraged to validate the 'alg' header to ensure 192 | * that the JWT is signed with the expected algorithm. This can be 193 | * done by checking the 'alg' header against a known value in the cjwt_t 194 | * object passed out via the jwt parameter. 195 | * 196 | * @param text [IN] the original JWT text 197 | * @param text_len [IN] length of the original text 198 | * @param options [IN] a bitmask of the options (see #defines at top of file) 199 | * @param key [IN] the public key to use for validating the signature 200 | * @param key_len [IN] the length of the key in bytes 201 | * @param time [IN] the time to use for evaluation of time based claims 202 | * @param skew [IN] the allowed time skew to accept in seconds 203 | * @param jwt [OUT] the resulting JWT if found to be valid, 204 | * set to NULL if not successful 205 | * 206 | * @return CJWTE_OK if successful, reason for failure otherwise 207 | */ 208 | cjwt_code_t cjwt_decode(const char *text, size_t text_len, uint32_t options, 209 | const uint8_t *key, size_t key_len, 210 | int64_t time, int64_t skew, cjwt_t **jwt); 211 | 212 | 213 | /** 214 | * The function that cleans up cjwt object allocations. 215 | * 216 | * @param jwt [IN] the to be freed cjwt 217 | */ 218 | void cjwt_destroy(cjwt_t *jwt); 219 | 220 | 221 | /** 222 | * This is a helper function that will walk the jwt and print out the contents 223 | * to the specified stream. 224 | * 225 | * @param stream the output stream to use (stdout or stderr) 226 | * @param jwt the JWT to output 227 | */ 228 | void cjwt_print(FILE *stream, cjwt_t *jwt); 229 | 230 | 231 | /** 232 | * Provides a simple way to take a string and convert it to the alg. 233 | * 234 | * @param s the string to inspect 235 | * @param len the length of the string (or SIZE_MAX if unknown length) 236 | * @param alg the resulting alg enum val if found 237 | * 238 | * @return CJWTE_OK if found, reason for failure otherwise 239 | * 240 | * Failure reasons: 241 | * CJWTE_INVALID_PARAMETERS 242 | * CJWTE_UNKNOWN_ALG 243 | */ 244 | cjwt_code_t cjwt_alg_string_to_enum(const char *s, size_t len, cjwt_alg_t *alg); 245 | 246 | #endif 247 | -------------------------------------------------------------------------------- /include/cjwt/cjwtver.h.in: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef _CJWT_VERSION_H_ 5 | #define _CJWT_VERSION_H_ 1 6 | 7 | #define CJWT_VERSION "@cjwt_VERSION@" 8 | 9 | #define CJWT_VERSION_MAJOR @cjwt_VERSION_MAJOR@ 10 | #define CJWT_VERSION_MINOR @cjwt_VERSION_MINOR@ 11 | #define CJWT_VERSION_PATCH @cjwt_VERSION_PATCH@ 12 | 13 | /* This is the numeric version of the cjwt version number, meant for easier 14 | * parsing and comparisons by programs. The CJWT_VERSION_NUM define will 15 | * always follow this syntax: 16 | * 17 | * 0xAABBCC 18 | * 19 | * Where AA, BB, and CC are each major version, minor version, patch in hex 20 | * using 8 bits each. 21 | * 22 | * It should be safe to compare two different versions with the greater number 23 | * being the newer version. 24 | */ 25 | #define CJWT_VERSION_NUM @cjwt_BITWISE_VERSION@ 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /include/cjwt/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | version = meson.project_version() 5 | version_arr = version.split('.') 6 | major = version_arr[0].to_int() 7 | minor = version_arr[1].to_int() 8 | patch = version_arr[2].to_int() 9 | 10 | hex = '0123456789abcdef' 11 | ver = '0x@0@@1@@2@@3@@4@@5@' 12 | bitwise = ver.format(hex[major / 16], hex[major % 16], 13 | hex[minor / 16], hex[minor % 16], 14 | hex[patch / 16], hex[patch % 16]) 15 | 16 | cfg = configuration_data() 17 | cfg.set( meson.project_name()+'_VERSION', version) 18 | cfg.set( meson.project_name()+'_VERSION_MAJOR', major) 19 | cfg.set( meson.project_name()+'_VERSION_MINOR', minor) 20 | cfg.set( meson.project_name()+'_VERSION_PATCH', patch) 21 | cfg.set( meson.project_name()+'_BITWISE_VERSION', bitwise) 22 | 23 | ver_h = configure_file(input: 'cjwtver.h.in', 24 | output: 'cjwtver.h', 25 | configuration: cfg) 26 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | # Meson build file 2 | # 3 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | project('cjwt', 'c', 7 | version: '2.3.0', 8 | license: ['Apache-2.0'], 9 | meson_version: '>= 0.60.3', 10 | default_options: ['c_std=c99', 11 | 'b_coverage=true']) 12 | 13 | if not meson.is_subproject() 14 | # We want strict flags 15 | warning_level = 3 # -Wall 16 | werror = true 17 | endif 18 | 19 | ################################################################################ 20 | # Common variable definitions 21 | ################################################################################ 22 | 23 | inc_base = 'include/'+meson.project_name() 24 | 25 | ################################################################################ 26 | # Generate the version header file 27 | ################################################################################ 28 | 29 | subdir('include/'+meson.project_name()) 30 | 31 | ################################################################################ 32 | # Define the dependencies 33 | ################################################################################ 34 | openssl = dependency('openssl', version: '>=1.1.1', fallback:['openssl', 'openssl_dep']) 35 | libcjson_dep = dependency('libcjson', version: '>=1.7.14', fallback: ['cjson', 'libcjson_dep']) 36 | libtrower_base64_dep = dependency('trower-base64', version: '>=1.2.7') 37 | 38 | ################################################################################ 39 | # Define the libraries 40 | ################################################################################ 41 | 42 | inc = include_directories([inc_base]) 43 | 44 | install_headers([inc_base+'/cjwt.h', ver_h], subdir: meson.project_name()) 45 | 46 | tls = [] 47 | if openssl.version().startswith('1.1') 48 | tls = [ 'src/jws_openssl_1.c' ] 49 | else 50 | tls = [ 'src/jws_openssl_3.c' ] 51 | endif 52 | 53 | sources = ['src/cjwt.c', 54 | 'src/print.c', 55 | 'src/utils.c', 56 | tls ] 57 | 58 | libcjwt = library(meson.project_name(), 59 | sources, 60 | include_directories: inc, 61 | dependencies: [libcjson_dep, libtrower_base64_dep, openssl], 62 | install: true) 63 | 64 | ################################################################################ 65 | # Define the examples 66 | ################################################################################ 67 | if not meson.is_subproject() 68 | examples = ['hs_example', 'rs_example', 'es_example'] 69 | 70 | foreach e : examples 71 | executable(e, ['examples/basic/'+e+'.c'], 72 | include_directories: inc, 73 | dependencies: [libcjson_dep, libtrower_base64_dep, openssl], 74 | link_with: libcjwt) 75 | endforeach 76 | endif 77 | 78 | ################################################################################ 79 | # Define the tests 80 | ################################################################################ 81 | 82 | if not meson.is_subproject() 83 | test_args = ['-fprofile-arcs', '-ftest-coverage', '-O0'] 84 | 85 | if meson.get_compiler('c').get_id() != 'clang' 86 | if host_machine.system().contains('linux') 87 | v = run_command('valgrind', '--version', check: false) 88 | if v.returncode() == 0 89 | add_test_setup('valgrind', 90 | is_default: true, 91 | exe_wrapper: [ 'valgrind', 92 | '--leak-check=full', 93 | '--show-reachable=yes', 94 | '--error-exitcode=1' ], 95 | timeout_multiplier: 4) 96 | endif 97 | endif 98 | endif 99 | 100 | cunit_dep = dependency('cunit') 101 | common_deps = [cunit_dep, libcjson_dep, libtrower_base64_dep, openssl] 102 | 103 | test('test utils', 104 | executable('test_utils', 105 | ['tests/test_utils.c', 106 | 'src/utils.c'], 107 | include_directories: inc, 108 | dependencies: cunit_dep, 109 | link_args: test_args)) 110 | 111 | 112 | test('test print', 113 | executable('test_print', 114 | ['tests/test_print.c', 115 | 'src/cjwt.c', 116 | 'src/print.c', 117 | 'src/utils.c', 118 | tls ], 119 | include_directories: inc, 120 | dependencies: common_deps, 121 | link_args: test_args)) 122 | 123 | test('test cjwt new', 124 | executable('test_cjwt_new', 125 | ['tests/test_cjwt_new.c', 126 | 'src/cjwt.c', 127 | 'src/utils.c', 128 | tls ], 129 | include_directories: inc, 130 | dependencies: common_deps, 131 | link_args: test_args)) 132 | 133 | test('test cjwt', 134 | executable('test_cjwt', 135 | ['tests/test_cjwt.c', 136 | 'src/cjwt.c', 137 | 'src/utils.c', 138 | tls ], 139 | include_directories: inc, 140 | dependencies: common_deps, 141 | link_args: test_args)) 142 | 143 | test('test map', 144 | executable('test_map', 145 | ['tests/test_map.c', 146 | 'src/cjwt.c', 147 | 'src/utils.c', 148 | tls ], 149 | include_directories: inc, 150 | dependencies: common_deps, 151 | link_args: test_args)) 152 | 153 | 154 | endif 155 | 156 | ################################################################################ 157 | # Add the license check target 158 | ################################################################################ 159 | 160 | reuse_bin = find_program('reuse', required: false) 161 | if reuse_bin.found() 162 | custom_target('license', 163 | command: [reuse_bin, 'lint'], 164 | build_always_stale: true, 165 | output: ['license']) 166 | endif 167 | 168 | ################################################################################ 169 | # Add the coverity check target 170 | ################################################################################ 171 | 172 | alias_target('coverity', libcjwt ) 173 | 174 | ################################################################################ 175 | # External/consumer definitions 176 | ################################################################################ 177 | 178 | libcjwt_dep = declare_dependency(include_directories: ['include'], 179 | link_with: libcjwt) 180 | 181 | if meson.version().version_compare('>=0.54.0') 182 | meson.override_dependency(meson.project_name(), libcjwt_dep) 183 | endif 184 | -------------------------------------------------------------------------------- /src/jws.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #ifndef __JWS_H__ 5 | #define __JWS_H__ 6 | 7 | #include 8 | #include 9 | 10 | #include "cjwt.h" 11 | 12 | struct sig_section { 13 | const uint8_t *data; 14 | size_t len; 15 | }; 16 | 17 | struct sig_input { 18 | struct sig_section full; 19 | struct sig_section sig; 20 | struct sig_section key; 21 | }; 22 | 23 | cjwt_code_t jws_verify_signature(const cjwt_t *jwt, const struct sig_input *in); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/jws_openssl_1.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "cjwt.h" 15 | #include "jws.h" 16 | 17 | /*----------------------------------------------------------------------------*/ 18 | /* Macros */ 19 | /*----------------------------------------------------------------------------*/ 20 | /* none */ 21 | 22 | /*----------------------------------------------------------------------------*/ 23 | /* Data Structures */ 24 | /*----------------------------------------------------------------------------*/ 25 | /* none */ 26 | 27 | /*----------------------------------------------------------------------------*/ 28 | /* File Scoped Variables */ 29 | /*----------------------------------------------------------------------------*/ 30 | /* none */ 31 | 32 | /*----------------------------------------------------------------------------*/ 33 | /* Function Prototypes */ 34 | /*----------------------------------------------------------------------------*/ 35 | /* none */ 36 | 37 | /*----------------------------------------------------------------------------*/ 38 | /* Internal functions */ 39 | /*----------------------------------------------------------------------------*/ 40 | cjwt_code_t verify_hmac(const EVP_MD *sha, const struct sig_input *in) 41 | { 42 | cjwt_code_t rv = CJWTE_SIGNATURE_VALIDATION_FAILED; 43 | EVP_MD_CTX *md_ctx = NULL; 44 | EVP_PKEY *pkey = NULL; 45 | uint8_t buff[EVP_MAX_MD_SIZE]; 46 | size_t size = sizeof(buff); 47 | 48 | if (INT_MAX < in->key.len) { 49 | return CJWTE_KEY_TOO_LARGE; 50 | } 51 | 52 | md_ctx = EVP_MD_CTX_new(); 53 | pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, in->key.data, (int) in->key.len); 54 | 55 | if (md_ctx && pkey 56 | && (1 == EVP_DigestSignInit(md_ctx, NULL, sha, NULL, pkey)) 57 | && (1 == EVP_DigestSignUpdate(md_ctx, in->full.data, in->full.len)) 58 | && (1 == EVP_DigestSignFinal(md_ctx, buff, &size)) 59 | && (in->sig.len == size) 60 | && (0 == CRYPTO_memcmp(in->sig.data, buff, size))) 61 | { 62 | rv = CJWTE_OK; 63 | } 64 | 65 | if (pkey) { 66 | EVP_PKEY_free(pkey); 67 | } 68 | if (md_ctx) { 69 | EVP_MD_CTX_free(md_ctx); 70 | } 71 | return rv; 72 | } 73 | 74 | 75 | cjwt_code_t verify_es(const EVP_MD *sha, const struct sig_input *in) 76 | { 77 | cjwt_code_t rv = CJWTE_SIGNATURE_VALIDATION_FAILED; 78 | EVP_MD_CTX *md_ctx = NULL; 79 | EVP_PKEY_CTX *ctx = NULL; 80 | EVP_PKEY *pkey = NULL; 81 | EC_KEY *ec = NULL; 82 | BIO *keybio = NULL; 83 | ECDSA_SIG *ecdsa_sig = NULL; 84 | BIGNUM *pr = NULL; 85 | BIGNUM *ps = NULL; 86 | int new_sig_len = 0; 87 | uint8_t *new_sig = NULL; 88 | uint8_t digest[EVP_MAX_MD_SIZE]; 89 | unsigned int dig_len = 0; 90 | 91 | if ((0 == in->key.len) || (NULL == in->key.data)) { 92 | return CJWTE_SIGNATURE_MISSING_KEY; 93 | } 94 | 95 | if (INT_MAX < in->sig.len) { 96 | return CJWTE_SIGNATURE_KEY_TOO_LARGE; 97 | } 98 | 99 | /* Read the ECDSA key in from a PEM encoded blob of memory */ 100 | keybio = BIO_new_mem_buf(in->key.data, (int) in->key.len); 101 | if (!keybio) { 102 | return CJWTE_OUT_OF_MEMORY; 103 | } 104 | 105 | ec = PEM_read_bio_EC_PUBKEY(keybio, &ec, NULL, NULL); 106 | BIO_free(keybio); 107 | if (!ec) { 108 | return CJWTE_SIGNATURE_INVALID_KEY; 109 | } 110 | 111 | pkey = EVP_PKEY_new(); 112 | md_ctx = EVP_MD_CTX_new(); 113 | ecdsa_sig = ECDSA_SIG_new(); 114 | 115 | /* Read out the r,s numbers from the signature for later. 116 | * We must convert from this format into DEC because that's 117 | * all openssl supports. */ 118 | pr = BN_bin2bn(in->sig.data, (int) in->sig.len / 2, NULL); 119 | ps = BN_bin2bn(in->sig.data + in->sig.len / 2, (int) in->sig.len / 2, NULL); 120 | 121 | /* Setup the pkey */ 122 | if (pkey && ec && (1 == EVP_PKEY_assign_EC_KEY(pkey, ec))) { 123 | /* pkey owns the ec memory, don't free it. */ 124 | ec = NULL; 125 | ctx = EVP_PKEY_CTX_new(pkey, NULL); 126 | } 127 | 128 | if (md_ctx && pkey && ecdsa_sig && ctx 129 | /* Setup the sha digest buffer */ 130 | && (1 == EVP_DigestInit_ex(md_ctx, sha, NULL)) 131 | && (1 == EVP_DigestUpdate(md_ctx, in->full.data, in->full.len)) 132 | && (1 == EVP_DigestFinal_ex(md_ctx, digest, &dig_len)) 133 | /* Rebuild the signature in DEC format */ 134 | && (1 == ECDSA_SIG_set0(ecdsa_sig, pr, ps))) 135 | { 136 | new_sig_len = i2d_ECDSA_SIG(ecdsa_sig, &new_sig); 137 | } 138 | 139 | if (0 < new_sig_len) { 140 | pr = NULL; /* We don't own the memory, don't free it. */ 141 | ps = NULL; /* We don't own the memory, don't free it. */ 142 | } 143 | 144 | if (ctx && new_sig && (0 < new_sig_len) 145 | && (1 == EVP_PKEY_verify_init(ctx)) 146 | && (1 == EVP_PKEY_verify(ctx, new_sig, new_sig_len, digest, dig_len))) 147 | { 148 | rv = CJWTE_OK; 149 | } 150 | 151 | if (new_sig) OPENSSL_free(new_sig); 152 | if (ps) BN_free(ps); 153 | if (pr) BN_free(pr); 154 | if (ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); 155 | if (md_ctx) EVP_MD_CTX_free(md_ctx); 156 | if (pkey) EVP_PKEY_free(pkey); 157 | if (ctx) EVP_PKEY_CTX_free(ctx); 158 | if (ec) EC_KEY_free(ec); 159 | 160 | return rv; 161 | } 162 | 163 | 164 | cjwt_code_t verify_rsa(const EVP_MD *sha, const struct sig_input *in, int padding) 165 | { 166 | cjwt_code_t rv = CJWTE_SIGNATURE_VALIDATION_FAILED; 167 | EVP_MD_CTX *md_ctx = NULL; 168 | EVP_PKEY_CTX *pkey_ctx = NULL; 169 | EVP_PKEY *pkey = NULL; 170 | RSA *rsa = NULL; 171 | BIO *keybio = NULL; 172 | 173 | if ((0 == in->key.len) || (NULL == in->key.data)) { 174 | return CJWTE_SIGNATURE_MISSING_KEY; 175 | } 176 | 177 | /* Read the RSA key in from a PEM encoded blob of memory */ 178 | keybio = BIO_new_mem_buf(in->key.data, (int) in->key.len); 179 | if (!keybio) { 180 | return CJWTE_OUT_OF_MEMORY; 181 | } 182 | 183 | rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL); 184 | BIO_free(keybio); 185 | if (!rsa) { 186 | return CJWTE_SIGNATURE_INVALID_KEY; 187 | } 188 | 189 | pkey = EVP_PKEY_new(); 190 | md_ctx = EVP_MD_CTX_create(); 191 | 192 | if (md_ctx && pkey 193 | && (1 == EVP_PKEY_assign_RSA(pkey, rsa)) 194 | && (1 == EVP_DigestInit_ex(md_ctx, sha, NULL)) 195 | && (1 == EVP_DigestVerifyInit(md_ctx, &pkey_ctx, sha, NULL, pkey)) 196 | && (0 < EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding)) 197 | && (1 == EVP_DigestVerifyUpdate(md_ctx, in->full.data, in->full.len)) 198 | && (1 == EVP_DigestVerifyFinal(md_ctx, in->sig.data, in->sig.len))) 199 | { 200 | rv = CJWTE_OK; 201 | } 202 | 203 | if (pkey) EVP_PKEY_free(pkey); 204 | if (md_ctx) EVP_MD_CTX_free(md_ctx); 205 | 206 | return rv; 207 | } 208 | 209 | 210 | /*----------------------------------------------------------------------------*/ 211 | /* External Functions */ 212 | /*----------------------------------------------------------------------------*/ 213 | cjwt_code_t jws_verify_signature(const cjwt_t *jwt, const struct sig_input *in) 214 | { 215 | switch (jwt->header.alg) { 216 | case alg_es256: 217 | return verify_es(EVP_sha256(), in); 218 | case alg_es384: 219 | return verify_es(EVP_sha384(), in); 220 | case alg_es512: 221 | return verify_es(EVP_sha512(), in); 222 | 223 | case alg_hs256: 224 | return verify_hmac(EVP_sha256(), in); 225 | case alg_hs384: 226 | return verify_hmac(EVP_sha384(), in); 227 | case alg_hs512: 228 | return verify_hmac(EVP_sha512(), in); 229 | 230 | case alg_ps256: 231 | return verify_rsa(EVP_sha256(), in, RSA_PKCS1_PSS_PADDING); 232 | case alg_ps384: 233 | return verify_rsa(EVP_sha384(), in, RSA_PKCS1_PSS_PADDING); 234 | case alg_ps512: 235 | return verify_rsa(EVP_sha512(), in, RSA_PKCS1_PSS_PADDING); 236 | 237 | case alg_rs256: 238 | return verify_rsa(EVP_sha256(), in, RSA_PKCS1_PADDING); 239 | case alg_rs384: 240 | return verify_rsa(EVP_sha384(), in, RSA_PKCS1_PADDING); 241 | case alg_rs512: 242 | return verify_rsa(EVP_sha512(), in, RSA_PKCS1_PADDING); 243 | 244 | default: 245 | break; 246 | } 247 | 248 | return CJWTE_SIGNATURE_UNSUPPORTED_ALG; 249 | } 250 | -------------------------------------------------------------------------------- /src/jws_openssl_3.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "cjwt.h" 15 | #include "jws.h" 16 | 17 | /*----------------------------------------------------------------------------*/ 18 | /* Macros */ 19 | /*----------------------------------------------------------------------------*/ 20 | /* none */ 21 | 22 | /*----------------------------------------------------------------------------*/ 23 | /* Data Structures */ 24 | /*----------------------------------------------------------------------------*/ 25 | /* none */ 26 | 27 | /*----------------------------------------------------------------------------*/ 28 | /* File Scoped Variables */ 29 | /*----------------------------------------------------------------------------*/ 30 | /* none */ 31 | 32 | /*----------------------------------------------------------------------------*/ 33 | /* Function Prototypes */ 34 | /*----------------------------------------------------------------------------*/ 35 | /* none */ 36 | 37 | /*----------------------------------------------------------------------------*/ 38 | /* Internal functions */ 39 | /*----------------------------------------------------------------------------*/ 40 | cjwt_code_t verify_hmac(const EVP_MD *sha, const struct sig_input *in) 41 | { 42 | cjwt_code_t rv = CJWTE_SIGNATURE_VALIDATION_FAILED; 43 | EVP_MD_CTX *md_ctx = NULL; 44 | EVP_PKEY *pkey = NULL; 45 | uint8_t buff[EVP_MAX_MD_SIZE]; 46 | size_t size = sizeof(buff); 47 | 48 | if (INT_MAX < in->key.len) { 49 | return CJWTE_KEY_TOO_LARGE; 50 | } 51 | 52 | md_ctx = EVP_MD_CTX_new(); 53 | pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, in->key.data, (int) in->key.len); 54 | 55 | if (md_ctx && pkey 56 | && (1 == EVP_DigestSignInit(md_ctx, NULL, sha, NULL, pkey)) 57 | && (1 == EVP_DigestSignUpdate(md_ctx, in->full.data, in->full.len)) 58 | && (1 == EVP_DigestSignFinal(md_ctx, buff, &size)) 59 | && (in->sig.len == size) 60 | && (0 == CRYPTO_memcmp(in->sig.data, buff, size))) 61 | { 62 | rv = CJWTE_OK; 63 | } 64 | 65 | EVP_PKEY_free(pkey); 66 | EVP_MD_CTX_free(md_ctx); 67 | return rv; 68 | } 69 | 70 | int add_padding(int type, EVP_PKEY_CTX *ctx, int padding) 71 | { 72 | if (EVP_PKEY_EC == type) { 73 | return 1; 74 | } 75 | 76 | return EVP_PKEY_CTX_set_rsa_padding(ctx, padding); 77 | } 78 | 79 | int calc_sig(int type, const struct sig_input *in, uint8_t **sig, int *len) 80 | { 81 | int rv = 0; /* Match the other openssl symantics for consistency */ 82 | ECDSA_SIG *ecdsa_sig = NULL; 83 | BIGNUM *pr = NULL; 84 | BIGNUM *ps = NULL; 85 | int new_sig_len = 0; 86 | uint8_t *new_sig = NULL; 87 | 88 | if (EVP_PKEY_RSA == type) { 89 | *sig = (uint8_t *) in->sig.data; 90 | *len = in->sig.len; 91 | return 1; 92 | } 93 | 94 | ecdsa_sig = ECDSA_SIG_new(); 95 | if (ecdsa_sig == NULL) { 96 | return 0; 97 | } 98 | 99 | /* Read out the r,s numbers from the signature for later. 100 | * We must convert from this format into DEC because that's 101 | * all openssl supports. */ 102 | pr = BN_bin2bn(in->sig.data, (int) in->sig.len / 2, NULL); 103 | ps = BN_bin2bn(in->sig.data + in->sig.len / 2, (int) in->sig.len / 2, NULL); 104 | 105 | if (1 == ECDSA_SIG_set0(ecdsa_sig, pr, ps)) { 106 | new_sig_len = i2d_ECDSA_SIG(ecdsa_sig, &new_sig); 107 | if (0 <= new_sig_len) { 108 | /* We don't own the memory now, don't free it. */ 109 | pr = NULL; 110 | ps = NULL; 111 | 112 | if (0 < new_sig_len) { 113 | *sig = new_sig; 114 | *len = new_sig_len; 115 | new_sig = NULL; /* Passed back now, so don't free the buffer. */ 116 | rv = 1; 117 | } 118 | } 119 | } 120 | 121 | OPENSSL_free(new_sig); 122 | ECDSA_SIG_free(ecdsa_sig); 123 | BN_free(ps); 124 | BN_free(pr); 125 | 126 | return rv; 127 | } 128 | 129 | cjwt_code_t verify_most(const EVP_MD *sha, const struct sig_input *in, int type, int padding) 130 | { 131 | cjwt_code_t rv = CJWTE_SIGNATURE_VALIDATION_FAILED; 132 | EVP_MD_CTX *md_ctx = NULL; 133 | EVP_PKEY_CTX *pkey_ctx = NULL; 134 | EVP_PKEY *pkey = NULL; 135 | BIO *keybio = NULL; 136 | int sig_len = 0; 137 | uint8_t *sig = NULL; 138 | 139 | if ((0 == in->key.len) || (NULL == in->key.data)) { 140 | return CJWTE_SIGNATURE_MISSING_KEY; 141 | } 142 | 143 | /* Read the RSA key in from a PEM encoded blob of memory */ 144 | keybio = BIO_new_mem_buf(in->key.data, (int) in->key.len); 145 | if (!keybio) { 146 | return CJWTE_OUT_OF_MEMORY; 147 | } 148 | 149 | pkey = PEM_read_bio_PUBKEY(keybio, NULL, NULL, NULL); 150 | if (!pkey) { 151 | rv = CJWTE_SIGNATURE_INVALID_KEY; 152 | goto done; 153 | } 154 | 155 | if (type != EVP_PKEY_id(pkey)) { 156 | rv = CJWTE_SIGNATURE_INVALID_KEY; 157 | goto done; 158 | } 159 | 160 | md_ctx = EVP_MD_CTX_create(); 161 | 162 | if (md_ctx 163 | && (1 == calc_sig(type, in, &sig, &sig_len)) 164 | && (1 == EVP_DigestVerifyInit(md_ctx, &pkey_ctx, sha, NULL, pkey)) 165 | && (0 < add_padding(type, pkey_ctx, padding)) 166 | && (1 == EVP_DigestVerifyUpdate(md_ctx, in->full.data, in->full.len)) 167 | && (1 == EVP_DigestVerifyFinal(md_ctx, sig, sig_len))) 168 | { 169 | rv = CJWTE_OK; 170 | } 171 | 172 | done: 173 | 174 | if (sig != in->sig.data) OPENSSL_free(sig); 175 | 176 | BIO_free(keybio); 177 | EVP_PKEY_free(pkey); 178 | EVP_MD_CTX_free(md_ctx); 179 | 180 | return rv; 181 | } 182 | 183 | 184 | /*----------------------------------------------------------------------------*/ 185 | /* External Functions */ 186 | /*----------------------------------------------------------------------------*/ 187 | cjwt_code_t jws_verify_signature(const cjwt_t *jwt, const struct sig_input *in) 188 | { 189 | switch (jwt->header.alg) { 190 | case alg_es256: 191 | return verify_most(EVP_sha256(), in, EVP_PKEY_EC, 0); 192 | case alg_es384: 193 | return verify_most(EVP_sha384(), in, EVP_PKEY_EC, 0); 194 | case alg_es512: 195 | return verify_most(EVP_sha512(), in, EVP_PKEY_EC, 0); 196 | 197 | case alg_hs256: 198 | return verify_hmac(EVP_sha256(), in); 199 | case alg_hs384: 200 | return verify_hmac(EVP_sha384(), in); 201 | case alg_hs512: 202 | return verify_hmac(EVP_sha512(), in); 203 | 204 | case alg_ps256: 205 | return verify_most(EVP_sha256(), in, EVP_PKEY_RSA, RSA_PKCS1_PSS_PADDING); 206 | case alg_ps384: 207 | return verify_most(EVP_sha384(), in, EVP_PKEY_RSA, RSA_PKCS1_PSS_PADDING); 208 | case alg_ps512: 209 | return verify_most(EVP_sha512(), in, EVP_PKEY_RSA, RSA_PKCS1_PSS_PADDING); 210 | 211 | case alg_rs256: 212 | return verify_most(EVP_sha256(), in, EVP_PKEY_RSA, RSA_PKCS1_PADDING); 213 | case alg_rs384: 214 | return verify_most(EVP_sha384(), in, EVP_PKEY_RSA, RSA_PKCS1_PADDING); 215 | case alg_rs512: 216 | return verify_most(EVP_sha512(), in, EVP_PKEY_RSA, RSA_PKCS1_PADDING); 217 | 218 | default: 219 | break; 220 | } 221 | 222 | return CJWTE_SIGNATURE_UNSUPPORTED_ALG; 223 | } 224 | -------------------------------------------------------------------------------- /src/print.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "cjwt.h" 10 | 11 | /*----------------------------------------------------------------------------*/ 12 | /* Macros */ 13 | /*----------------------------------------------------------------------------*/ 14 | /* none */ 15 | 16 | /*----------------------------------------------------------------------------*/ 17 | /* Data Structures */ 18 | /*----------------------------------------------------------------------------*/ 19 | /* none */ 20 | 21 | /*----------------------------------------------------------------------------*/ 22 | /* File Scoped Variables */ 23 | /*----------------------------------------------------------------------------*/ 24 | /* none */ 25 | 26 | /*----------------------------------------------------------------------------*/ 27 | /* Function Prototypes */ 28 | /*----------------------------------------------------------------------------*/ 29 | extern const char *alg_to_string(cjwt_alg_t alg); 30 | static const char *str(const char *s); 31 | static void priv(FILE *stream, cJSON *list); 32 | 33 | /*----------------------------------------------------------------------------*/ 34 | /* External Functions */ 35 | /*----------------------------------------------------------------------------*/ 36 | void cjwt_print(FILE *stream, cjwt_t *jwt) 37 | { 38 | if (!jwt) { 39 | fprintf(stream, 40 | "=====================\n" 41 | "jwt is NULL\n" 42 | "=====================\n"); 43 | return; 44 | } 45 | 46 | fprintf(stream, 47 | "=====================\n" 48 | "header\n" 49 | "---------------------\n" 50 | " alg: %s\n" 51 | " kid: %s\n" 52 | " private_headers:\n\n", 53 | alg_to_string(jwt->header.alg), 54 | str(jwt->header.kid)); 55 | 56 | priv(stream, jwt->header.private_headers); 57 | 58 | 59 | fprintf(stream, 60 | "payload\n" 61 | "---------------------\n"); 62 | 63 | if (jwt->iat) { 64 | fprintf(stream, " iat: %" PRId64 "\n\n", *jwt->iat); 65 | } else { 66 | fprintf(stream, " iat: NULL\n\n"); 67 | } 68 | if (jwt->exp) { 69 | fprintf(stream, " exp: %" PRId64 "\n", *jwt->exp); 70 | } else { 71 | fprintf(stream, " exp: NULL\n"); 72 | } 73 | if (jwt->nbf) { 74 | fprintf(stream, " nbf: %" PRId64 "\n\n", *jwt->nbf); 75 | } else { 76 | fprintf(stream, " nbf: NULL\n\n"); 77 | } 78 | fprintf(stream, " iss: %s\n", str(jwt->iss)); 79 | fprintf(stream, " sub: %s\n", str(jwt->sub)); 80 | fprintf(stream, " jti: %s\n", str(jwt->jti)); 81 | fprintf(stream, " aud: "); 82 | if (0 == jwt->aud.count) { 83 | fprintf(stream, "NULL\n"); 84 | } else { 85 | const char *comma = ""; 86 | for (int i = 0; i < jwt->aud.count; i++) { 87 | fprintf(stream, "%s%s", comma, jwt->aud.names[i]); 88 | comma = ", "; 89 | } 90 | fprintf(stream, "\n"); 91 | } 92 | 93 | fprintf(stream, 94 | "\nprivate claims\n" 95 | "---------------------\n"); 96 | priv(stream, jwt->private_claims); 97 | fprintf(stream, "=====================\n"); 98 | } 99 | 100 | 101 | /*----------------------------------------------------------------------------*/ 102 | /* Internal functions */ 103 | /*----------------------------------------------------------------------------*/ 104 | static const char *str(const char *s) 105 | { 106 | if (NULL == s) { 107 | return "NULL"; 108 | } 109 | 110 | return s; 111 | } 112 | 113 | static void priv(FILE *stream, cJSON *list) 114 | { 115 | if (list) { 116 | char *text = NULL; 117 | 118 | text = cJSON_Print(list); 119 | fprintf(stream, "%s\n", text); 120 | cJSON_free(text); 121 | } else { 122 | fprintf(stream, "(none)\n"); 123 | } 124 | fprintf(stream, "=====================\n"); 125 | } 126 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #include 5 | 6 | #include "utils.h" 7 | 8 | /*----------------------------------------------------------------------------*/ 9 | /* Macros */ 10 | /*----------------------------------------------------------------------------*/ 11 | /* none */ 12 | 13 | /*----------------------------------------------------------------------------*/ 14 | /* Data Structures */ 15 | /*----------------------------------------------------------------------------*/ 16 | /* none */ 17 | 18 | /*----------------------------------------------------------------------------*/ 19 | /* File Scoped Variables */ 20 | /*----------------------------------------------------------------------------*/ 21 | /* none */ 22 | 23 | /*----------------------------------------------------------------------------*/ 24 | /* Function Prototypes */ 25 | /*----------------------------------------------------------------------------*/ 26 | /* none */ 27 | 28 | /*----------------------------------------------------------------------------*/ 29 | /* External Functions */ 30 | /*----------------------------------------------------------------------------*/ 31 | int split(const char *full, size_t len, struct split_jwt *split) 32 | { 33 | size_t dots[6] = { 0, len, len, len, len, len }; 34 | 35 | memset(split, 0, sizeof(struct split_jwt)); 36 | 37 | split->count = 1; 38 | for (size_t i = 0; i < len; i++) { 39 | if ('.' == full[i]) { 40 | if (4 < split->count) { 41 | /* Too many sections */ 42 | return -1; 43 | } 44 | dots[split->count] = i; 45 | split->count++; 46 | } 47 | } 48 | 49 | if (1 == split->count) { 50 | return -1; 51 | } 52 | 53 | split->sections[0].data = full; 54 | split->sections[0].len = dots[1]; 55 | 56 | for (size_t i = 1; i < split->count; i++) { 57 | split->sections[i].data = &full[dots[i] + 1]; 58 | split->sections[i].len = dots[i + 1] - dots[i] - 1; 59 | } 60 | 61 | return 0; 62 | } 63 | 64 | 65 | char *cjwt_strdup(const char *s) 66 | { 67 | char *rv = NULL; 68 | 69 | if (s) { 70 | size_t len; 71 | 72 | len = strlen(s) + 1; 73 | rv = (char *) malloc(len); 74 | if (rv) { 75 | memcpy(rv, s, len); 76 | } 77 | } 78 | 79 | return rv; 80 | } 81 | 82 | 83 | /*----------------------------------------------------------------------------*/ 84 | /* Internal functions */ 85 | /*----------------------------------------------------------------------------*/ 86 | /* none */ 87 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | 4 | #ifndef __UTILS_H__ 5 | #define __UTILS_H__ 6 | 7 | #include 8 | #include 9 | 10 | struct section { 11 | const char *data; 12 | size_t len; 13 | }; 14 | 15 | struct split_jwt { 16 | size_t count; 17 | struct section sections[5]; 18 | }; 19 | 20 | int split(const char *full, size_t len, struct split_jwt *split); 21 | 22 | char *cjwt_strdup(const char *s); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /subprojects/cjson.wrap: -------------------------------------------------------------------------------- 1 | [wrap-file] 2 | directory = cJSON-1.7.14 3 | source_url = https://github.com/DaveGamble/cJSON/archive/refs/tags/v1.7.14.tar.gz 4 | source_filename = v1.7.14.tar.gz 5 | source_hash = fb50a663eefdc76bafa80c82bc045af13b1363e8f45cec8b442007aef6a41343 6 | patch_filename = cjson_1.7.14-1_patch.zip 7 | patch_url = https://wrapdb.mesonbuild.com/v2/cjson_1.7.14-1/get_patch 8 | patch_hash = 82d7a029637bdd6696a89075907581768e7088c20b1c69f400cb6e15e716d803 9 | 10 | [provide] 11 | libcjson = libcjson_dep 12 | 13 | -------------------------------------------------------------------------------- /subprojects/trower-base64.wrap: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Comcast Cable Communications Management, LLC 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | [wrap-file] 5 | directory = trower-base64-1.2.7 6 | 7 | source_filename = trower-base64-1.2.7.tar.gz 8 | source_url = https://github.com/xmidt-org/trower-base64/releases/download/v1.2.7/trower-base64-1.2.7.tar.gz 9 | source_hash = 9921ea1eca2328c6cadc058df805e6ac58cca06c0737ac21b987ba13b8697ad9 10 | 11 | [provide] 12 | libtrower_base64 = libtrower_base64_dep 13 | -------------------------------------------------------------------------------- /tests/inputs/badkey4.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7C8R+hmRcVOuLxi/Qjc9 3 | 4S0qAm+03JGm4G1aejyEcvXChMH6p0P9qIaq3aJTAOj3q7tvg4AbNYid7iTUnPvF 4 | xaYVI9CZtoFbplX3JUmUxJDOMSOA9wAV59D4+vz7OUpMfaV5NyiPfPJLAbHnA/hT 5 | agT4JilhtBqfiUqzxMALQOGQT/+L7QhsRBc0QkjkgZE4du59X9PDOD47GPrzL8k1 6 | Reu8uGW951iR6WtcjgZR4ndMSNd/CjxAZfvVWotQMEVm4ZaudiPfiFYwqDe1IvSm 7 | 0YH3dtUiRS4d4Q8OsUqzarXFPpr7+RriwMRxebQnBqQICryob40FOL/n4ZRlu+85 8 | FQIDAQAA 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/inputs/badkey5.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAve4r4LAbo9yvKDN3uyQK 3 | u1Kp8O62p0j+Mah4Ntn8X9Kubg+JCXZ7ebY01QomphbVo5tDha7V7rSlJGN2LxXP 4 | Nw1Cq3iA3J5W6sIrUtFeCaUeMSkBJ4VJtlHh655JEJjm0uh4X0gSjdITtYW1MzYm 5 | 9z7Axa/Pv5jQZEM0+xftPvdWBAukeZy8DHJBDzqUMqBFzXGsFqdy94DY538ZyGFF 6 | Rwl4DkTQxhdN820Ovfiy5KkwrO0wv2Xt2QX6zFrtChJwqm+kATKhU/wfoSYhvSy2 7 | Z2hIztBaqyAI1rXNp57/nxRAgbcyVR3twWZqNYbtFX10tc9Zpaj7tDgMgG7kLI4n 8 | dQIDAQABC 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/inputs/badkey6.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | XIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4UxC3y4Pd5BEYTSMR6GR 3 | iPFl1NKAcEhQbwnYpztMMiHJGn9geJyaUErWAKXa4B7S+UsIRzKWFHPrqYlAQpoZ 4 | c1EjdW2Qwv4aAbj0tQe2uv70f9nzlpz0mM1ce8Xb4fXCsypwIxLdN3mcwnrkmWyy 5 | vfBF8lZ3ptof+MKEgA3v0ZI0bs49EkAfyZkm6Rg8uaJqDSkHpo87A9G5GROfLRpf 6 | tjcbWGKPP69uTsGh46hZ784nVQ5/Wb9teAW/niTEqU0K73IZ+4Qy28FOR9f5O75n 7 | 3zgmFT7SL7hI4aTYN7Hxjw7bsHGZI965b93x52oRGgLOOqFQIRty9a1XjIBetiB4 8 | PQIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/inputs/jwt1.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.MAWYApFqPqS6u3uZ6uZtTSgMi5iEy4V4tpHL_bdTULw -------------------------------------------------------------------------------- /tests/inputs/jwt10_hs512.txt: -------------------------------------------------------------------------------- 1 | eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJmaWxlcy5jeXBocmUuY29tIiwic3ViIjoidXNlcjAifQ.u-4XQB1xlYV8SgAnKBof8fOWOtfyNtc1ytTlc_vHo0Ulh5uGT238te6kSacnVzBbC6qwzVMT1806oa1Y8_8EOg -------------------------------------------------------------------------------- /tests/inputs/jwt11.txt: -------------------------------------------------------------------------------- 1 | eyJraWQiOiJzYXQtcHJvZC1rMS0xMDI0IiwiYWxnIjoiUlMyNTYifQ.eyJqdGkiOiJmYWRkMjQ2Yi1hZjAwLTQyNTgtOTNlNS1lOGUyMWIyZWU1OWQiLCJpc3MiOiJzYXRzLXByb2R1Y3Rpb24iLCJzdWIiOiJ4MTp3ZWJwYS10ZXN0aW5nOjUyMzRmZSIsImlhdCI6MTQ4NzM3NTU3MywibmJmIjoxNDg3Mzc1NTczLCJleHAiOjE0ODczNzkxNzYsInZlcnNpb24iOiIxLjAiLCJhbGxvd2VkUmVzb3VyY2VzIjp7ImFsbG93ZWRQYXJ0bmVycyI6WyJjb21jYXN0Il19LCJjYXBhYmlsaXRpZXMiOlsieDE6d2VicGE6YXBpOi4qOmFsbCJdLCJhdWQiOltdfQ.BK69GgJgN24JVKY-kJGTAdQpC6R45Efyb772AfvE-_MkNjXENedctAELlftUmPlEh67uZ9IppPK2TUU8-8FdoRitQ0m2b1ZSALtHisslmp8l6_s8OlnOLebPZrGtn6fm-AuV6mi-uJmBvmoh5j2BcMY8AbOGfwxhgTcmtKt5dgk 2 | -------------------------------------------------------------------------------- /tests/inputs/jwt12.txt: -------------------------------------------------------------------------------- 1 | eyJraWQiOiJzYXQtcHJvZC1rMS0xMDI0IiwiYWxnIjoiUlMyNTYifQ.eyJqdGkiOiI4NTJlZjBkNy1mMzE5LTQzMjItYjcyMy1iYzdiNTg3Yzc1YWIiLCJpc3MiOiJzYXRzLXByb2R1Y3Rpb24iLCJzdWIiOiJ4MTp3ZWJwYS10ZXN0aW5nOjUyMzRmZSIsImlhdCI6MTQ4OTAwNTk2MiwibmJmIjoxNDg5MDA1OTYyLCJleHAiOjE0ODkwOTIzNjUsInZlcnNpb24iOiIxLjAiLCJhbGxvd2VkUmVzb3VyY2VzIjp7ImFsbG93ZWRQYXJ0bmVycyI6WyJjb21jYXN0Il19LCJjYXBhYmlsaXRpZXMiOlsieDE6d2VicGE6YXBpOi4qOmFsbCJdLCJhdWQiOltdfQ.VSJxw4zFTv364QxNw-ia_RwaZQGnceON3e0uQnX2d-LMm-4lb9x5JRhAsDITiSf4BqpNfajNAn31DKjJJuHn00S6fNSQzaaoQoPXksUO_90_HXQoCRHtpdK3093qx0QbXUQHqpdAalj-E8GbYpvgfq4eiVvEpiW1EgLQO3wJ1OY 2 | -------------------------------------------------------------------------------- /tests/inputs/jwt13.txt: -------------------------------------------------------------------------------- 1 | eyJraWQiOiJzYXQtcHJvZC1rMS0xMDI0IiwiYWxnIjoiUlMyNTYifQ.eyJqdGkiOiIwYWMzNjEwNC1lYjA1LTQzOGMtYTk2MS03ODQ1M2E2OTFlYWQiLCJpc3MiOiJzYXRzLXByb2R1Y3Rpb24iLCJzdWIiOiJ4MTp3ZWJwYS10ZXN0aW5nOjUyMzRmZSIsImlhdCI6MTQ4OTE5MzQ5OSwibmJmIjoxNDg5MTkzNDk5LCJleHAiOjE0ODkyNzk5MDIsInZlcnNpb24iOiIxLjAiLCJhbGxvd2VkUmVzb3VyY2VzIjp7ImFsbG93ZWRQYXJ0bmVycyI6WyJjb21jYXN0Il19LCJjYXBhYmlsaXRpZXMiOlsieDE6d2VicGE6YXBpOi4qOmFsbCJdLCJhdWQiOltdfQ.DsWJW7MwzS6ZiuWMzs-LwmxwX9jNNTsDPNMMVNaHBWG9l6QUEvKOCtApVD_pZeBMrTyCUAh30F4nkQ6CugIof4Adam1fTLSE9ypbddLRs6i9JQS40M3zvF7lmRnAGCuOC9X6w30FV81WSRQEKdvxQJ0a_vcV31HU6LZElCosu6g -------------------------------------------------------------------------------- /tests/inputs/jwt1l.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkdW1wIjoiMCIsInBpbmdQZXJpb2QiOiIxMHMiLCJodHRwVGltZW91dCI6IjkwcyIsInBvcnQiOjgwODAsIkRldmljZU5ldHdvcmtJbnRlcmZhY2UiOiJlbnAyczEiLCJoY3BvcnQiOjg4ODgsImxvZyI6eyJtYXhCYWNrdXAiOjk5OTksIm1heFNpemUiOjIwMDAwMDAsImZpbGUiOiJzZXJ2ZXJfbG9ncy90YWxhcmlhTG9nLmxvZyIsImxldmVsIjoiREVCVUcifSwicGFyYW1ldGVycyI6W3siZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLlhfQ09NQ0FTVC1DT01fQ01fTUFDIiwidmFsdWUiOiJtYWM6MTEyMjMzNDQ1NTk5In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uV2VicGEuWF9DT01DQVNULUNPTV9DSUQiLCJ2YWx1ZSI6IjEyMzQifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuRGV2aWNlSW5mby5XZWJwYS5YX0NPTUNBU1QtQ09NX0NNQyIsInZhbHVlIjoiNzcyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uV2VicGEuWF9DT01DQVNULUNPTV9GaXJtd2FyZVZlcnNpb24iLCJ2YWx1ZSI6IjEuMCJ9LHsiZGF0YVR5cGUiOiIyIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLldlYnBhLlhfQ09NQ0FTVC1DT01fRGV2aWNlVXBUaW1lIiwidmFsdWUiOiIwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uTWFudWZhY3R1cmVyIiwidmFsdWUiOiJBUlJJUyBHcm91cCwgSW5jLiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLk1vZGVsTmFtZSIsInZhbHVlIjoiVEcxNjgyRyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5ESENQdjQuQ2xpZW50LjEuSVBSb3V0ZXJzIiwidmFsdWUiOiIxMC4yNTUuMjQ1LjEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuSVAuSW50ZXJmYWNlLjEuSVB2NkFkZHJlc3MuMS5JUEFkZHJlc3MiLCJ2YWx1ZSI6ImZlODA6OmJlY2E6YjVmZjpmZWYxOjlhMzQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuSVAuSW50ZXJmYWNlLjEuSVB2NkFkZHJlc3MuMi5JUEFkZHJlc3MiLCJ2YWx1ZSI6IjIwMDE6NTU4OmZmMjM6YjpiODYyOjg5Yjk6YzFjMjpiNzI2In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS4xLklQdjZQcmVmaXguMS5QcmVmaXgiLCJ2YWx1ZSI6IjIwMDE6NTU4OmZmM2I6YTA6Oi82NCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5JUC5JbnRlcmZhY2UuMy5JUHY2QWRkcmVzcy4xLklQQWRkcmVzcyIsInZhbHVlIjoiOjoxIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS40LklQdjZBZGRyZXNzLjEuSVBBZGRyZXNzIiwidmFsdWUiOiJmZTgwOjpiZWNhOmI1ZmY6ZmVmMTo5YTM3In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS40LklQdjZBZGRyZXNzLjIuSVBBZGRyZXNzIiwidmFsdWUiOiIyMDAxOjU1ODpmZjNiOmEwOmJlY2E6YjVmZjpmZWYxOjlhMzcifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy4xMC5OZXh0SG9wIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy4xLk5leHRIb3AiLCJ2YWx1ZSI6IiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjIuTmV4dEhvcCIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuMy5OZXh0SG9wIiwidmFsdWUiOiJmZTgwOjoyMDE6NWNmZjpmZTRmOjZlNDEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy40Lk5leHRIb3AiLCJ2YWx1ZSI6IiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjUuTmV4dEhvcCIsInZhbHVlIjoiZmU4MDo6MjAxOjVjZmY6ZmU0Zjo2ZTQxIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuNi5OZXh0SG9wIiwidmFsdWUiOiJmZTgwOjoyMDE6NWNmZjpmZTRmOjZlNDEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy43Lk5leHRIb3AiLCJ2YWx1ZSI6ImZlODA6OjIwMTo1Y2ZmOmZlNGY6NmU0MSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjguTmV4dEhvcCIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuOS5OZXh0SG9wIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJwYXNzd29yZCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMDAxLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMDAxLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkRlbnkifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiI1NTVDODQzNDUxMTZCQkI4QjQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDIuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDMuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDQuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDUuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDYuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDcuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDguWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJwYXNzd29yZCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAxLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAxLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6IjU1NUM4NDM0NTExNkJCQjhCNCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMi5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMy5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNC5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNi5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNy5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwOC5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIxIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlRyYW5zbWl0UG93ZXIiLCJ2YWx1ZSI6IjEwMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlhfQ0lTQ09fQ09NX0Jhc2ljUmF0ZSIsInZhbHVlIjoiRGVmYXVsdCJ9LHsiZGF0YVR5cGUiOiIyIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlhfQ0lTQ09fQ09NX0JlYWNvbkludGVydmFsIiwidmFsdWUiOiIxMDAifSx7ImRhdGFUeXBlIjoiMSIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5UcmFuc21pdFBvd2VyIiwidmFsdWUiOiIxMDAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5YX0NJU0NPX0NPTV9CYXNpY1JhdGUiLCJ2YWx1ZSI6IkRlZmF1bHQifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5YX0NJU0NPX0NPTV9CZWFjb25JbnRlcnZhbCIsInZhbHVlIjoiMTAwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMS5OYW1lIiwidmFsdWUiOiJhdGgwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMS5TU0lEIiwidmFsdWUiOiJFY2hvIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMi5OYW1lIiwidmFsdWUiOiJhdGgyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMi5TU0lEIiwidmFsdWUiOiJBbHBoYTMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDAzLk5hbWUiLCJ2YWx1ZSI6ImF0aDQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA0Lk5hbWUiLCJ2YWx1ZSI6ImF0aDYifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA0LlNTSUQiLCJ2YWx1ZSI6IkFscGhhNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAwMDUuTmFtZSIsInZhbHVlIjoiYXRoOCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAwMDUuU1NJRCIsInZhbHVlIjoiVGVzdDMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA2Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwNi5TU0lEIiwidmFsdWUiOiJCZXRhM2EifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA3Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwNy5TU0lEIiwidmFsdWUiOiJCZXRhNWEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA4Lk5hbWUiLCJ2YWx1ZSI6ImF0aDE0In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwOC5TU0lEIiwidmFsdWUiOiJCZXRhNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDEuTmFtZSIsInZhbHVlIjoiYXRoMSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDEuU1NJRCIsInZhbHVlIjoiSW5kaWEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTAyLk5hbWUiLCJ2YWx1ZSI6ImF0aDMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTAyLlNTSUQiLCJ2YWx1ZSI6IkFscGhhNCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDMuTmFtZSIsInZhbHVlIjoiYXRoNSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDQuTmFtZSIsInZhbHVlIjoiYXRoNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDQuU1NJRCIsInZhbHVlIjoiQWxwaGE4YSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDUuTmFtZSIsInZhbHVlIjoiYXRoOSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDUuU1NJRCIsInZhbHVlIjoiVGVzdDQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA2Lk5hbWUiLCJ2YWx1ZSI6ImF0aDExIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDEwNi5TU0lEIiwidmFsdWUiOiJCZXRhNGEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA3Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEzIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDEwNy5TU0lEIiwidmFsdWUiOiJCZXRhNiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDguTmFtZSIsInZhbHVlIjoiYXRoMTUifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA4LlNTSUQiLCJ2YWx1ZSI6IkJldGE4YSJ9XSwiZXZlbnRNYXAiOnsiZGVmYXVsdCI6WyJodHRwOi8vbG9jYWxob3N0OjgwOTAvYXBpL3YyL25vdGlmeSJdfSwiU2VydmVySVAiOiJmYWJyaWMtYmV0YS53ZWJwYS5jb21jYXN0Lm5ldCIsImF1dGhLZXkiOiJkMlZpY0dGZmNtVnNaV0Z6WlRFdU1BPT0iLCJTZXJ2ZXJQb3J0Ijo4MDgwLCJvbGQtcGFyYW1ldGVycyI6W3sibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLkRvZ3NhbmRjYXRzIiwidmFsdWUiOiJsaXZpbmcgdG9nZXRoZXIgLi4uIHBhbmRhbW9uaXVtIn1dLCJNYXhQaW5nV2FpdFRpbWVJblNlYyI6MTgwLCJwb25nV2FpdCI6IjMwcyIsIm1zZ1FTaXplIjoxMCwia2V5Ijoia2V5LnBlbSIsIlJldHJ5SW50ZXJ2YWxJblNlYyI6MTAsIlNlY3VyZSI6MSwibm9LZXkiOjEsImNlcnQiOiJjZXJ0LnBlbSIsIk5vdGlmeSI6WyJEZXZpY2UuV2lGaS5TU0lELjEuU1NJRCIsIkRldmljZS5XaUZpLlJhZGlvLjEuRW5hYmxlIl0sInJlc3BXYWl0IjoiOTBzIn0.fpOAIFYSHiYju6ThpNPmMLiBRCInrVR3Vl9GBFST4XQ -------------------------------------------------------------------------------- /tests/inputs/jwt1x.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT24ifQ.xdhWBxISQs8xcjRFiyd3fJRkgcH6lQW28_fWO-I6uRk -------------------------------------------------------------------------------- /tests/inputs/jwt1y.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT2ZmIn0.75rxphIuNa08IDpSHek_SBPCg3vYkjS2ma605J7N14Y -------------------------------------------------------------------------------- /tests/inputs/jwt2.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.zKbmrWfKVMVsKOYlWHuB9qSuZ98mMPbAFFspqN_OKTN5AkjWEmFz5q-8B2MDHo6v -------------------------------------------------------------------------------- /tests/inputs/jwt2l.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJkdW1wIjoiMCIsInBpbmdQZXJpb2QiOiIxMHMiLCJodHRwVGltZW91dCI6IjkwcyIsInBvcnQiOjgwODAsIkRldmljZU5ldHdvcmtJbnRlcmZhY2UiOiJlbnAyczEiLCJoY3BvcnQiOjg4ODgsImxvZyI6eyJtYXhCYWNrdXAiOjk5OTksIm1heFNpemUiOjIwMDAwMDAsImZpbGUiOiJzZXJ2ZXJfbG9ncy90YWxhcmlhTG9nLmxvZyIsImxldmVsIjoiREVCVUcifSwicGFyYW1ldGVycyI6W3siZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLlhfQ09NQ0FTVC1DT01fQ01fTUFDIiwidmFsdWUiOiJtYWM6MTEyMjMzNDQ1NTk5In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uV2VicGEuWF9DT01DQVNULUNPTV9DSUQiLCJ2YWx1ZSI6IjEyMzQifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuRGV2aWNlSW5mby5XZWJwYS5YX0NPTUNBU1QtQ09NX0NNQyIsInZhbHVlIjoiNzcyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uV2VicGEuWF9DT01DQVNULUNPTV9GaXJtd2FyZVZlcnNpb24iLCJ2YWx1ZSI6IjEuMCJ9LHsiZGF0YVR5cGUiOiIyIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLldlYnBhLlhfQ09NQ0FTVC1DT01fRGV2aWNlVXBUaW1lIiwidmFsdWUiOiIwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uTWFudWZhY3R1cmVyIiwidmFsdWUiOiJBUlJJUyBHcm91cCwgSW5jLiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLk1vZGVsTmFtZSIsInZhbHVlIjoiVEcxNjgyRyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5ESENQdjQuQ2xpZW50LjEuSVBSb3V0ZXJzIiwidmFsdWUiOiIxMC4yNTUuMjQ1LjEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuSVAuSW50ZXJmYWNlLjEuSVB2NkFkZHJlc3MuMS5JUEFkZHJlc3MiLCJ2YWx1ZSI6ImZlODA6OmJlY2E6YjVmZjpmZWYxOjlhMzQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuSVAuSW50ZXJmYWNlLjEuSVB2NkFkZHJlc3MuMi5JUEFkZHJlc3MiLCJ2YWx1ZSI6IjIwMDE6NTU4OmZmMjM6YjpiODYyOjg5Yjk6YzFjMjpiNzI2In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS4xLklQdjZQcmVmaXguMS5QcmVmaXgiLCJ2YWx1ZSI6IjIwMDE6NTU4OmZmM2I6YTA6Oi82NCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5JUC5JbnRlcmZhY2UuMy5JUHY2QWRkcmVzcy4xLklQQWRkcmVzcyIsInZhbHVlIjoiOjoxIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS40LklQdjZBZGRyZXNzLjEuSVBBZGRyZXNzIiwidmFsdWUiOiJmZTgwOjpiZWNhOmI1ZmY6ZmVmMTo5YTM3In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS40LklQdjZBZGRyZXNzLjIuSVBBZGRyZXNzIiwidmFsdWUiOiIyMDAxOjU1ODpmZjNiOmEwOmJlY2E6YjVmZjpmZWYxOjlhMzcifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy4xMC5OZXh0SG9wIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy4xLk5leHRIb3AiLCJ2YWx1ZSI6IiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjIuTmV4dEhvcCIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuMy5OZXh0SG9wIiwidmFsdWUiOiJmZTgwOjoyMDE6NWNmZjpmZTRmOjZlNDEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy40Lk5leHRIb3AiLCJ2YWx1ZSI6IiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjUuTmV4dEhvcCIsInZhbHVlIjoiZmU4MDo6MjAxOjVjZmY6ZmU0Zjo2ZTQxIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuNi5OZXh0SG9wIiwidmFsdWUiOiJmZTgwOjoyMDE6NWNmZjpmZTRmOjZlNDEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy43Lk5leHRIb3AiLCJ2YWx1ZSI6ImZlODA6OjIwMTo1Y2ZmOmZlNGY6NmU0MSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjguTmV4dEhvcCIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuOS5OZXh0SG9wIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJwYXNzd29yZCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMDAxLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMDAxLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkRlbnkifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiI1NTVDODQzNDUxMTZCQkI4QjQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDIuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDMuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDQuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDUuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDYuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDcuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDguWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJwYXNzd29yZCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAxLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAxLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6IjU1NUM4NDM0NTExNkJCQjhCNCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMi5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMy5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNC5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNi5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNy5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwOC5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIxIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlRyYW5zbWl0UG93ZXIiLCJ2YWx1ZSI6IjEwMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlhfQ0lTQ09fQ09NX0Jhc2ljUmF0ZSIsInZhbHVlIjoiRGVmYXVsdCJ9LHsiZGF0YVR5cGUiOiIyIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlhfQ0lTQ09fQ09NX0JlYWNvbkludGVydmFsIiwidmFsdWUiOiIxMDAifSx7ImRhdGFUeXBlIjoiMSIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5UcmFuc21pdFBvd2VyIiwidmFsdWUiOiIxMDAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5YX0NJU0NPX0NPTV9CYXNpY1JhdGUiLCJ2YWx1ZSI6IkRlZmF1bHQifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5YX0NJU0NPX0NPTV9CZWFjb25JbnRlcnZhbCIsInZhbHVlIjoiMTAwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMS5OYW1lIiwidmFsdWUiOiJhdGgwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMS5TU0lEIiwidmFsdWUiOiJFY2hvIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMi5OYW1lIiwidmFsdWUiOiJhdGgyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMi5TU0lEIiwidmFsdWUiOiJBbHBoYTMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDAzLk5hbWUiLCJ2YWx1ZSI6ImF0aDQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA0Lk5hbWUiLCJ2YWx1ZSI6ImF0aDYifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA0LlNTSUQiLCJ2YWx1ZSI6IkFscGhhNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAwMDUuTmFtZSIsInZhbHVlIjoiYXRoOCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAwMDUuU1NJRCIsInZhbHVlIjoiVGVzdDMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA2Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwNi5TU0lEIiwidmFsdWUiOiJCZXRhM2EifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA3Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwNy5TU0lEIiwidmFsdWUiOiJCZXRhNWEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA4Lk5hbWUiLCJ2YWx1ZSI6ImF0aDE0In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwOC5TU0lEIiwidmFsdWUiOiJCZXRhNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDEuTmFtZSIsInZhbHVlIjoiYXRoMSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDEuU1NJRCIsInZhbHVlIjoiSW5kaWEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTAyLk5hbWUiLCJ2YWx1ZSI6ImF0aDMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTAyLlNTSUQiLCJ2YWx1ZSI6IkFscGhhNCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDMuTmFtZSIsInZhbHVlIjoiYXRoNSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDQuTmFtZSIsInZhbHVlIjoiYXRoNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDQuU1NJRCIsInZhbHVlIjoiQWxwaGE4YSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDUuTmFtZSIsInZhbHVlIjoiYXRoOSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDUuU1NJRCIsInZhbHVlIjoiVGVzdDQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA2Lk5hbWUiLCJ2YWx1ZSI6ImF0aDExIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDEwNi5TU0lEIiwidmFsdWUiOiJCZXRhNGEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA3Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEzIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDEwNy5TU0lEIiwidmFsdWUiOiJCZXRhNiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDguTmFtZSIsInZhbHVlIjoiYXRoMTUifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA4LlNTSUQiLCJ2YWx1ZSI6IkJldGE4YSJ9XSwiZXZlbnRNYXAiOnsiZGVmYXVsdCI6WyJodHRwOi8vbG9jYWxob3N0OjgwOTAvYXBpL3YyL25vdGlmeSJdfSwiU2VydmVySVAiOiJmYWJyaWMtYmV0YS53ZWJwYS5jb21jYXN0Lm5ldCIsImF1dGhLZXkiOiJkMlZpY0dGZmNtVnNaV0Z6WlRFdU1BPT0iLCJTZXJ2ZXJQb3J0Ijo4MDgwLCJvbGQtcGFyYW1ldGVycyI6W3sibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLkRvZ3NhbmRjYXRzIiwidmFsdWUiOiJsaXZpbmcgdG9nZXRoZXIgLi4uIHBhbmRhbW9uaXVtIn1dLCJNYXhQaW5nV2FpdFRpbWVJblNlYyI6MTgwLCJwb25nV2FpdCI6IjMwcyIsIm1zZ1FTaXplIjoxMCwia2V5Ijoia2V5LnBlbSIsIlJldHJ5SW50ZXJ2YWxJblNlYyI6MTAsIlNlY3VyZSI6MSwibm9LZXkiOjEsImNlcnQiOiJjZXJ0LnBlbSIsIk5vdGlmeSI6WyJEZXZpY2UuV2lGaS5TU0lELjEuU1NJRCIsIkRldmljZS5XaUZpLlJhZGlvLjEuRW5hYmxlIl0sInJlc3BXYWl0IjoiOTBzIn0.d5k5Z_4VP6qwruoePfLweR9zDXQChOnSQJj5QJ49evt5Hg-yYta11IPyytPYr8iU -------------------------------------------------------------------------------- /tests/inputs/jwt2x.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT24ifQ.MQhvt-BUPtP_MY7jItouOIEUMORSAJSU_5A_AQXZ2wJtViFSjPex6-gol8zEDMYo -------------------------------------------------------------------------------- /tests/inputs/jwt2y.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT2ZmIn0.ySoont1M8eF4rVDpbnu4fdB48GnxQPQCIjdKizJ39h9msrz_cB-kIzSK0vn3IsQ5 -------------------------------------------------------------------------------- /tests/inputs/jwt3.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.wQtvQnhz9ssKblWD77c5KNi25XI-i-BsGGa6JQmmVvb-jQtnDWNJbZtl-11sOVZ3znBsqqiBZYmSuS6d4fIjfg -------------------------------------------------------------------------------- /tests/inputs/jwt3l.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJkdW1wIjoiMCIsInBpbmdQZXJpb2QiOiIxMHMiLCJodHRwVGltZW91dCI6IjkwcyIsInBvcnQiOjgwODAsIkRldmljZU5ldHdvcmtJbnRlcmZhY2UiOiJlbnAyczEiLCJoY3BvcnQiOjg4ODgsImxvZyI6eyJtYXhCYWNrdXAiOjk5OTksIm1heFNpemUiOjIwMDAwMDAsImZpbGUiOiJzZXJ2ZXJfbG9ncy90YWxhcmlhTG9nLmxvZyIsImxldmVsIjoiREVCVUcifSwicGFyYW1ldGVycyI6W3siZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLlhfQ09NQ0FTVC1DT01fQ01fTUFDIiwidmFsdWUiOiJtYWM6MTEyMjMzNDQ1NTk5In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uV2VicGEuWF9DT01DQVNULUNPTV9DSUQiLCJ2YWx1ZSI6IjEyMzQifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuRGV2aWNlSW5mby5XZWJwYS5YX0NPTUNBU1QtQ09NX0NNQyIsInZhbHVlIjoiNzcyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uV2VicGEuWF9DT01DQVNULUNPTV9GaXJtd2FyZVZlcnNpb24iLCJ2YWx1ZSI6IjEuMCJ9LHsiZGF0YVR5cGUiOiIyIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLldlYnBhLlhfQ09NQ0FTVC1DT01fRGV2aWNlVXBUaW1lIiwidmFsdWUiOiIwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uTWFudWZhY3R1cmVyIiwidmFsdWUiOiJBUlJJUyBHcm91cCwgSW5jLiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLk1vZGVsTmFtZSIsInZhbHVlIjoiVEcxNjgyRyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5ESENQdjQuQ2xpZW50LjEuSVBSb3V0ZXJzIiwidmFsdWUiOiIxMC4yNTUuMjQ1LjEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuSVAuSW50ZXJmYWNlLjEuSVB2NkFkZHJlc3MuMS5JUEFkZHJlc3MiLCJ2YWx1ZSI6ImZlODA6OmJlY2E6YjVmZjpmZWYxOjlhMzQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuSVAuSW50ZXJmYWNlLjEuSVB2NkFkZHJlc3MuMi5JUEFkZHJlc3MiLCJ2YWx1ZSI6IjIwMDE6NTU4OmZmMjM6YjpiODYyOjg5Yjk6YzFjMjpiNzI2In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS4xLklQdjZQcmVmaXguMS5QcmVmaXgiLCJ2YWx1ZSI6IjIwMDE6NTU4OmZmM2I6YTA6Oi82NCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5JUC5JbnRlcmZhY2UuMy5JUHY2QWRkcmVzcy4xLklQQWRkcmVzcyIsInZhbHVlIjoiOjoxIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS40LklQdjZBZGRyZXNzLjEuSVBBZGRyZXNzIiwidmFsdWUiOiJmZTgwOjpiZWNhOmI1ZmY6ZmVmMTo5YTM3In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS40LklQdjZBZGRyZXNzLjIuSVBBZGRyZXNzIiwidmFsdWUiOiIyMDAxOjU1ODpmZjNiOmEwOmJlY2E6YjVmZjpmZWYxOjlhMzcifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy4xMC5OZXh0SG9wIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy4xLk5leHRIb3AiLCJ2YWx1ZSI6IiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjIuTmV4dEhvcCIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuMy5OZXh0SG9wIiwidmFsdWUiOiJmZTgwOjoyMDE6NWNmZjpmZTRmOjZlNDEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy40Lk5leHRIb3AiLCJ2YWx1ZSI6IiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjUuTmV4dEhvcCIsInZhbHVlIjoiZmU4MDo6MjAxOjVjZmY6ZmU0Zjo2ZTQxIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuNi5OZXh0SG9wIiwidmFsdWUiOiJmZTgwOjoyMDE6NWNmZjpmZTRmOjZlNDEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy43Lk5leHRIb3AiLCJ2YWx1ZSI6ImZlODA6OjIwMTo1Y2ZmOmZlNGY6NmU0MSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjguTmV4dEhvcCIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuOS5OZXh0SG9wIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJwYXNzd29yZCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMDAxLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMDAxLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkRlbnkifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiI1NTVDODQzNDUxMTZCQkI4QjQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDIuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDMuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDQuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDUuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDYuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDcuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDguWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJwYXNzd29yZCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAxLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAxLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6IjU1NUM4NDM0NTExNkJCQjhCNCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMi5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMy5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNC5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNi5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNy5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwOC5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIxIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlRyYW5zbWl0UG93ZXIiLCJ2YWx1ZSI6IjEwMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlhfQ0lTQ09fQ09NX0Jhc2ljUmF0ZSIsInZhbHVlIjoiRGVmYXVsdCJ9LHsiZGF0YVR5cGUiOiIyIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlhfQ0lTQ09fQ09NX0JlYWNvbkludGVydmFsIiwidmFsdWUiOiIxMDAifSx7ImRhdGFUeXBlIjoiMSIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5UcmFuc21pdFBvd2VyIiwidmFsdWUiOiIxMDAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5YX0NJU0NPX0NPTV9CYXNpY1JhdGUiLCJ2YWx1ZSI6IkRlZmF1bHQifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5YX0NJU0NPX0NPTV9CZWFjb25JbnRlcnZhbCIsInZhbHVlIjoiMTAwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMS5OYW1lIiwidmFsdWUiOiJhdGgwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMS5TU0lEIiwidmFsdWUiOiJFY2hvIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMi5OYW1lIiwidmFsdWUiOiJhdGgyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMi5TU0lEIiwidmFsdWUiOiJBbHBoYTMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDAzLk5hbWUiLCJ2YWx1ZSI6ImF0aDQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA0Lk5hbWUiLCJ2YWx1ZSI6ImF0aDYifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA0LlNTSUQiLCJ2YWx1ZSI6IkFscGhhNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAwMDUuTmFtZSIsInZhbHVlIjoiYXRoOCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAwMDUuU1NJRCIsInZhbHVlIjoiVGVzdDMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA2Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwNi5TU0lEIiwidmFsdWUiOiJCZXRhM2EifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA3Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwNy5TU0lEIiwidmFsdWUiOiJCZXRhNWEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA4Lk5hbWUiLCJ2YWx1ZSI6ImF0aDE0In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwOC5TU0lEIiwidmFsdWUiOiJCZXRhNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDEuTmFtZSIsInZhbHVlIjoiYXRoMSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDEuU1NJRCIsInZhbHVlIjoiSW5kaWEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTAyLk5hbWUiLCJ2YWx1ZSI6ImF0aDMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTAyLlNTSUQiLCJ2YWx1ZSI6IkFscGhhNCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDMuTmFtZSIsInZhbHVlIjoiYXRoNSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDQuTmFtZSIsInZhbHVlIjoiYXRoNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDQuU1NJRCIsInZhbHVlIjoiQWxwaGE4YSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDUuTmFtZSIsInZhbHVlIjoiYXRoOSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDUuU1NJRCIsInZhbHVlIjoiVGVzdDQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA2Lk5hbWUiLCJ2YWx1ZSI6ImF0aDExIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDEwNi5TU0lEIiwidmFsdWUiOiJCZXRhNGEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA3Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEzIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDEwNy5TU0lEIiwidmFsdWUiOiJCZXRhNiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDguTmFtZSIsInZhbHVlIjoiYXRoMTUifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA4LlNTSUQiLCJ2YWx1ZSI6IkJldGE4YSJ9XSwiZXZlbnRNYXAiOnsiZGVmYXVsdCI6WyJodHRwOi8vbG9jYWxob3N0OjgwOTAvYXBpL3YyL25vdGlmeSJdfSwiU2VydmVySVAiOiJmYWJyaWMtYmV0YS53ZWJwYS5jb21jYXN0Lm5ldCIsImF1dGhLZXkiOiJkMlZpY0dGZmNtVnNaV0Z6WlRFdU1BPT0iLCJTZXJ2ZXJQb3J0Ijo4MDgwLCJvbGQtcGFyYW1ldGVycyI6W3sibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLkRvZ3NhbmRjYXRzIiwidmFsdWUiOiJsaXZpbmcgdG9nZXRoZXIgLi4uIHBhbmRhbW9uaXVtIn1dLCJNYXhQaW5nV2FpdFRpbWVJblNlYyI6MTgwLCJwb25nV2FpdCI6IjMwcyIsIm1zZ1FTaXplIjoxMCwia2V5Ijoia2V5LnBlbSIsIlJldHJ5SW50ZXJ2YWxJblNlYyI6MTAsIlNlY3VyZSI6MSwibm9LZXkiOjEsImNlcnQiOiJjZXJ0LnBlbSIsIk5vdGlmeSI6WyJEZXZpY2UuV2lGaS5TU0lELjEuU1NJRCIsIkRldmljZS5XaUZpLlJhZGlvLjEuRW5hYmxlIl0sInJlc3BXYWl0IjoiOTBzIn0.XyrmOad3WBqpyFFvWi-9GhbejJtK2FAPoi6ZUCQEagP6AWM_3jpd5H0x1AaWfugKi_eL-PqqOiCl62bJ49O1Dw -------------------------------------------------------------------------------- /tests/inputs/jwt3x.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT24ifQ.z9iQw5AETu6EPg-cwe9pfPoYu6bUXC7PtraLM0xBlbPmORSuLuxnAjE6n7ajBtgMloLTQ2oKAwVKkMnhh3THxA -------------------------------------------------------------------------------- /tests/inputs/jwt3y.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT2ZmIn0.yKKV4aVYg_H6gh8XbbYTgNXU-Mk9Asg1wyFO-cIPppRMjVja67za0b7rBgG6fC4c4PwxKv8PlMU3RY-oVHoYDQ -------------------------------------------------------------------------------- /tests/inputs/jwt4.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.o8IMkEfA69S7tJMBLexFWB2YmqmOXzZDiCkaqVGXZV8_QVhOqYAwaj6tbq6r1ry1E49436mA3UxaqiFYY0lCeZW0J81R9v6RQe09FAQm7hMZV3uOxzh3GNEWjq1v_MMYbnMuzrfVBh028t7n_hKJpW9aWM-jBJI-s6XrDajokGaIFia3E-7kJZK7DW2gqK5Y8JclzJP8uA3CQhMd36sEa4VfentpJGOtqo_XdQlTm2pjO0CVSApCVgl7SEbW3VP3CVfK8iOf7dHLddG1dJrZU8AgsgMEF_ix9iN908KNAUO_WhdQ75G2u0Y7wiyozXJcpf16TUMCr4m18BU23pzIEQ -------------------------------------------------------------------------------- /tests/inputs/jwt4l.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJkdW1wIjoiMCIsInBpbmdQZXJpb2QiOiIxMHMiLCJodHRwVGltZW91dCI6IjkwcyIsInBvcnQiOjgwODAsIkRldmljZU5ldHdvcmtJbnRlcmZhY2UiOiJlbnAyczEiLCJoY3BvcnQiOjg4ODgsImxvZyI6eyJtYXhCYWNrdXAiOjk5OTksIm1heFNpemUiOjIwMDAwMDAsImZpbGUiOiJzZXJ2ZXJfbG9ncy90YWxhcmlhTG9nLmxvZyIsImxldmVsIjoiREVCVUcifSwicGFyYW1ldGVycyI6W3siZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLlhfQ09NQ0FTVC1DT01fQ01fTUFDIiwidmFsdWUiOiJtYWM6MTEyMjMzNDQ1NTk5In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uV2VicGEuWF9DT01DQVNULUNPTV9DSUQiLCJ2YWx1ZSI6IjEyMzQifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuRGV2aWNlSW5mby5XZWJwYS5YX0NPTUNBU1QtQ09NX0NNQyIsInZhbHVlIjoiNzcyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uV2VicGEuWF9DT01DQVNULUNPTV9GaXJtd2FyZVZlcnNpb24iLCJ2YWx1ZSI6IjEuMCJ9LHsiZGF0YVR5cGUiOiIyIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLldlYnBhLlhfQ09NQ0FTVC1DT01fRGV2aWNlVXBUaW1lIiwidmFsdWUiOiIwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLkRldmljZUluZm8uTWFudWZhY3R1cmVyIiwidmFsdWUiOiJBUlJJUyBHcm91cCwgSW5jLiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLk1vZGVsTmFtZSIsInZhbHVlIjoiVEcxNjgyRyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5ESENQdjQuQ2xpZW50LjEuSVBSb3V0ZXJzIiwidmFsdWUiOiIxMC4yNTUuMjQ1LjEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuSVAuSW50ZXJmYWNlLjEuSVB2NkFkZHJlc3MuMS5JUEFkZHJlc3MiLCJ2YWx1ZSI6ImZlODA6OmJlY2E6YjVmZjpmZWYxOjlhMzQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuSVAuSW50ZXJmYWNlLjEuSVB2NkFkZHJlc3MuMi5JUEFkZHJlc3MiLCJ2YWx1ZSI6IjIwMDE6NTU4OmZmMjM6YjpiODYyOjg5Yjk6YzFjMjpiNzI2In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS4xLklQdjZQcmVmaXguMS5QcmVmaXgiLCJ2YWx1ZSI6IjIwMDE6NTU4OmZmM2I6YTA6Oi82NCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5JUC5JbnRlcmZhY2UuMy5JUHY2QWRkcmVzcy4xLklQQWRkcmVzcyIsInZhbHVlIjoiOjoxIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS40LklQdjZBZGRyZXNzLjEuSVBBZGRyZXNzIiwidmFsdWUiOiJmZTgwOjpiZWNhOmI1ZmY6ZmVmMTo5YTM3In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLklQLkludGVyZmFjZS40LklQdjZBZGRyZXNzLjIuSVBBZGRyZXNzIiwidmFsdWUiOiIyMDAxOjU1ODpmZjNiOmEwOmJlY2E6YjVmZjpmZWYxOjlhMzcifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy4xMC5OZXh0SG9wIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy4xLk5leHRIb3AiLCJ2YWx1ZSI6IiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjIuTmV4dEhvcCIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuMy5OZXh0SG9wIiwidmFsdWUiOiJmZTgwOjoyMDE6NWNmZjpmZTRmOjZlNDEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy40Lk5leHRIb3AiLCJ2YWx1ZSI6IiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjUuTmV4dEhvcCIsInZhbHVlIjoiZmU4MDo6MjAxOjVjZmY6ZmU0Zjo2ZTQxIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuNi5OZXh0SG9wIiwidmFsdWUiOiJmZTgwOjoyMDE6NWNmZjpmZTRmOjZlNDEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuUm91dGluZy5Sb3V0ZXIuMS5JUHY2Rm9yd2FyZGluZy43Lk5leHRIb3AiLCJ2YWx1ZSI6ImZlODA6OjIwMTo1Y2ZmOmZlNGY6NmU0MSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5Sb3V0aW5nLlJvdXRlci4xLklQdjZGb3J3YXJkaW5nLjguTmV4dEhvcCIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLlJvdXRpbmcuUm91dGVyLjEuSVB2NkZvcndhcmRpbmcuOS5OZXh0SG9wIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJwYXNzd29yZCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMDAxLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMDAxLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkRlbnkifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiI1NTVDODQzNDUxMTZCQkI4QjQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDIuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMi5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDMuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwMy5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDQuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNC5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDUuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNS5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDYuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNi5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDcuWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwNy5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJicnVzaDYyOTJhcnRpc3QifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5YX0NJU0NPX0NPTV9NQUNGaWx0ZXIuTUFDQWRkcmVzcyIsInZhbHVlIjoiIn0seyJkYXRhVHlwZSI6IjIiLCJuYW1lIjoiRGV2aWNlLldpRmkuQWNjZXNzUG9pbnQuMTAwMDguWF9DSVNDT19DT01fTWFjRmlsdGVyVGFibGVOdW1iZXJPZkVudHJpZXMiLCJ2YWx1ZSI6IjAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDAwOC5YX0NPTUNBU1QtQ09NX01BQ19GaWx0ZXJpbmdNb2RlIiwidmFsdWUiOiJBbGxvdy1BTEwifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMS5TZWN1cml0eS5LZXlQYXNzcGhyYXNlIiwidmFsdWUiOiJwYXNzd29yZCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAxLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAxLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6IjU1NUM4NDM0NTExNkJCQjhCNCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMi5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAyLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwMy5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTAzLlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNC5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA0LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNS5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA1LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNi5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA2LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwNy5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA3LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlNlY3VyaXR5LktleVBhc3NwaHJhc2UiLCJ2YWx1ZSI6ImJydXNoNjI5MmFydGlzdCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlhfQ0lTQ09fQ09NX01BQ0ZpbHRlci5NQUNBZGRyZXNzIiwidmFsdWUiOiIifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5BY2Nlc3NQb2ludC4xMDEwOC5YX0NJU0NPX0NPTV9NYWNGaWx0ZXJUYWJsZU51bWJlck9mRW50cmllcyIsInZhbHVlIjoiMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLkFjY2Vzc1BvaW50LjEwMTA4LlhfQ09NQ0FTVC1DT01fTUFDX0ZpbHRlcmluZ01vZGUiLCJ2YWx1ZSI6IkFsbG93LUFMTCJ9LHsiZGF0YVR5cGUiOiIxIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlRyYW5zbWl0UG93ZXIiLCJ2YWx1ZSI6IjEwMCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlhfQ0lTQ09fQ09NX0Jhc2ljUmF0ZSIsInZhbHVlIjoiRGVmYXVsdCJ9LHsiZGF0YVR5cGUiOiIyIiwibmFtZSI6IkRldmljZS5XaUZpLlJhZGlvLjEwMDAwLlhfQ0lTQ09fQ09NX0JlYWNvbkludGVydmFsIiwidmFsdWUiOiIxMDAifSx7ImRhdGFUeXBlIjoiMSIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5UcmFuc21pdFBvd2VyIiwidmFsdWUiOiIxMDAifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5YX0NJU0NPX0NPTV9CYXNpY1JhdGUiLCJ2YWx1ZSI6IkRlZmF1bHQifSx7ImRhdGFUeXBlIjoiMiIsIm5hbWUiOiJEZXZpY2UuV2lGaS5SYWRpby4xMDEwMC5YX0NJU0NPX0NPTV9CZWFjb25JbnRlcnZhbCIsInZhbHVlIjoiMTAwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMS5OYW1lIiwidmFsdWUiOiJhdGgwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMS5TU0lEIiwidmFsdWUiOiJFY2hvIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMi5OYW1lIiwidmFsdWUiOiJhdGgyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwMi5TU0lEIiwidmFsdWUiOiJBbHBoYTMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDAzLk5hbWUiLCJ2YWx1ZSI6ImF0aDQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA0Lk5hbWUiLCJ2YWx1ZSI6ImF0aDYifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA0LlNTSUQiLCJ2YWx1ZSI6IkFscGhhNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAwMDUuTmFtZSIsInZhbHVlIjoiYXRoOCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAwMDUuU1NJRCIsInZhbHVlIjoiVGVzdDMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA2Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEwIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwNi5TU0lEIiwidmFsdWUiOiJCZXRhM2EifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA3Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEyIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwNy5TU0lEIiwidmFsdWUiOiJCZXRhNWEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMDA4Lk5hbWUiLCJ2YWx1ZSI6ImF0aDE0In0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDAwOC5TU0lEIiwidmFsdWUiOiJCZXRhNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDEuTmFtZSIsInZhbHVlIjoiYXRoMSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDEuU1NJRCIsInZhbHVlIjoiSW5kaWEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTAyLk5hbWUiLCJ2YWx1ZSI6ImF0aDMifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTAyLlNTSUQiLCJ2YWx1ZSI6IkFscGhhNCJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDMuTmFtZSIsInZhbHVlIjoiYXRoNSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDQuTmFtZSIsInZhbHVlIjoiYXRoNyJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDQuU1NJRCIsInZhbHVlIjoiQWxwaGE4YSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDUuTmFtZSIsInZhbHVlIjoiYXRoOSJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDUuU1NJRCIsInZhbHVlIjoiVGVzdDQifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA2Lk5hbWUiLCJ2YWx1ZSI6ImF0aDExIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDEwNi5TU0lEIiwidmFsdWUiOiJCZXRhNGEifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA3Lk5hbWUiLCJ2YWx1ZSI6ImF0aDEzIn0seyJkYXRhVHlwZSI6IjAiLCJuYW1lIjoiRGV2aWNlLldpRmkuU1NJRC4xMDEwNy5TU0lEIiwidmFsdWUiOiJCZXRhNiJ9LHsiZGF0YVR5cGUiOiIwIiwibmFtZSI6IkRldmljZS5XaUZpLlNTSUQuMTAxMDguTmFtZSIsInZhbHVlIjoiYXRoMTUifSx7ImRhdGFUeXBlIjoiMCIsIm5hbWUiOiJEZXZpY2UuV2lGaS5TU0lELjEwMTA4LlNTSUQiLCJ2YWx1ZSI6IkJldGE4YSJ9XSwiZXZlbnRNYXAiOnsiZGVmYXVsdCI6WyJodHRwOi8vbG9jYWxob3N0OjgwOTAvYXBpL3YyL25vdGlmeSJdfSwiU2VydmVySVAiOiJmYWJyaWMtYmV0YS53ZWJwYS5jb21jYXN0Lm5ldCIsImF1dGhLZXkiOiJkMlZpY0dGZmNtVnNaV0Z6WlRFdU1BPT0iLCJTZXJ2ZXJQb3J0Ijo4MDgwLCJvbGQtcGFyYW1ldGVycyI6W3sibmFtZSI6IkRldmljZS5EZXZpY2VJbmZvLkRvZ3NhbmRjYXRzIiwidmFsdWUiOiJsaXZpbmcgdG9nZXRoZXIgLi4uIHBhbmRhbW9uaXVtIn1dLCJNYXhQaW5nV2FpdFRpbWVJblNlYyI6MTgwLCJwb25nV2FpdCI6IjMwcyIsIm1zZ1FTaXplIjoxMCwia2V5Ijoia2V5LnBlbSIsIlJldHJ5SW50ZXJ2YWxJblNlYyI6MTAsIlNlY3VyZSI6MSwibm9LZXkiOjEsImNlcnQiOiJjZXJ0LnBlbSIsIk5vdGlmeSI6WyJEZXZpY2UuV2lGaS5TU0lELjEuU1NJRCIsIkRldmljZS5XaUZpLlJhZGlvLjEuRW5hYmxlIl0sInJlc3BXYWl0IjoiOTBzIn0.gKl6fR4Bw7bwPSJTq_rT-j2iOPA9oilh-qAVZKwBHBqFxvhjrPKDgXQZCNtiQt9zzbbhr8TIab05bMciQE-FAcNAYUP7Lf9KkPco_2-KLpza2Td3VC4NgA48ZLtRpjBGQuh2x9YQKn-4HLPxTQsykPHTEYqyCQN-EZD5CrTAXPWuqDS-hd2bKue0kbx8fVaO4YQqF7lRWp41Q1bXLB-OLSq7FQntpm7fJnH_u2vQm40xB3ak1KUW8c0WV5JwvTx5yz27lvoDwUc971YlGZcqUkJ9pRYaz18EZC_dg4Grwkc4u_rxVFRPTHXnUCPHsCNqluEUA4xVoyfKrXxgxqOEBw -------------------------------------------------------------------------------- /tests/inputs/jwt4x.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT24ifQ.RTwNqfa6osF-U4xPCDRs8zbs-eacw9jfDmXU1H7P1N6NyaeuYeDkqBo5x9mW2BkH001l1mH4XLY8Yd71CdrgTZoiuBWuAwQxoy0TLtVS15DqCtEbR3tEkdCsQC0yVwgGQ_961ax8Wi6UkHhfkoSfuNw_2lhQ_qbOt5OLzxK0C3VhTs45xnA5rWMcqyKfKrTY4eh1FYo0hLD9E210NAzl3Z5OFFgtrQ4AlsD1zequdMxprZFBAbXK3HA8Ek9X3G6znAKTbDza9eRWQHD5GKXnppvX0FigUC_Wk0AzDLQijtoxLaoJpdh-p8u9AnMMjgrDaskjmhSr09lY3sesnD7R_A -------------------------------------------------------------------------------- /tests/inputs/jwt4y.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT2ZmIn0.XbGbjzn7CIqT8UM1N827XCW63fm42s5mIiMUQ5vSIsWySjkrnI0-hlQHLYB16k1PPn9TEO60hPz3aKLeM--WnsKfbCRZUYKl_owv4V7XtVpTz19BHucNINmcrg7bGAOA0ZoNxoe6sN3urvyssEPFFb-GRCiKtec8__mbFt02n95LrKYVuTFr7cGd6fflGONCCwOHuuixgO34BHWgHcS7oLilM_UX5NqJCm5_AEaPKzmOicVDtAma36Edmc9FL347JzkbOdXd8EGVrZuXxiJVpYAuMVrS_x_iRCSDEk9kKP8k61L6zO_CVszpVhb6qIAxnXo7BIlunoYlFqgdX7h0IA -------------------------------------------------------------------------------- /tests/inputs/jwt5.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.QGPQg4EYNlc40LRKMOHcmjHO1iqltMkMs3EAteQKkNoHdtT6AepOe74Edz1xlctZGYn3DV-Ekioksj2i5X6AodnSDymp1iXqE7gKGLIlUI2qv1o2M4-sUgwMiInbfDcAKoFbIYbGr8uypGoDb9IdNzOol-yONJrBWq7rqogrFJAfPecOANXonVh8IhjPDSnAr5DVTd4jCAV1CfPXKgiTqx7R599phwjLGZlLwOobZG8BaoI7WGQu6mhxyBTw7x3fYbyrE8hgaeKPHHia2EIAxYpPzmLygLhogzZSGug7j4NqolbXRBupudhkBzKUUTZWqlJJyqvFB-HM-p3Rh7rrtQ -------------------------------------------------------------------------------- /tests/inputs/jwt5x.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT24ifQ.ZAW1OF6-sGeqcnIq7q8VYKySd9wv8_w_aq3A5j3ZW_CcqRybeE9hJt3stIc2GRe9dBw_zIWZNZug0aPubuG4goekk1gH7Ed9CmM2wLTkHAKWuDIXUg08rqxOR-1LbBy8Gt2HsPF4jy-ckSasOIRwlZ6RurxQoS_bjF2Ts9tjoDi3l0cXnNO9DkDN17d0LYTNz_wTUeCpkhByX_y8CaCjgWxRjf6M0T8gSzITSdVzHb5Pi0WOjlRGoTzXtxCu6FXGxegqPBgPBPtHHNd3EWxaZfTNflXPL46cfkPnsmUmS9ba8k3Cu_mTwyttDJp017XVCs5c9DKtR6c-uSY4_2FVyw -------------------------------------------------------------------------------- /tests/inputs/jwt5y.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT2ZmIn0.sLTYPDpMT4gfPbeb3cpTMdMY0smAKWg5eQcgu8XlxnvGdPkMm9qb-rtyuFHBm5ll72icRMN1NSFsEhJMUJxNOH6CQ1tY3M88dYj5xo__fuxySJXQdHTXSPAQSxyvO3AGiCv0fKg6O6bBKTuvwDwUDaDPPNaXBcA0RQucTM0vv5_5iMneyKHNyaWOuJnws-DKqWrXlYHujIwq_UOJqVIpsJrhVWYndpdwm5ekSmKCrKg-YsXchd-LCoYooiJBcT5EErMxPeh6upXtKLvE0o9HqGe_wWxdvoSnKi-BOpVtHGb6H8DXvqGjlj3r6tkhY26HFcbZbjuOPw0GBpdY1MGFBg -------------------------------------------------------------------------------- /tests/inputs/jwt6.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.DreeREH61ocCTNyznqEvX5avyE_OiGZGWr8wZY0pSqQP0lwI8W_PhfuIv8JUrAbLg2_JIHp3ABqAweTwwgpNF98WPGtBHTyU2tgDrVEOYXeuRjUNXuvUhmpqX7-mlIlZJMne-9gg7dytZu1Kk6ZfhLtYBq9eTPwoPGqETXf3jycJEMnlbS4RSzI0p3ylqtqKb0oUZxnATg6qzT2mCJvpkph8ktsDYL7yLQ0iYsuZp1ZLg2nelxN0edQcVKeeYbu8lAft0JHvBi-el8T1XG9NmDvtIxcu8xQ9uxvs3RHaHSwe9ejo3AsiYu_Fmi8zJIuW4EJL9KK0yqCq7JR9vzRPJQ -------------------------------------------------------------------------------- /tests/inputs/jwt6x.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT24ifQ.0KsComJ3SeKLxNv6OwGyNw2tmwemidNJ0Toq0HIMvFTsbryfkVlJbo65QOm38zxVkxysFyps1CbbWdlC1IaGHB-HMNB6F36FLkRV4md8KdhiiAgxfNmZlISIjKoOb-UunElPtARWh2b5mAKBcRq85rYgt_5BiKd_THxE_dmFrOSsZZHw084VaPwBS1c9HiHk4_RDFtyV2fUoQ2efiHOsc-Me9ZGa1xmQQGkA1AFbCiHelGoJGuWTsOGisrbWRn0Jx47U8u1oQznis85AOsG6Ld_-Q9QocaqTsGexLKZl4ZL1TsU5zY01VvKoXKd0-rWDlZ4xyKYRf4XtkpdkdP3D2g -------------------------------------------------------------------------------- /tests/inputs/jwt6y.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT2ZmIn0.0zP0EaxnkSRbbdgoQ5bfHzFzHCcDRqhGeUvrfj9E4VOeJL4bSweMsv8VFz7MT2gUbz8swYgD89IzHlTELWSWGdkFS4u6TqHnir_4Ts51-7yFfB4XIRRZ7BwJGQ5Ty418jf7hQy592FkUs7Y_w9gzXeOLVf1IBmLgkFpFW0Qo4zqxakZudc2TlRVkiJUPIgkrMujLSGMNQoBK8vaeiIjbILJ_jRc7RJxjx_AsnQTuHp5yzjK6gjHds-qoh7RVEsA8gNV8hY7CDchJiqKYtJKjCRK08DUaHtH-TjjhMqWbGmuP5OXtavSE1mNbtiJrvLuzeZMvxhq7PiFYPiVQIx-LRg -------------------------------------------------------------------------------- /tests/inputs/jwt8_hs256.txt: -------------------------------------------------------------------------------- 1 | eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJmaWxlcy5jeXBocmUuY29tIiwic3ViIjoidXNlcjAifQ.dLFbrHVViu1e3VD1yeCd9aaLNed-bfXhSsF0Gh56fBg -------------------------------------------------------------------------------- /tests/inputs/jwt9_hs384.txt: -------------------------------------------------------------------------------- 1 | eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpc3MiOiJmaWxlcy5jeXBocmUuY29tIiwic3ViIjoidXNlcjAifQ.xqea3OVgPEMxsCgyikrR3gGv4H2yqMyXMm7xhOlQWpA-NpT6n2a1d7TDGgU6LOe4 -------------------------------------------------------------------------------- /tests/inputs/jwt_r11.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA33TqqLR3eeUmDtHS89qF 3 | 3p4MP7Wfqt2Zjj3lZjLjjCGDvwr9cJNlNDiuKboODgUiT4ZdPWbOiMAfDcDzlOxA 4 | 04DDnEFGAf+kDQiNSe2ZtqC7bnIc8+KSG/qOGQIVaay4Ucr6ovDkykO5Hxn7OU7s 5 | Jp9TP9H0JH8zMQA6YzijYH9LsupTerrY3U6zyihVEDXXOv08vBHk50BMFJbE9iwF 6 | wnxCsU5+UZUZYw87Uu0n4LPFS9BT8tUIvAfnRXIEWCha3KbFWmdZQZlyrFw0buUE 7 | f0YN3/Q0auBkdbDR/ES2PbgKTJdkjc/rEeM0TxvOUf7HuUNOhrtAVEN1D5uuxE1W 8 | SwIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/inputs/jwt_r11.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2p3dC1pZHAuZXhhbXBsZS5jb20iLCJzdWIiOiJtYWlsdG86bWlrZUBleGFtcGxlLmNvbSIsIm5iZiI6MTQ4NzI3MzM4MSwiZXhwIjoxNDg3Mjc2OTgxLCJpYXQiOjE0ODcyNzMzODEsImp0aSI6ImlkMTIzNDU2IiwidHlwIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9yZWdpc3RlciJ9.Uf6thgOcXETo4bqPap38MQyydZwBkTlrJG9_3shmNlBLJw2FRZHF0XyZXfusLMO1xFTWf4qlLwY4VyUFJwfd9k3BD7khBLRXGiQBLqYSl1WFRfTrgFbZrCi_zvjw2RdVzGC3CSw4JKnwey8GzydC788YKjXjVkPd5daAfDWC0-G-n7aS2fSWNa87ZbYBs3CtElTUjoWsruaSNe3S8RXA-3K01naJdfLxnU2bjdWHeLkK_DWLJZ97ob0klPSqFqc35eCsH2zbTCuePonApVO83PbBYJehE7DAih8OMmUBWuMQK3__jKQyqSMXn93bARfBmlj7q_-tNIx89rs8SSI3_Q 2 | -------------------------------------------------------------------------------- /tests/inputs/jwtbadalg.txt: -------------------------------------------------------------------------------- 1 | eyAiYWxnIjogImludmFsaWQiLCAidHlwIjogIkpXVCIgfQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c 2 | -------------------------------------------------------------------------------- /tests/inputs/jwtia.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ@.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.MAWYApFqPqS6u3uZ6uZtTSgMi5iEy4V4tpHL_bdTULw 2 | -------------------------------------------------------------------------------- /tests/inputs/jwtib.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.[yJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.MAWYApFqPqS6u3uZ6uZtTSgMi5iEy4V4tpHL_bdTULw 2 | -------------------------------------------------------------------------------- /tests/inputs/jwtic.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.MAW.Y.ApFqPqS6u3uZ6uZtTSgMi5iEy4V4tpHL_bdTULw 2 | -------------------------------------------------------------------------------- /tests/inputs/jwtid.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.MAWYApFqPqS6u3uZ6uZtTSgMi5iEy4V4tpHL_bdTULw 2 | -------------------------------------------------------------------------------- /tests/inputs/jwtie.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC=9.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9.MAWYApFqPqS6u3uZ6uZtTSgMi5iEy4V4tpHL_bdTULw 2 | -------------------------------------------------------------------------------- /tests/inputs/jwtif.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbi=9.MAWYApFqPqS6u3uZ6uZtTSgMi5iEy4V4tpHL_bdTULw 2 | -------------------------------------------------------------------------------- /tests/inputs/jwtn.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZXJ2aWNlMiI6Ik9uIiwic2VydmljZTEiOiJPbiJ9. -------------------------------------------------------------------------------- /tests/inputs/jwtnx.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT24ifQ. -------------------------------------------------------------------------------- /tests/inputs/jwtny.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZXJ2aWNlMiI6Ik9mZiIsInNlcnZpY2UxIjoiT2ZmIn0. -------------------------------------------------------------------------------- /tests/inputs/jwtr1.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2p3dC1pZHAuZXhhbXBsZS5jb20iLCJzdWIiOiJtYWlsdG86bWlrZUBleGFtcGxlLmNvbSIsIm5iZiI6MTQ4NzIzNTc4OSwiZXhwIjoxNDg3MjM5Mzg5LCJpYXQiOjE0ODcyMzU3ODksImp0aSI6ImlkMTIzNDU2IiwidHlwIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9yZWdpc3RlciJ9.FH7uM6KXeENtc7eTIPlwRErlEEMtC51S1GE_7GLacjUkeYPIxmOBDhhI4bt5Gkd7hpXwl_mux6TgthhXQlMLQ6cSfgbW0wvKdiME-9FVC8TO33A92Fyyhr4uxyHOl-isMwNUsr33jGpAhQIiPrBPHcF_kWt4igp8GhuwAHBUHA_5sLm8fVlCBxUukWXrqW2DBumhauYIOIO5TM5wAMxi0lPwOxLRm3vi7Arylgjj3GTsnQprAvKjzkpRzvBlpvTAy3LlQqZE8pKaVHGh-8qpCo_ltC_GpX7r823mdZCC9LEjz610XYWAjvxQt4JY1wIb_y8jWeGEWb_Wu_ImKw_0PA 2 | -------------------------------------------------------------------------------- /tests/inputs/jwtr2.txt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2p3dC1pZHAuZXhhbXBsZS5jb20iLCJzdWIiOiJtYWlsdG86bWlrZUBleGFtcGxlLmNvbSIsIm5iZiI6MTQ4NzIzNTI1MiwiZXhwIjoxNDg3MjM4ODUyLCJpYXQiOjE0ODcyMzUyNTIsImp0aSI6ImlkMTIzNDU2IiwidHlwIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9yZWdpc3RlciJ9.vsGidPSL79m6PpUqifjqUkFPWVmeBmEsHemBKMik-S4 2 | -------------------------------------------------------------------------------- /tests/inputs/key10_hs512.pem: -------------------------------------------------------------------------------- 1 | 012345678901234567890123456789XY012345678901234567890123456789XY -------------------------------------------------------------------------------- /tests/inputs/key4.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDsLxH6GZFxU64v 3 | GL9CNz3hLSoCb7TckabgbVp6PIRy9cKEwfqnQ/2ohqrdolMA6Peru2+DgBs1iJ3u 4 | JNSc+8XFphUj0Jm2gVumVfclSZTEkM4xI4D3ABXn0Pj6/Ps5Skx9pXk3KI988ksB 5 | secD+FNqBPgmKWG0Gp+JSrPEwAtA4ZBP/4vtCGxEFzRCSOSBkTh27n1f08M4PjsY 6 | +vMvyTVF67y4Zb3nWJHpa1yOBlHid0xI138KPEBl+9Vai1AwRWbhlq52I9+IVjCo 7 | N7Ui9KbRgfd21SJFLh3hDw6xSrNqtcU+mvv5GuLAxHF5tCcGpAgKvKhvjQU4v+fh 8 | lGW77zkVAgMBAAECggEBAI8DoZsTyGIbDaovDgEGek3Tj1CSW64D9EyJavQBmSIT 9 | don0+9Y08XAOu4AhPqmaZ/5xLQEvnUo5Q4hkfOnh+svH2Z0qPymoAtshytmlSJQO 10 | KwzONtVaE+mfPGSes3DpcI/UlyWzRc+e15RbKUvaHohgIfLZs/Pe+yOjPF+y+h16 11 | Tpvklvk9GuS5/njOm0N8iRZw0+mKMLjwKCf0Q9WpF5OXW7hYccG9aTpmiUDnpixP 12 | nMyEdZMhmfFDLl+t6Txj3KhNX8jixDmfkuiPuoADWZuYk3GjS499nb3Y5Tmm8TLq 13 | jf0St48y1bObNnkceSqODnUK2hUZzzWcgTLwIC1E0DECgYEA+QoVuCA5i3eAiyE7 14 | PUsKpT0qVH/rWVWl0HYykUI7MSv0KJH7uPS+m2GzScxpCZoA4wtu6iK5IePNf645 15 | yJAleglx+1vuBGCWQrr206gOPWrkthfVHd+pDCr/fnIG+RdNr9SgwUx1youpovQ4 16 | x64RQuEyBXENt+xx2+fFI28GxEcCgYEA8skAisNqPgREewZ+hM2OkhIyU7GaKWgt 17 | HfjPYHHYWVO/sSfOdcyzcCUZJkseBhIVEmIeiXM4NCO0spmieHa6bo8oLr1nPMtm 18 | J4UkyVRPtO99V5mIBYOS3cWAEwEt7lWZ+4JiIyEBO/tMVjIrB8YkOE4LqV40Vvpu 19 | XGJbtw3JEcMCgYEA15xnmXYs3Bamb85hn3tsyArgry/g7wM7//OVbDXPUY8gYE+j 20 | hEpBC/3WX7pd5jYzNl8btBJD/pdfv39z/7Ts/W9YA6tfsuJ8tWFxeWYyjfIR+aVA 21 | mhCeJy7C7RKD/vyyAd0xIKm2AZpRUAfpcNe/kguuZw+uNOK84QsUnsztKtkCgYAE 22 | KBDMT2AoQ6ZwfMH5wBMqyQj3idjb0J7FHpdeTVSo4tgrTkUomyKPTvNJRovzCqg1 23 | slxXehOCQQI89Ihli5LRhb3oXvG/hrPvBUaF892ReXAp6cT8Yy5GgbUZnjGNHQYP 24 | 2kGX3F7LChhaeW1nKqtAE4X7llNLEeqFxmFPlvrURQKBgA0c5s3WPeX5OfSRsLaF 25 | iXaQNQ88QORNJ4hp/L7/o3ZNy7elH/R3GM1fs8Yf711CDxy4qI7icRYyrkl0P/Py 26 | WyRbNnvw0JMa5xkzRgKlnvspfEfve7gzcZhE9yEw173MIyyoxIn43G9aGNSN3QIR 27 | 51ZlCYyuIAgR7p+9lKvM74HR 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /tests/inputs/key5.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC97ivgsBuj3K8o 3 | M3e7JAq7Uqnw7ranSP4xqHg22fxf0q5uD4kJdnt5tjTVCiamFtWjm0OFrtXutKUk 4 | Y3YvFc83DUKreIDcnlbqwitS0V4JpR4xKQEnhUm2UeHrnkkQmObS6HhfSBKN0hO1 5 | hbUzNib3PsDFr8+/mNBkQzT7F+0+91YEC6R5nLwMckEPOpQyoEXNcawWp3L3gNjn 6 | fxnIYUVHCXgORNDGF03zbQ69+LLkqTCs7TC/Ze3ZBfrMWu0KEnCqb6QBMqFT/B+h 7 | JiG9LLZnaEjO0FqrIAjWtc2nnv+fFECBtzJVHe3BZmo1hu0VfXS1z1mlqPu0OAyA 8 | buQsjid1AgMBAAECggEAXIGUfWtJCxaBeWMX/d4gG/y3KNIbxH6Y0Dbt1kl10nYa 9 | 3yBR7nn2yeEk+l5nVJ3qkDUfPg1ZxVnW1VJcTbKhqn6a6klW+h1k2BKaZ0vyMWBq 10 | xCbkmQsiS9q13rzJeXv/cNopRr8jyk93qgHlr3vAnsvBuIdY+EjFtw/EzkdpFjEq 11 | i0LYRb+Yrc6+wEM7E5Sr44KVN4Y2iiQbV/wZDlzd0xPhmpFCjRBAci2Se9ayvloT 12 | tT7oB7hGO2n2gWfqsEl72fLMta7iw5pK5hv9dI3ioT7oB74gjm1AzBaIrTtuPJNP 13 | pAytQgE1WGm9LndezW3GjpIf23XKZjOi6Xt8StK2AQKBgQDli3FM56xeiR2ToHrE 14 | KvCymtvwimnsCZbChJuJ1zTN6alZRIH7HQHHoPLzll2O8FC2f2dVHl7wuO1kpIVg 15 | yDFWqDgJK4FDEY9zD3+LA1r94EEK/aJQKRt+s6vr+QAfTmwrlLmNFXjbufISNDfc 16 | 1I/g7BE+FlqRQzKYVQEYA0q/HQKBgQDT0e9j8sIN2LueTHjCoUmxSZELBpEUVgaH 17 | 2myZvSgBcDmWI5AK7VQJclEBixv8ZCN22M9oWAKkbRZC6Zx5+FFpy/LFf15G4pes 18 | b/m2SdUguz08/m1+R+fuJvUvB4OUiqUpJDLChC4vuO3ycANgSY2Ptgo26Vebntj7 19 | UIbGFFriOQKBgFLT3i5B6pCyKVn7rlDarb/E4VgKme3yB9RoxTcX0JX8mn77mWtj 20 | LCE8km4S8++AB5/SmRa9vsRd9ks6kmY51pPOX2nvqNTqoTiDfyJKM6soIFA29Tq3 21 | mpQ9gOvFDaY+RgnzwICIHvQqRI8NCJtGmCQxCoe8yTFhbgBJq/teNLqBAoGAZ1N0 22 | JFxJ/vknZGvHSKHm0b2iLC+y26mvG9wXt9MGzdTRsoR8gmgM42LJUyhpqW+rwRC3 23 | 9B1ihJTWFCPi+biA9kvPjDm6YnesJyikNiDD/2h20ecGwGARKiIE3kEbFX2gXXZT 24 | 8IEMCql6IRY0/2ZB0MWrK+gdnUMac1VvuPY68zkCgYEAlhq4bOiNgfaas3HRIq9L 25 | G0gygLNOXI2o2COz9buvaO2EzTdBkE/9W8nOpoMbrgeCYdCuq8WBPLqJrHltV8x9 26 | 2WLDZ29N8ukY+En8QirH6EGbsCh8n9YySw8y8Aumg7JpNdXQbkV3tg45vMF8W7+x 27 | uKZAxDuQlE106QsOU6h+jS0= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /tests/inputs/key6.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDhTELfLg93kERh 3 | NIxHoZGI8WXU0oBwSFBvCdinO0wyIckaf2B4nJpQStYApdrgHtL5SwhHMpYUc+up 4 | iUBCmhlzUSN1bZDC/hoBuPS1B7a6/vR/2fOWnPSYzVx7xdvh9cKzKnAjEt03eZzC 5 | euSZbLK98EXyVnem2h/4woSADe/RkjRuzj0SQB/JmSbpGDy5omoNKQemjzsD0bkZ 6 | E58tGl+2NxtYYo8/r25OwaHjqFnvzidVDn9Zv214Bb+eJMSpTQrvchn7hDLbwU5H 7 | 1/k7vmffOCYVPtIvuEjhpNg3sfGPDtuwcZkj3rlv3fHnahEaAs46oVAhG3L1rVeM 8 | gF62IHg9AgMBAAECggEBAKyYHYqX4KV50cid1vFxJuq/84DsmhRqcaP+6QiD9sVY 9 | +JTiC+eaIOVtzy/D3z9encT45CiW6j5U566DRMVBBEpBWGa3PvUCcK3tIRomBKiQ 10 | dIIVV/SD3SXJ/RWc5+vcuAFFe46C/xFmit66ArI+gVfc39jcwOEDrQaHDbaD9rqW 11 | VGRG9kL07HU/h4i/E2Bon3d2MfLcokGuDwchULYBgUSv4YS8w00eKeaPoG0yrjmo 12 | 8DqTNNX1tAIKql7h2Pw4RKhkt5LACoAKP8LumWFz0gVXmIy0lr0sZiVtMsMT1oXh 13 | nFabQILTQy52ZjzoUTwYgLJF5N9B/qyNmioIGXzdocECgYEA+qG/UI+f3F1be0wv 14 | zwSNaQz0CsL4jKnZeMXTaIc8Bq9oho4RLi2RrfzN+kVx7/his52ontC5G00U1EAP 15 | JxvY8NI3eFW3piEUJql8X/l/6sZ0giWfS4W3RercIF1NUuyrHuXG//iMp3wEPlVr 16 | 5G+JPLFQtsLNWk9L28aoC9idxmkCgYEA5h+apMnKrgV/C6/NOtpGK0VhsuWyVREF 17 | ngINf+yE4nGF45ELaR4aAN6iqEbUoN7l2UpyERJbstsrRSm/TOV3R4CFERLT4C3M 18 | MDBmu7etjr5XNKyq5k1PBPlRBgJQqgwchhlI5VujyVrADMkpQAJnOn4dTCIXfIa0 19 | VqTSla1zsLUCgYBDWHcZ5J3mDsfoJ56pF+YPlkV1JtK2qWUgSLf33G7KtRN3JHGF 20 | YQVGJSoL1+E3xBxxeym2EwvKRDoWlmf78EWo4DO7h/zjDPxnLx+WgmpW4aCo4Acf 21 | ufx3MxaXM7r1T1bj5IZGfbj9wBs7zKRDK51Ky7KOiWW4oJoXohfBpyEuEQKBgBmT 22 | oah3FSPKUJiH7ZOA9xOQHo+3n958iddJ+x4gt5RDcdIdKNuCEPnPxNxXIwLOQ1Wn 23 | RI5JMA/s9B43yZ9OUbeMvT1sjkf4Tx18A68RdyTKWv7rwgLezM2MuEimsTh1KCZv 24 | YP689LNIdtf087S9j6OcqLzxfRLGFf0bTJx+LsGRAoGBAOx2DiaRAf3XsgMoBJtf 25 | q9LSfjUqkkZW0Z2JBiKXIJduU/lhuBqHOtcRH1AQq6VCQgWXpgjW366a9VML5puj 26 | vPGQMFL5IG+bnBldOt7QJt9SE8gy8kUHXBKPJXoxwFMdl+VkuxT24jD5yj2m75wE 27 | QJkUy5pGLW8L9yopgh6yZU4e 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /tests/inputs/key8_hs256.pem: -------------------------------------------------------------------------------- 1 | 012345678901234567890123456789XY -------------------------------------------------------------------------------- /tests/inputs/key9_hs384.pem: -------------------------------------------------------------------------------- 1 | aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllll -------------------------------------------------------------------------------- /tests/inputs/pubkey4.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7C8R+hmRcVOuLxi/Qjc9 3 | 4S0qAm+03JGm4G1aejyEcvXChMH6p0P9qIaq3aJTAOj3q7tvg4AbNYid7iTUnPvF 4 | xaYVI9CZtoFbplX3JUmUxJDOMSOA9wAV59D4+vz7OUpMfaV5NyiPfPJLAbHnA/hT 5 | agT4JilhtBqfiUqzxMALQOGQT/+L7QhsRBc0QkjkgZE4du59X9PDOD47GPrzL8k1 6 | Reu8uGW951iR6WtcjgZR4ndMSNd/CjxAZfvVWotQMEVm4ZaudiPfiFYwqDe1IvSm 7 | 0YH3dtUiRS4d4Q8OsUqzarXFPpr7+RriwMRxebQnBqQICryob40FOL/n4ZRlu+85 8 | FQIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/inputs/pubkey5.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAve4r4LAbo9yvKDN3uyQK 3 | u1Kp8O62p0j+Mah4Ntn8X9Kubg+JCXZ7ebY01QomphbVo5tDha7V7rSlJGN2LxXP 4 | Nw1Cq3iA3J5W6sIrUtFeCaUeMSkBJ4VJtlHh655JEJjm0uh4X0gSjdITtYW1MzYm 5 | 9z7Axa/Pv5jQZEM0+xftPvdWBAukeZy8DHJBDzqUMqBFzXGsFqdy94DY538ZyGFF 6 | Rwl4DkTQxhdN820Ovfiy5KkwrO0wv2Xt2QX6zFrtChJwqm+kATKhU/wfoSYhvSy2 7 | Z2hIztBaqyAI1rXNp57/nxRAgbcyVR3twWZqNYbtFX10tc9Zpaj7tDgMgG7kLI4n 8 | dQIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/inputs/pubkey6.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4UxC3y4Pd5BEYTSMR6GR 3 | iPFl1NKAcEhQbwnYpztMMiHJGn9geJyaUErWAKXa4B7S+UsIRzKWFHPrqYlAQpoZ 4 | c1EjdW2Qwv4aAbj0tQe2uv70f9nzlpz0mM1ce8Xb4fXCsypwIxLdN3mcwnrkmWyy 5 | vfBF8lZ3ptof+MKEgA3v0ZI0bs49EkAfyZkm6Rg8uaJqDSkHpo87A9G5GROfLRpf 6 | tjcbWGKPP69uTsGh46hZ784nVQ5/Wb9teAW/niTEqU0K73IZ+4Qy28FOR9f5O75n 7 | 3zgmFT7SL7hI4aTYN7Hxjw7bsHGZI965b93x52oRGgLOOqFQIRty9a1XjIBetiB4 8 | PQIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/inputs/pubkey_jwr1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA33TqqLR3eeUmDtHS89qF 3 | 3p4MP7Wfqt2Zjj3lZjLjjCGDvwr9cJNlNDiuKboODgUiT4ZdPWbOiMAfDcDzlOxA 4 | 04DDnEFGAf+kDQiNSe2ZtqC7bnIc8+KSG/qOGQIVaay4Ucr6ovDkykO5Hxn7OU7s 5 | Jp9TP9H0JH8zMQA6YzijYH9LsupTerrY3U6zyihVEDXXOv08vBHk50BMFJbE9iwF 6 | wnxCsU5+UZUZYw87Uu0n4LPFS9BT8tUIvAfnRXIEWCha3KbFWmdZQZlyrFw0buUE 7 | f0YN3/Q0auBkdbDR/ES2PbgKTJdkjc/rEeM0TxvOUf7HuUNOhrtAVEN1D5uuxE1W 8 | SwIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/new_inputs/es256.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.dVNftrYfhBrS7tNzJj5UKM-GTzFfZpL7rTUsrYUFn9m0EFPtFT85DVcWI5mYrkms7TMhcU9i18CAna_Xd0qCBA 2 | -------------------------------------------------------------------------------- /tests/new_inputs/es256.jwt.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs/o5+uQbTjL3chynL4wXgUg2R9 3 | q9UU8I5mEovUf86QZ7kOBIjJwqnzD1omageEHWwHdBO6B+dFabmdT9POxg== 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /tests/new_inputs/es384.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.OV5MNaEE7_4ThrHY_-ighEG-UgWiSwHE7gAYCCl8vF9EbEJl_a9w6zIPNsRdFvInLusF_kSjWPy0b4DL4tvdtD1uS7W527ymlM87HrJwXnSI5PWIeR9OjPIGtz8iIyzG 2 | -------------------------------------------------------------------------------- /tests/new_inputs/es384.jwt.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEC1uWSXj2czCDwMTLWV5BFmwxdM6PX9p+ 3 | Pk9Yf9rIf374m5XP1U8q79dBhLSIuaojsvOT39UUcPJROSD1FqYLued0rXiooIii 4 | 1D3jaW6pmGVJFhodzC31cy5sfOYotrzF 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /tests/new_inputs/es512.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.AMWnDOy7ViaFrN0MTIp5uRXjQTsltKJGPfEmKyU3jWQFo4RPAAq_h0wseD1A5Amr97G-Mp99GuaOerkKle1A1OiYARSssUFGuCSrUYsDW2Yl1ZRYQ44JGkNPl_qmADQnenm7rDhoGz5z-va3a7AFxEFg-F9uV3cswaJwPj2agKOgIJZI 2 | -------------------------------------------------------------------------------- /tests/new_inputs/es512.jwt.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ 3 | PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47 4 | 6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM 5 | Al8G7CqwoJOsW7Kddns= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /tests/new_inputs/hdr_b64.inv: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI|NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.FoFCmBgmsAWmK-O-TjbztS2RKOYNxkzNz1fw46sygTA 2 | -------------------------------------------------------------------------------- /tests/new_inputs/hs256.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.FoFCmBgmsAWmK-O-TjbztS2RKOYNxkzNz1fw46sygTA 2 | -------------------------------------------------------------------------------- /tests/new_inputs/hs384.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.6PfKsXyhZE3X6NPWtlA7340eml8if1rOAxcK4hke0Hlpc8AseNaw4FHdx0YuV_s_ 2 | -------------------------------------------------------------------------------- /tests/new_inputs/hs512.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.nz-dS4bAFaM6uYicJn5FJxS8tCoHdvBKNQ5iOuOEpb9xo1sAYsiISZR_Ytkn_VruVW8B7G7I3gx3Jxwrdtws7Q 2 | -------------------------------------------------------------------------------- /tests/new_inputs/ps.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv 3 | vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc 4 | aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy 5 | tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0 6 | e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb 7 | V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9 8 | MwIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/new_inputs/ps256.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.DpngS9JGahV4YpgPJa-PHMhVmPdBlXCaBjZ0XE9WkDBeRP0y_pCWFbIp-6F8nXa1BmG9Tw2fPQ85yZUxyFHCVacq8sCZdlAdgGvd4xbpEJ-RErLu0d4Sqh2QrqG-mjF6esJRdyZTVircc16PbE54lGlnXoKqcf3Ef5YtR7X35nm5lcyZYEtfDvBDNCOjFHP1V1i_frcHDs9Mria2KGVPP5xyWNauq3zXBZRizsGF9q5j28bkkBVXv-NlYUGm-nKCJFCs0zIgTGnYt6lW2eWZoYsdalkHbvOv3m9_KVQCKKyzRY4yOsqjXeHaZndmxSKTp4UMsEN5ZCPQ1y7TeX3xwg 2 | -------------------------------------------------------------------------------- /tests/new_inputs/ps384.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.Jt2SaHKp56wizHwwzomeRo-9a4M6ODg02sB7cZUZslEg-1QtoDTGHXZvF73KmG8AJ9S2r4FbhZ9mmP_wL4OJs2fObA3RdMkyd2P1rpdXfXpK7mXU10fzQzT-l7RHQ3MqKkALs1iaczSp-rUOB-FiekkrAGSca0K02oHM9rpXxICL4Gc_nV-mk32e-R7jihV3BCX_8zpQoBt0cUwufW6R1GyD6DdmOErU0cTqa6t0oTmZIFNARCZ4AXj-GRajwN5meEwFjtmyGAXCL9bZl8Sv_7FsNEnscW8UaL9CWIz_4CInAdFnWFj4EGNKfKt60lfdNPUAxZYPERXFkxBbcqQXBg 2 | -------------------------------------------------------------------------------- /tests/new_inputs/ps512.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.eNEMgOnNsR1ac_uvZwdS6KpuSozlk4-5oAYUdqhthPB_R6ACdlhtY3p9wijr-ofWaj-xaPV5f3ILIAwI4o_dfPNjZwjKAAhAD1HFdWTx0hxi5siky6IrTvbf21MazLVmnsaYB4ssZJNzJdYkxXuiid38_gZ1mazd_lFeUEiDw7vwSDdrFsyibGbCslxNTDSl2Fp1KnWSWPD4TKTqdErHUkeC06lbdx92i3v1G2ASmZiCsjjZC1R5FzufbJCyicEnG7bcWBFhH6pMxPOCyyqAgGzKoVoL3yHZAq4XZD1X0f2eOlNJBMG5iN-hXVjShVGHRN5pv0LBHkWAJMi2FX5VeQ 2 | -------------------------------------------------------------------------------- /tests/new_inputs/rs-alt.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA1HA6cmqM98p7iqiNi36Jzb82d5CUOMq6Owo+5vUppTsBhQY3 3 | wci/M1wjSonYkelohYH+2TUb/qmyp+ooJYUGjkMEs54c+Nun+mGvEZc31fUxe7LO 4 | w87wygWTwEydIydrS/GllKgMRwHKWohnq4QPrCG1gzB/G5M9zods6P2svRgGPuuU 5 | +jq7TiYVdSzPiLsUTOGLUvaoo+8IKbwDTZ764Ww4auWSstBRCluo3Gey7f0YaORi 6 | 6WvoecFwYP4ABgNXD4SYSOiy+qRDb3lkTwlLvuuISfcnWGPnw0wPvhnU4O+f8x/6 7 | G5fOgI/mMK4roHVJ09gjexNsBuT7ugCpoQcw/QIDAQABAoIBACaDJgViDaZKXfU4 8 | M1jrmr3jAVPRsR1Om05iwB6MqX0b4l2kT+1goFEGThuQO+PP5bP2aiYke6vCRfIt 9 | ABQ1NogJ3EtXybbP03cPyHYu7N9r8QmU0+kplft54VxGR2J9HfWJnFQD1x30VCPv 10 | gKPWcCTrg4WCADkWi2jqojLm8i7hXIb8meU23R/LotXE8ykKEvkLUx3MokgrF6qA 11 | aDio+b+g5fqxABvb8h1R66RR1v6dV1J/Z6RaWxAaozAZsAEE00SE9F1JGte7mER+ 12 | iyP0+/FAJZ0E5WhZQj+kUxsAPcN4XIl8ZMPTGztZ7dTtXxRqElJNgE51r8JW5qR3 13 | wVj50d0CgYEA7WQc4KgijfB3NR9l/8Gf9imlACpUYt3e6oeAYMUYVUMj7Q8mEygF 14 | 5RZsBz3RPeArfF+JU+pYFzXVok1xvnGbx/DyBaTAl+S+9/DFRSgnmDYj7faX+OPM 15 | OVNTLkevg1nWwdcwxeofvN4eGUR4KJsJgicBv/Z5ihxeiK8+T4uFu+MCgYEA5Rdf 16 | kUSGZ4dWsT8BjN/hQ4TnFa6ISP0K+DcfBsS+4DaQDepILNkG1w6s1h/WfPk2behq 17 | jEEeeWiDrv1bbavUbg8TUZXs71k+AQFIVHLKAHO58ekiUtJOwOI+w1q4TVqUDTxX 18 | s5MO5Y+halkl9YmQyCmkPFiquj9c80KkwBJgtZ8CgYBy92gQ2PybFxj0Tjd8rE4G 19 | zlZNhTKHCwKZPHRM6UcGi9SLSynaXyizsK8ytppuR/Fnc3EzhauR2g2TY8QxQh36 20 | r9LWLtri9PITa7Rt8Kt0SMwPw7wH2nKeVJ9VK3xxtYGPMOM7Bk7Gjh+vhvxWVfc9 21 | 5Bwx1nE4FNMniQ85QM3MlwKBgQDEMptPLw+olJjjXaF3Q7mJeMXrpLjlQYlmgNaa 22 | ll8eaLxAnpfHiOq5vcC59TRdfZVm1XiCu7Zcpey5LhRiPZnF1DVoVu0/Iv/eHnoS 23 | kOh9MJ9cFZymr6RwvpKf/g7/eIZ5O2ekzFoisjq8eLLwsSsEsd0NLaaxsVhqoXW1 24 | ZUfb4wKBgH/t3ZP8g9833qeJyL3rcdsbpVVHFZe+3T+aTwUiYvQ1TavV4zLskZx6 25 | k5/XghVTYoEPBKHOGxOXHSNF+IbjXuysimonbXcCkaHA3ciiFYuJqnntNj4Xr2Ns 26 | RHOY7fKEh8cD7dSEfVp30cSKYGRf7Bbdz+3TpqcKQRNmKpzGrf42 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /tests/new_inputs/rs-alt.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1HA6cmqM98p7iqiNi36J 3 | zb82d5CUOMq6Owo+5vUppTsBhQY3wci/M1wjSonYkelohYH+2TUb/qmyp+ooJYUG 4 | jkMEs54c+Nun+mGvEZc31fUxe7LOw87wygWTwEydIydrS/GllKgMRwHKWohnq4QP 5 | rCG1gzB/G5M9zods6P2svRgGPuuU+jq7TiYVdSzPiLsUTOGLUvaoo+8IKbwDTZ76 6 | 4Ww4auWSstBRCluo3Gey7f0YaORi6WvoecFwYP4ABgNXD4SYSOiy+qRDb3lkTwlL 7 | vuuISfcnWGPnw0wPvhnU4O+f8x/6G5fOgI/mMK4roHVJ09gjexNsBuT7ugCpoQcw 8 | /QIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/new_inputs/rs.partial: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv 3 | vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc 4 | V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9 5 | MwIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /tests/new_inputs/rs.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv 3 | vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc 4 | aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy 5 | tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0 6 | e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb 7 | V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9 8 | MwIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /tests/new_inputs/rs256.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.e-pFjFcKyrWa6ODgkclHe26EEF6AkI-xaW6J-Z37IdfygRKmgqy5cIzhjIGBPQg2aJGrPmCc5zP-zeK1M98odo5OCxCDdfQsKTtJJlCIVC2Iv1CaZDc-dTNnmjZE6PBM9fzwhXd5ESNjSxhtHSt8_9gFmogaixcxD1D7AnSJ1kl-o9yVK2vBRTHfFEyx5npUGbuNGSdIcoUHQUvL3B55XhQW_IlTmoYUjBKAg0Mqk1HAhzQ-ZXz2C6Ptopx9ga3ccK4QmXnUHwo_bRF7eIhWweMfy_JM7pNGZc1VGa0hCpp-Axwq3CZfwLL0DY7ohcSYfJN_4d4Qn72S8EHKg_E5Ng 2 | -------------------------------------------------------------------------------- /tests/new_inputs/rs384.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.nQkVc533UNJnuGkC4UuseIxShDbqbF1jBm5xe8jlJuXsNG3MPRRbVi8Gd6TFUi-4AIu9jhodknZVwW7UhbkHiJ0gMIpmCBvrrG8IQfNGuFGDWJemEdQJt5jU9ZO654DpwAa4Ru1cN7VoPProf27iUR8f73NwIfMQ63NmVQMFAzHbMuHiRKaI560_6-UPdzQFgAb7yjJWmOuSR0iK7F6WR0MFnE_g5uHyEsnkp0wRDO41qdqFmJoFO5sMORLfP_eaHgJfD5EdxexQTyVwUkamB-FR6pUK5t_2ELeX4umdf4UB-b2SQ7hDlrJcQ6QPgXAq9ySvldgyID8JUpx7yV7HJA 2 | -------------------------------------------------------------------------------- /tests/new_inputs/rs512.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.Dfq1xuOesBKAjQToECv0OcwwuWC4aBn4XcPNT7OccGKGCCJXXP7cg-RQez-36qRFHm6HCkVjE1vfEGKawBLj17aFVmywpQ7ZapBbFvt2aVy3nr6IOJO4JnVFmVtA77WOWHM0cp7l9xTtEchGPwprN1BFeM5bXsj_vmILpR8t3z8eRCj4JIIXU6cjWFKLKmx0T4UihrPWE8_GpyG5CsKet3u5FWeGHn91A8Ds4gAooSuWbmSmMORshD8q6LH5g7YtUwTx0Y6ZIZ9H-pIZZ3hAD1trcIXKAgfcB3YC5GTqMifDAhyf14hagECIew442nLVFwfEysLinvknaqBWvhKHLQ 2 | -------------------------------------------------------------------------------- /tests/new_inputs/sig_b64.inv: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.FoFCmBg|sAWmK-O-TjbztS2RKOYNxkzNz1fw46sygTA 2 | -------------------------------------------------------------------------------- /tests/new_inputs/try_1.inv: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 2 | -------------------------------------------------------------------------------- /tests/new_inputs/try_2.inv: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0 2 | -------------------------------------------------------------------------------- /tests/new_inputs/try_4.inv: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.FoFCmBgmsAWmK-O-TjbztS2RKOYNxkzNz1fw46sygTA.foo 2 | -------------------------------------------------------------------------------- /tests/new_inputs/try_5.inv: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibGlicmFyeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS94bWlkdC1vcmcvY2p3dCIsImlhdCI6MTUxNjIzOTAyMn0.FoFCmBgmsAWmK-O-TjbztS2RKOYNxkzNz1fw46sygTA.foo.bar 2 | -------------------------------------------------------------------------------- /tests/test_cjwt.c: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2017-2022 Comcast Cable Communications Management, LLC 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "cjwt.h" 15 | 16 | typedef struct { 17 | int expected; 18 | const char *jwt_file_name; 19 | bool is_key_in_file; 20 | bool expect_symmetric; 21 | const char *key; 22 | const char *decode_test_name; 23 | } test_case_t; 24 | 25 | test_case_t test_list[] = { 26 | { 0, "jwtn.txt", false, false, "", "No Alg claims on on"}, 27 | { 0, "jwtnx.txt", false, false, "", "No Alg claims off on"}, 28 | { 0, "jwtny.txt", false, false, "", "No Alg claims off off"}, 29 | { EINVAL, "jwtia.txt", false, true, "test_passwd1", "HS256 invalid jwt"}, 30 | { EINVAL, "jwtib.txt", false, true, "test_passwd1", "HS256 invalid jwt"}, 31 | // { EINVAL, "jwtic.txt", false, true, "test_passwd1", "HS256 invalid jwt"}, /*TBD */ //FAILED test after modifying verify_signature logic 32 | { EINVAL, "jwtid.txt", false, true, "test_passwd1", "HS256 invalid jwt"}, 33 | { EINVAL, "jwtie.txt", false, true, "test_passwd1", "HS256 invalid jwt"}, 34 | { EINVAL, "jwtif.txt", false, true, "test_passwd1", "HS256 invalid jwt"}, 35 | { 0, "jwt1.txt", false, true, "test_passwd1", "HS256 claims on on"}, 36 | { EINVAL, "jwt1.txt", false, true, "test_passbad", "HS256 claims on on"}, 37 | { 0, "jwt2.txt", false, true, "test_passwd2", "HS384 claims on on"}, 38 | { EINVAL, "jwt2.txt", false, true, "test_passbad", "HS384 claims on on"}, 39 | { 0, "jwt3.txt", false, true, "test_passwd3", "HS512 claims on on"}, 40 | { EINVAL, "jwt3.txt", false, true, "test_passbad", "HS512 claims on on"}, 41 | { 0, "jwt5.txt", true, false, "pubkey5.pem", "RS384 claims on on"}, 42 | { EINVAL, "jwt5.txt", true, false, "badkey4.pem", "RS384 claims on on"}, 43 | { 0, "jwt4.txt", true, false, "pubkey4.pem", "RS256 claims on on"}, 44 | { EINVAL, "jwt4.txt", true, false, "badkey4.pem", "RS256 claims on on"}, 45 | { 0, "jwt6.txt", true, false, "pubkey6.pem", "RS512 claims on on"}, 46 | { EINVAL, "jwt6.txt", true, false, "badkey6.pem", "RS512 claims on on"}, 47 | { 0, "jwt1x.txt", false, true, "test_passwd1", "HS256 claims off on"}, 48 | { EINVAL, "jwt1x.txt", false, true, "test_prasswd1", "HS256 claims off on"}, 49 | { 0, "jwt2x.txt", false, true, "test_passwd2", "HS384 claims off on"}, 50 | { EINVAL, "jwt2x.txt", false, true, "twest_passwd2", "HS384 claims off on"}, 51 | { 0, "jwt3x.txt", false, true, "test_passwd3", "HS512 claims off on"}, 52 | { EINVAL, "jwt3x.txt", false, true, "test_passwd3...", "HS512 claims off on"}, 53 | { 0, "jwt4x.txt", true, false, "pubkey4.pem", "RS256 claims off on"}, 54 | { EINVAL, "jwt4x.txt", true, false, "pubkey5.pem", "RS256 claims off on"}, 55 | { 0, "jwt5x.txt", true, false, "pubkey5.pem", "RS384 claims off on"}, 56 | { EINVAL, "jwt5x.txt", true, false, "badkey5.pem", "RS384 claims off on"}, 57 | { 0, "jwt6x.txt", true, false, "pubkey6.pem", "RS512 claims off on"}, 58 | { EINVAL, "jwt6x.txt", true, false, "badkey6.pem", "RS512 claims off on"}, 59 | { 0, "jwt1y.txt", false, true, "test_passwd1", "HS256 claims off off"}, 60 | { EINVAL, "jwt1y.txt", false, true, "tast_passwd1", "HS256 claims off off"}, 61 | { 0, "jwt2y.txt", false, true, "test_passwd2", "HS384 claims off off"}, 62 | { EINVAL, "jwt2y.txt", false, true, "test..passwd2", "HS384 claims off off"}, 63 | { 0, "jwt3y.txt", false, true, "test_passwd3", "HS512 claims off off"}, 64 | { EINVAL, "jwt3y.txt", false, true, "tteesstt_passwd3", "HS512 claims off off"}, 65 | { 0, "jwt4y.txt", true, false, "pubkey4.pem", "RS256 claims off off"}, 66 | { EINVAL, "jwt4y.txt", true, false, "badkey4.pem", "RS256 claims off off"}, 67 | { 0, "jwt5y.txt", true, false, "pubkey5.pem", "RS384 claims off off"}, 68 | { EINVAL, "jwt5y.txt", true, false, "pubkey6.pem", "RS384 claims off off"}, 69 | { 0, "jwt6y.txt", true, false, "pubkey6.pem", "RS512 claims off off"}, 70 | { EINVAL, "jwt6y.txt", true, false, "pubkey5.pem", "RS512 claims off off"}, 71 | { 0, "jwt1l.txt", false, true, "test_passwd1", "HS256 claims long"}, 72 | { EINVAL, "jwt1l.txt", false, true, "test_keyword1", "HS256 claims long"}, 73 | { 0, "jwt2l.txt", false, true, "test_passwd2", "HS384 claims long"}, 74 | { EINVAL, "jwt2l.txt", false, true, "test_passwd1", "HS384 claims long"}, 75 | { 0, "jwt3l.txt", false, true, "test_passwd3", "HS512 claims long"}, 76 | { EINVAL, "jwt3l.txt", false, true, "passwd3", "HS512 claims long"}, 77 | { 0, "jwt4l.txt", true, false, "pubkey4.pem", "RS256 claims long"}, 78 | { EINVAL, "jwt4l.txt", true, false, "badkey4.pem", "RS256 claims long"}, 79 | { 0, "jwt5l.txt", true, false, "pubkey5.pem", "RS384 claims long"}, 80 | { EINVAL, "jwt5l.txt", true, false, "badkey5.pem", "RS384 claims long"}, 81 | { 0, "jwt6l.txt", true, false, "pubkey6.pem", "RS512 claims long"}, 82 | { EINVAL, "jwt6l.txt", true, false, "badkey6.pem", "RS512 claims long"}, 83 | { 0, "jwt2.txt", false, true, "test_passwd2", "HS384 claims on on"}, 84 | { 0, "jwt3.txt", false, true, "test_passwd3", "HS512 claims on on"}, 85 | { 0, "jwt8_hs256.txt", true, true, "key8_hs256.pem", "HS256 claims on on"}, 86 | { 0, "jwt9_hs384.txt", true, true, "key9_hs384.pem", "HS384 claims on on"}, 87 | { 0, "jwt10_hs512.txt", true, true, "key10_hs512.pem", "HS512 claims on on"}, 88 | { EINVAL, "jwt11.txt", false, false, "incorrect_key", "RS256 claims all"}, 89 | { EINVAL, "jwt12.txt", false, false, "incorrect_key", "RS256 claims all"}, 90 | { EINVAL, "jwt13.txt", false, false, "incorrect_key", "RS256 claims all"}, 91 | {ENOTSUP, "jwtbadalg.txt", false, false, "incorrect_key", "Invalid/unsupported alg."} 92 | }; 93 | 94 | #define _NUM_TEST_CASES (sizeof(test_list) / sizeof(test_case_t)) 95 | 96 | int open_input_file(const char *fname) 97 | { 98 | char cwd[1024]; 99 | 100 | if (getcwd(cwd, sizeof(cwd)) != NULL) { 101 | strcat(cwd, "/../tests/inputs/"); 102 | } else { 103 | perror("getcwd() error"); 104 | return -1; 105 | } 106 | 107 | if ((fname == NULL) || ((strlen(cwd) + strlen(fname)) > sizeof(cwd))) 108 | { 109 | perror("file name too long error"); 110 | return -1; 111 | } 112 | strcat(cwd, fname); 113 | int fd = open(cwd, O_RDONLY); 114 | 115 | if (fd < 0) { 116 | printf("File %s open error\n", fname); 117 | } 118 | 119 | return fd; 120 | } 121 | 122 | ssize_t read_file(const char *fname, char *buf, size_t buflen) 123 | { 124 | ssize_t nbytes = 0; 125 | int fd = open_input_file(fname); 126 | 127 | if (fd < 0) { 128 | return fd; 129 | } 130 | 131 | nbytes = read(fd, buf, buflen); 132 | 133 | if (nbytes < 0) { 134 | printf("Read file %s error\n", fname); 135 | close(fd); 136 | return nbytes; 137 | } 138 | 139 | close(fd); 140 | return nbytes; 141 | } 142 | 143 | static unsigned int pass_cnt = 0; 144 | static unsigned int fail_cnt = 0; 145 | 146 | void test_case(unsigned _i) 147 | { 148 | const char *jwt_fname; 149 | const char *key_str; 150 | const char *decode_test_name; 151 | int expected; 152 | int key_len; 153 | ssize_t jwt_bytes; 154 | cjwt_code_t result = 0; 155 | cjwt_t *jwt = NULL; 156 | char jwt_buf[65535]; 157 | char pem_buf[8192]; 158 | int options; 159 | jwt_fname = test_list[_i].jwt_file_name; 160 | key_str = test_list[_i].key; 161 | key_len = strlen(key_str); 162 | expected = test_list[_i].expected; 163 | decode_test_name = test_list[_i].decode_test_name; 164 | options = OPT_ALLOW_ALG_NONE | OPT_ALLOW_ANY_TIME; 165 | 166 | if (key_len == 0) { 167 | key_str = NULL; 168 | } else if (test_list[_i].is_key_in_file) { 169 | key_len = read_file(key_str, pem_buf, sizeof(pem_buf)); 170 | 171 | if (key_len >= 0) { 172 | key_str = (const char *) pem_buf; 173 | } else { 174 | printf("Error reading pem file\n"); 175 | CU_ASSERT(0 == 1); 176 | fail_cnt += 1; 177 | return; 178 | } 179 | } 180 | 181 | if (expected) { 182 | printf("\n--- Test %s expected good\n", decode_test_name); 183 | } else { 184 | printf("\n--- Test %s expected bad\n", decode_test_name); 185 | } 186 | printf("key in file %d, keylen = %d\n", test_list[_i].is_key_in_file, 187 | key_len); 188 | 189 | memset(jwt_buf, 0, sizeof(jwt_buf)); 190 | printf("--- Input jwt : %s \n", jwt_fname); 191 | jwt_bytes = read_file(jwt_fname, jwt_buf, sizeof(jwt_buf)); 192 | 193 | if (jwt_bytes > 0) { 194 | if (test_list[_i].expect_symmetric) { 195 | options |= OPT_ALLOW_ONLY_HS_ALG; 196 | } 197 | result = cjwt_decode(jwt_buf, strlen(jwt_buf), 198 | options, 199 | (const uint8_t *) key_str, key_len, 200 | 0, 0, &jwt); 201 | } else { 202 | result = jwt_bytes; 203 | } 204 | 205 | if ((0 == expected) && (CJWTE_OK == result)) { 206 | printf("--- PASSED: %s\n", decode_test_name); 207 | pass_cnt += 1; 208 | CU_ASSERT(CJWTE_OK == result); 209 | } else if ((0 != expected) && (CJWTE_OK != result)) { 210 | printf("--- PASSED: %s\n", decode_test_name); 211 | pass_cnt += 1; 212 | CU_ASSERT(CJWTE_OK != result); 213 | } else { 214 | printf("\x1B[01;31m--- FAILED: %s (%d != %d)\x1B[00m\n", decode_test_name, expected, result); 215 | fail_cnt += 1; 216 | CU_ASSERT(0 == 1); 217 | } 218 | 219 | cjwt_destroy(jwt); 220 | } 221 | 222 | 223 | void test_cjwt(void) 224 | { 225 | unsigned i; 226 | for (i = 0; i < _NUM_TEST_CASES; i++) 227 | test_case(i); 228 | } 229 | 230 | 231 | void add_suites(CU_pSuite *suite) 232 | { 233 | printf("--------Start of Test Cases Execution ---------\n"); 234 | *suite = CU_add_suite("tests", NULL, NULL); 235 | CU_add_test(*suite, "Test cjwt", test_cjwt); 236 | } 237 | 238 | /*----------------------------------------------------------------------------*/ 239 | /* External Functions */ 240 | /*----------------------------------------------------------------------------*/ 241 | int main(void) 242 | { 243 | unsigned rv = 1; 244 | CU_pSuite suite = NULL; 245 | 246 | if (CUE_SUCCESS == CU_initialize_registry()) { 247 | add_suites(&suite); 248 | 249 | if (NULL != suite) { 250 | CU_basic_set_mode(CU_BRM_VERBOSE); 251 | CU_basic_run_tests(); 252 | printf("\n"); 253 | CU_basic_show_failures(CU_get_failure_list()); 254 | printf("\n\n"); 255 | rv = CU_get_number_of_tests_failed(); 256 | } 257 | 258 | CU_cleanup_registry(); 259 | } 260 | 261 | return rv; 262 | } 263 | -------------------------------------------------------------------------------- /tests/test_map.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "cjwt.h" 10 | 11 | void test_map(void) 12 | { 13 | struct vector { 14 | const char *s; 15 | size_t len; 16 | cjwt_alg_t expected; 17 | cjwt_code_t rv; 18 | } tests[] = { 19 | { "none", SIZE_MAX, alg_none, CJWTE_OK}, 20 | { "ES256", SIZE_MAX, alg_es256, CJWTE_OK}, 21 | { "ES384", SIZE_MAX, alg_es384, CJWTE_OK}, 22 | { "ES512", SIZE_MAX, alg_es512, CJWTE_OK}, 23 | { "HS256", SIZE_MAX, alg_hs256, CJWTE_OK}, 24 | { "HS384", SIZE_MAX, alg_hs384, CJWTE_OK}, 25 | { "HS512", SIZE_MAX, alg_hs512, CJWTE_OK}, 26 | { "PS256", SIZE_MAX, alg_ps256, CJWTE_OK}, 27 | { "PS384", SIZE_MAX, alg_ps384, CJWTE_OK}, 28 | { "PS512", SIZE_MAX, alg_ps512, CJWTE_OK}, 29 | { "RS256", SIZE_MAX, alg_rs256, CJWTE_OK}, 30 | { "RS384", SIZE_MAX, alg_rs384, CJWTE_OK}, 31 | { "RS512", SIZE_MAX, alg_rs512, CJWTE_OK}, 32 | { "none_", 4, alg_none, CJWTE_OK}, 33 | { "ES256_", 5, alg_es256, CJWTE_OK}, 34 | { "ES384_", 5, alg_es384, CJWTE_OK}, 35 | { "ES512_", 5, alg_es512, CJWTE_OK}, 36 | { "HS256_", 5, alg_hs256, CJWTE_OK}, 37 | { "HS384_", 5, alg_hs384, CJWTE_OK}, 38 | { "HS512_", 5, alg_hs512, CJWTE_OK}, 39 | { "PS256_", 5, alg_ps256, CJWTE_OK}, 40 | { "PS384_", 5, alg_ps384, CJWTE_OK}, 41 | { "PS512_", 5, alg_ps512, CJWTE_OK}, 42 | { "RS256_", 5, alg_rs256, CJWTE_OK}, 43 | { "RS384_", 5, alg_rs384, CJWTE_OK}, 44 | { "RS512_", 5, alg_rs512, CJWTE_OK}, 45 | { "RS512_", 0, alg_none, CJWTE_INVALID_PARAMETERS}, 46 | { NULL, 0, alg_none, CJWTE_INVALID_PARAMETERS}, 47 | { NULL, 5, alg_none, CJWTE_INVALID_PARAMETERS}, 48 | { "none", 3, alg_none, CJWTE_UNKNOWN_ALG}, 49 | {"toolong", 7, alg_none, CJWTE_UNKNOWN_ALG}, 50 | { "tree", 4, alg_none, CJWTE_UNKNOWN_ALG}, 51 | { "trees", 5, alg_none, CJWTE_UNKNOWN_ALG}, 52 | }; 53 | cjwt_alg_t alg; 54 | 55 | for (size_t i = 0; i < sizeof(tests) / sizeof(struct vector); i++) { 56 | if (alg_none == tests[i].expected) { 57 | alg = alg_es256; 58 | } else { 59 | alg = alg_none; 60 | } 61 | CU_ASSERT(tests[i].rv == cjwt_alg_string_to_enum(tests[i].s, tests[i].len, &alg)); 62 | if (CJWTE_OK == tests[i].rv) { 63 | CU_ASSERT(tests[i].expected == alg); 64 | } 65 | } 66 | 67 | /* If a NULL alg is passed, check for that. */ 68 | CU_ASSERT(CJWTE_INVALID_PARAMETERS == cjwt_alg_string_to_enum("none", 4, NULL)); 69 | } 70 | 71 | 72 | void add_suites(CU_pSuite *suite) 73 | { 74 | *suite = CU_add_suite("Print tests", NULL, NULL); 75 | CU_add_test(*suite, "cjwt_alg_string_to_enum() Tests", test_map); 76 | } 77 | 78 | 79 | /*----------------------------------------------------------------------------*/ 80 | /* External Functions */ 81 | /*----------------------------------------------------------------------------*/ 82 | int main(void) 83 | { 84 | unsigned rv = 1; 85 | CU_pSuite suite = NULL; 86 | 87 | if (CUE_SUCCESS == CU_initialize_registry()) { 88 | add_suites(&suite); 89 | 90 | if (NULL != suite) { 91 | CU_basic_set_mode(CU_BRM_VERBOSE); 92 | CU_basic_run_tests(); 93 | printf("\n"); 94 | CU_basic_show_failures(CU_get_failure_list()); 95 | printf("\n\n"); 96 | rv = CU_get_number_of_tests_failed(); 97 | } 98 | 99 | CU_cleanup_registry(); 100 | } 101 | 102 | if (0 != rv) { 103 | return 1; 104 | } 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /tests/test_print.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "cjwt.h" 10 | 11 | void test_print(void) 12 | { 13 | // clang-format off 14 | cjwt_t jwt = { 15 | .header.alg = alg_rs512, 16 | .iss = (char*) "Issuer Claim", 17 | .sub = (char*) "Sub Claim", 18 | .jti = (char*) "JTI Claim", 19 | .aud.count = 2, 20 | .aud.names = (char*[2]) { "Aud Item", "foo" }, 21 | .exp = (int64_t[1]) { 100 }, 22 | .nbf = (int64_t[1]) { 2000 }, 23 | .iat = (int64_t[1]) { 40000 }, 24 | .private_claims = cJSON_CreateObject(), 25 | }; 26 | // clang-format on 27 | 28 | /* This is generally a debugging tool & validating the output is 29 | * less of a priority than not crashing. */ 30 | 31 | cjwt_print(stdout, NULL); 32 | 33 | cjwt_print(stdout, &jwt); 34 | 35 | cJSON_Delete(jwt.private_claims); 36 | memset(&jwt, 0, sizeof(cjwt_t)); 37 | 38 | cjwt_print(stdout, &jwt); 39 | } 40 | 41 | 42 | void add_suites(CU_pSuite *suite) 43 | { 44 | *suite = CU_add_suite("Print tests", NULL, NULL); 45 | CU_add_test(*suite, "cjwt_print() Tests", test_print); 46 | } 47 | 48 | 49 | /*----------------------------------------------------------------------------*/ 50 | /* External Functions */ 51 | /*----------------------------------------------------------------------------*/ 52 | int main(void) 53 | { 54 | unsigned rv = 1; 55 | CU_pSuite suite = NULL; 56 | 57 | if (CUE_SUCCESS == CU_initialize_registry()) { 58 | add_suites(&suite); 59 | 60 | if (NULL != suite) { 61 | CU_basic_set_mode(CU_BRM_VERBOSE); 62 | CU_basic_run_tests(); 63 | printf("\n"); 64 | CU_basic_show_failures(CU_get_failure_list()); 65 | printf("\n\n"); 66 | rv = CU_get_number_of_tests_failed(); 67 | } 68 | 69 | CU_cleanup_registry(); 70 | } 71 | 72 | if (0 != rv) { 73 | return 1; 74 | } 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /tests/test_utils.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: 2021-2022 Comcast Cable Communications Management, LLC */ 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../src/utils.h" 10 | 11 | 12 | struct test_vector { 13 | const char *full; 14 | size_t len; 15 | int rv; 16 | struct split_jwt goal; 17 | }; 18 | 19 | void test_split(void); 20 | 21 | void test_split(void) 22 | { 23 | // clang-format off 24 | struct test_vector tests[] = { 25 | { .full = "abcdefghijkl", 26 | .len = 12, 27 | .rv = -1, 28 | }, 29 | { .full = "a.b.c.d.e.fghijkl", 30 | .len = 17, 31 | .rv = -1, 32 | }, 33 | { .full = "abcd.efg", 34 | .len = 8, 35 | .rv = 0, 36 | .goal = { 37 | .count = 2, 38 | .sections = { 39 | { .data = "abcd", .len = 4 }, 40 | { .data = "efg", .len = 3 }, 41 | { .data = NULL, .len = 0 }, 42 | { .data = NULL, .len = 0 }, 43 | { .data = NULL, .len = 0 }, 44 | }, 45 | }, 46 | }, 47 | { .full = "abcd.efg.hij", 48 | .len = 12, 49 | .rv = 0, 50 | .goal = { 51 | .count = 3, 52 | .sections = { 53 | { .data = "abcd", .len = 4 }, 54 | { .data = "efg", .len = 3 }, 55 | { .data = "hij", .len = 3 }, 56 | { .data = NULL, .len = 0 }, 57 | { .data = NULL, .len = 0 }, 58 | }, 59 | }, 60 | }, 61 | { .full = "abcd.efg.hij.klm", 62 | .len = 16, 63 | .rv = 0, 64 | .goal = { 65 | .count = 4, 66 | .sections = { 67 | { .data = "abcd", .len = 4 }, 68 | { .data = "efg", .len = 3 }, 69 | { .data = "hij", .len = 3 }, 70 | { .data = "klm", .len = 3 }, 71 | { .data = NULL, .len = 0 }, 72 | }, 73 | }, 74 | }, 75 | { .full = "abcd.efg.hij.klm.op", 76 | .len = 19, 77 | .rv = 0, 78 | .goal = { 79 | .count = 5, 80 | .sections = { 81 | { .data = "abcd", .len = 4 }, 82 | { .data = "efg", .len = 3 }, 83 | { .data = "hij", .len = 3 }, 84 | { .data = "klm", .len = 3 }, 85 | { .data = "op", .len = 2 }, 86 | }, 87 | }, 88 | }, 89 | { .full = "abcd.efg..klm.op", 90 | .len = 16, 91 | .rv = 0, 92 | .goal = { 93 | .count = 5, 94 | .sections = { 95 | { .data = "abcd", .len = 4 }, 96 | { .data = "efg", .len = 3 }, 97 | { .data = "", .len = 0 }, 98 | { .data = "klm", .len = 3 }, 99 | { .data = "op", .len = 2 }, 100 | }, 101 | }, 102 | }, 103 | { .full = "....", 104 | .len = 4, 105 | .rv = 0, 106 | .goal = { 107 | .count = 5, 108 | .sections = { 109 | { .data = "", .len = 0 }, 110 | { .data = "", .len = 0 }, 111 | { .data = "", .len = 0 }, 112 | { .data = "", .len = 0 }, 113 | { .data = "", .len = 0 }, 114 | }, 115 | }, 116 | }, 117 | { .full = "d....g", 118 | .len = 6, 119 | .rv = 0, 120 | .goal = { 121 | .count = 5, 122 | .sections = { 123 | { .data = "d", .len = 1 }, 124 | { .data = "", .len = 0 }, 125 | { .data = "", .len = 0 }, 126 | { .data = "", .len = 0 }, 127 | { .data = "g", .len = 1 }, 128 | }, 129 | }, 130 | }, 131 | { .full = "dog.", 132 | .len = 4, 133 | .rv = 0, 134 | .goal = { 135 | .count = 2, 136 | .sections = { 137 | { .data = "dog", .len = 3 }, 138 | { .data = "", .len = 0 }, 139 | { .data = "", .len = 0 }, 140 | { .data = "", .len = 0 }, 141 | { .data = "", .len = 0 }, 142 | }, 143 | }, 144 | }, 145 | }; 146 | // clang-format on 147 | 148 | for (size_t i = 0; i < sizeof(tests) / sizeof(struct test_vector); i++) { 149 | struct split_jwt got; 150 | int rv; 151 | 152 | rv = split(tests[i].full, tests[i].len, &got); 153 | 154 | CU_ASSERT(rv == tests[i].rv); 155 | if (0 == tests[i].rv) { 156 | CU_ASSERT_FATAL(got.count == tests[i].goal.count); 157 | 158 | for (size_t j = 0; j < got.count; j++) { 159 | CU_ASSERT(got.sections[j].len == tests[i].goal.sections[j].len); 160 | 161 | for (size_t k = 0; k < tests[i].goal.sections[j].len; k++) { 162 | CU_ASSERT(got.sections[j].data[k] == tests[i].goal.sections[j].data[k]); 163 | } 164 | } 165 | } 166 | } 167 | } 168 | 169 | 170 | void add_suites(CU_pSuite *suite); 171 | 172 | void add_suites(CU_pSuite *suite) 173 | { 174 | *suite = CU_add_suite("Utils tests", NULL, NULL); 175 | CU_add_test(*suite, "split() Tests", test_split); 176 | } 177 | 178 | 179 | /*----------------------------------------------------------------------------*/ 180 | /* External Functions */ 181 | /*----------------------------------------------------------------------------*/ 182 | int main(void) 183 | { 184 | unsigned rv = 1; 185 | CU_pSuite suite = NULL; 186 | 187 | if (CUE_SUCCESS == CU_initialize_registry()) { 188 | add_suites(&suite); 189 | 190 | if (NULL != suite) { 191 | CU_basic_set_mode(CU_BRM_VERBOSE); 192 | CU_basic_run_tests(); 193 | printf("\n"); 194 | CU_basic_show_failures(CU_get_failure_list()); 195 | printf("\n\n"); 196 | rv = CU_get_number_of_tests_failed(); 197 | } 198 | 199 | CU_cleanup_registry(); 200 | } 201 | 202 | if (0 != rv) { 203 | return 1; 204 | } 205 | return 0; 206 | } 207 | --------------------------------------------------------------------------------