├── .gitignore ├── .gitmodules ├── .travis.yml ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── cmake └── modules │ └── CodeCoverage.cmake ├── include ├── export │ └── jwtpp │ │ └── jwtpp.hh └── local │ └── jwtpp │ └── statics.hh ├── pkgconfig.pc.in ├── src ├── b64.cpp ├── claims.cpp ├── crypto.cpp ├── digest.cpp ├── ecdsa.cpp ├── eddsa.cpp ├── header.cpp ├── hmac.cpp ├── jwtpp.cpp ├── pss.cpp ├── rsa.cpp ├── statics.cpp └── tools.cpp └── tests ├── b64.cpp ├── claims.cpp ├── crypto.cpp ├── digest.cpp ├── ecdsa.cpp ├── eddsa.cpp ├── expire.cpp ├── header.cpp ├── hmac.cpp ├── pss.cpp ├── rsa.cpp └── rsa.pem /.gitignore: -------------------------------------------------------------------------------- 1 | build* 2 | cmake-build* 3 | .idea 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "gtest"] 2 | path = gtest 3 | url = https://github.com/google/googletest.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: bionic 3 | 4 | language: cpp 5 | 6 | matrix: 7 | include: 8 | - os: linux 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | packages: 14 | - g++-9 15 | - lcov 16 | - libssl-dev 17 | env: 18 | - MATRIX_EVAL="CC=gcc-9 && CXX=g++-9" 19 | - CMAKE_CXX_STANDARD=11 20 | - os: linux 21 | addons: 22 | apt: 23 | sources: 24 | - ubuntu-toolchain-r-test 25 | packages: 26 | - g++-9 27 | - lcov 28 | - libssl-dev 29 | env: 30 | - MATRIX_EVAL="CC=gcc-9 && CXX=g++-9" 31 | - CMAKE_CXX_STANDARD=14 32 | - os: linux 33 | addons: 34 | apt: 35 | sources: 36 | - ubuntu-toolchain-r-test 37 | packages: 38 | - g++-9 39 | - lcov 40 | - libssl-dev 41 | env: 42 | - MATRIX_EVAL="CC=gcc-9 && CXX=g++-9" 43 | - CMAKE_CXX_STANDARD=17 44 | 45 | - os: linux 46 | addons: 47 | apt: 48 | sources: 49 | - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main' 50 | key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' 51 | - ubuntu-toolchain-r-test 52 | packages: 53 | - llvm-dev 54 | - libclang-dev 55 | - clang 56 | - lcov 57 | - libssl-dev 58 | env: 59 | - MATRIX_EVAL="CC=clang && CXX=clang++" 60 | - CMAKE_CXX_STANDARD=11 61 | - os: linux 62 | addons: 63 | apt: 64 | sources: 65 | - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main' 66 | key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' 67 | - ubuntu-toolchain-r-test 68 | packages: 69 | - llvm-dev 70 | - libclang-dev 71 | - clang 72 | - lcov 73 | - libssl-dev 74 | env: 75 | - MATRIX_EVAL="CC=clang && CXX=clang++" 76 | - CMAKE_CXX_STANDARD=14 77 | - os: linux 78 | addons: 79 | apt: 80 | sources: 81 | - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main' 82 | key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' 83 | - ubuntu-toolchain-r-test 84 | packages: 85 | - llvm-dev 86 | - libclang-dev 87 | - clang 88 | - lcov 89 | - libssl-dev 90 | env: 91 | - MATRIX_EVAL="CC=clang && CXX=clang++" 92 | - CMAKE_CXX_STANDARD=17 93 | 94 | - os: osx 95 | osx_image: xcode12.2 96 | env: 97 | - CMAKE_CXX_STANDARD=11 98 | - os: osx 99 | osx_image: xcode12.2 100 | env: 101 | - CMAKE_CXX_STANDARD=14 102 | - os: osx 103 | osx_image: xcode12.2 104 | env: 105 | - CMAKE_CXX_STANDARD=17 106 | 107 | git: 108 | depth: 1 109 | 110 | before_install: 111 | - eval "${MATRIX_EVAL}" 112 | # Dependencies required by the CI are installed in ${TRAVIS_BUILD_DIR}/deps/ 113 | - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" 114 | - mkdir -p "${DEPS_DIR}" 115 | - cd "${DEPS_DIR}" 116 | ############################################################################ 117 | # Install a recent CMake (unless already installed on OS X) 118 | ############################################################################ 119 | - CMAKE_VERSION=3.15.4 120 | - | 121 | if [ ${TRAVIS_OS_NAME} == linux ]; then 122 | CMAKE_URL="https://cmake.org/files/v${CMAKE_VERSION%.[0-9]}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz" 123 | mkdir cmake && travis_retry wget --no-check-certificate -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake 124 | export PATH=${DEPS_DIR}/cmake/bin:${PATH} 125 | sudo apt-get update 126 | git clone https://github.com/open-source-parsers/jsoncpp.git ~/jsoncpp 127 | export BLD_PATH=`pwd`; cd ~/jsoncpp; mkdir build && cd build 128 | cmake -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release .. 129 | make && sudo make install && cd $BLD_PATH 130 | else 131 | brew update 132 | brew install openssl --force 133 | brew install jsoncpp lcov 134 | brew install cmake || brew upgrade cmake 135 | fi 136 | before_script: 137 | - cd ${TRAVIS_BUILD_DIR} 138 | - git submodule update --init --recursive 139 | - mkdir build-debug && cd build-debug 140 | - | 141 | if [ $TRAVIS_OS_NAME == osx ]; then 142 | cmake -Wno-dev -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DCMAKE_BUILD_TYPE=Debug -DJWTPP_WITH_COVERAGE=ON -DJWTPP_WITH_TESTS=ON -DJWTPP_WITH_SHARED_LIBS=ON -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) -DCMAKE_INSTALL_PREFIX=/usr/local .. 143 | else 144 | cmake -Wno-dev -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DCMAKE_BUILD_TYPE=Debug -DJWTPP_WITH_COVERAGE=ON -DJWTPP_WITH_TESTS=ON -DJWTPP_WITH_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr/local .. 145 | fi 146 | - cd .. && mkdir build-release && cd build-release 147 | - | 148 | if [ $TRAVIS_OS_NAME == osx ]; then 149 | cmake -Wno-dev -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DCMAKE_BUILD_TYPE=Release -DJWTPP_WITH_TESTS=ON -DJWTPP_WITH_SHARED_LIBS=ON -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) -DCMAKE_INSTALL_PREFIX=/usr/local .. 150 | else 151 | cmake -Wno-dev -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DCMAKE_BUILD_TYPE=Release -DJWTPP_WITH_TESTS=ON -DJWTPP_WITH_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr/local .. 152 | fi 153 | script: 154 | - make 155 | - mkdir -p tests 156 | - ./jwtpp_test 157 | - sudo make install 158 | - cd ../build-debug 159 | - make 160 | - mkdir -p tests 161 | - ./jwtpp_test 162 | after_success: 163 | # Create lcov report 164 | - lcov --capture --directory . --output-file coverage.info 165 | - lcov --remove coverage.info '/usr/*' --output-file coverage.info # filter system-files 166 | - lcov --list coverage.info # debug info 167 | # Uploading report to CodeCov 168 | - bash <(curl -s https://codecov.io/bash) -f coverage.info || echo "Codecov did not collect coverage reports" 169 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | 3 | project(jwtpp LANGUAGES C CXX) 4 | 5 | set(VERSION 0.1.0) 6 | 7 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules") 8 | 9 | option(JWTPP_WITH_TESTS "Build tests" OFF) 10 | option(JWTPP_WITH_COVERAGE "Enable coverage tests" OFF) 11 | option(JWTPP_WITH_INSTALL "Allow root targets to not issue install" ON) 12 | option(JWTPP_WITH_SHARED_LIBS "Build shared library" OFF) 13 | 14 | if(JWTPP_WITH_TESTS AND (CMAKE_BUILD_TYPE STREQUAL "Debug")) 15 | include(CodeCoverage) 16 | endif () 17 | 18 | include(CheckCSourceCompiles) 19 | include(CheckCCompilerFlag) 20 | include(CheckCXXSourceCompiles) 21 | include(CheckCXXSymbolExists) 22 | include(CheckCXXCompilerFlag) 23 | include(CheckFunctionExists) 24 | include(CheckTypeSize) 25 | include(CheckIncludeFiles) 26 | include(CheckIncludeFileCXX) 27 | 28 | set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") 29 | set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") 30 | set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") 31 | 32 | find_package(OpenSSL REQUIRED) 33 | 34 | if (NOT WIN32 AND NOT JsonCPP_FOUND) 35 | find_package(PkgConfig REQUIRED) 36 | pkg_check_modules(JsonCPP REQUIRED jsoncpp) 37 | endif () 38 | 39 | include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR}) 40 | include_directories(SYSTEM ${JsonCPP_INCLUDE_DIRS}) 41 | link_directories(${JsonCPP_LIBRARY_DIRS}) 42 | 43 | check_include_file_cxx(memory HAVE_MEMORY) 44 | check_include_file_cxx(functional HAVE_FUNCTIONAL) 45 | check_include_file_cxx(string HAVE_STRING) 46 | check_include_file_cxx(vector HAVE_VECTOR) 47 | check_include_file_cxx(mutex HAVE_MUTEX) 48 | check_include_file_cxx(exception HAVE_EXCEPTION) 49 | check_include_file_cxx(stdexcept HAVE_STDEXCEPT) 50 | 51 | if (NOT CMAKE_CXX_STANDARD) 52 | set(CMAKE_CXX_STANDARD 11) 53 | endif() 54 | 55 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 56 | 57 | if (NOT MSVC) 58 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated") 59 | endif () 60 | 61 | 62 | set(LIB_SOURCES 63 | src/b64.cpp 64 | src/claims.cpp 65 | src/crypto.cpp 66 | src/digest.cpp 67 | src/ecdsa.cpp 68 | src/eddsa.cpp 69 | src/header.cpp 70 | src/hmac.cpp 71 | src/jwtpp.cpp 72 | src/pss.cpp 73 | src/rsa.cpp 74 | src/statics.cpp 75 | src/tools.cpp 76 | 77 | include/export/jwtpp/jwtpp.hh 78 | include/local/jwtpp/statics.hh 79 | ) 80 | 81 | add_library( 82 | ${PROJECT_NAME}-static 83 | STATIC ${LIB_SOURCES} 84 | ) 85 | 86 | set_target_properties(${PROJECT_NAME}-static PROPERTIES OUTPUT_NAME ${PROJECT_NAME} CLEAN_DIRECT_OUTPUT 1) 87 | 88 | target_include_directories( 89 | ${PROJECT_NAME}-static 90 | PUBLIC 91 | include/export 92 | ${JsonCPP_INCLUDE_DIRS} 93 | PRIVATE 94 | include/local 95 | ) 96 | 97 | target_link_libraries( 98 | ${PROJECT_NAME}-static 99 | ${OPENSSL_LIBRARIES} 100 | ${JsonCPP_LIBRARIES} 101 | ) 102 | 103 | if (JWTPP_WITH_INSTALL) 104 | install( 105 | TARGETS 106 | ${PROJECT_NAME}-static 107 | ARCHIVE 108 | DESTINATION 109 | lib 110 | ) 111 | endif () 112 | 113 | if (JWTPP_WITH_SHARED_LIBS) 114 | add_library(${PROJECT_NAME}-shared SHARED ${LIB_SOURCES}) 115 | 116 | set_target_properties(${PROJECT_NAME}-shared PROPERTIES POSITION_INDEPENDENT_CODE TRUE) 117 | set_target_properties(${PROJECT_NAME}-shared PROPERTIES OUTPUT_NAME ${PROJECT_NAME} CLEAN_DIRECT_OUTPUT 1) 118 | target_include_directories( 119 | ${PROJECT_NAME}-shared 120 | PUBLIC 121 | include/export 122 | ${JsonCPP_INCLUDE_DIRS} 123 | PRIVATE 124 | include/local 125 | ) 126 | 127 | target_link_libraries( 128 | ${PROJECT_NAME}-shared 129 | PUBLIC 130 | ${OPENSSL_LIBRARIES} 131 | ${JsonCPP_LIBRARIES} 132 | ) 133 | 134 | if (WITH_INSTALL) 135 | install( 136 | TARGETS 137 | ${PROJECT_NAME}-shared 138 | LIBRARY 139 | DESTINATION 140 | lib 141 | ) 142 | endif () 143 | endif () 144 | 145 | if (JWTPP_WITH_INSTALL) 146 | install( 147 | DIRECTORY 148 | include/export/jwtpp 149 | DESTINATION include 150 | FILES_MATCHING PATTERN "*.hh" 151 | ) 152 | endif () 153 | 154 | set(JWTPP_PC ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc) 155 | 156 | if (JWTPP_WITH_INSTALL) 157 | configure_file( 158 | pkgconfig.pc.in 159 | ${JWTPP_PC} 160 | @ONLY 161 | ) 162 | 163 | install(FILES ${JWTPP_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") 164 | endif () 165 | 166 | if (JWTPP_WITH_TESTS) 167 | enable_testing() 168 | add_subdirectory(gtest EXCLUDE_FROM_ALL) 169 | 170 | include_directories(${PROJECT_SOURCE_DIR}/gtest/googletest/include) 171 | 172 | add_executable(jwtpp_test 173 | tests/b64.cpp 174 | tests/claims.cpp 175 | tests/crypto.cpp 176 | tests/digest.cpp 177 | tests/ecdsa.cpp 178 | tests/eddsa.cpp 179 | tests/header.cpp 180 | tests/hmac.cpp 181 | tests/pss.cpp 182 | tests/rsa.cpp 183 | tests/expire.cpp 184 | ) 185 | 186 | if (WIN32) 187 | set(WIN32_DEP_LIBS crypt32.lib ws2_32.lib) 188 | endif (WIN32) 189 | 190 | target_link_libraries( 191 | jwtpp_test 192 | gtest_main 193 | ${PROJECT_NAME}-static 194 | ${WIN32_DEP_LIBS} 195 | ) 196 | 197 | add_test(UnitTests jwtpp_test) 198 | 199 | target_compile_definitions( 200 | jwtpp_test 201 | PRIVATE 202 | -DTEST_RSA_KEY_PATH=\"${CMAKE_SOURCE_DIR}/tests/rsa.pem\" 203 | ) 204 | 205 | if (JWTPP_WITH_COVERAGE) 206 | if (CMAKE_BUILD_TYPE STREQUAL "Debug") 207 | append_coverage_compiler_flags() 208 | 209 | setup_target_for_coverage_lcov( 210 | NAME coverage 211 | EXECUTABLE jwtpp_test 212 | ) 213 | endif () 214 | endif () 215 | endif () 216 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at troian.ap@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2020 Artur Troian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jwtpp 2 | JSON Object Signing and Encryption library for C++ 3 | 4 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/da9665fd01ba4c759cef755d1ff03d2c)](https://www.codacy.com/app/troian/jwtpp?utm_source=github.com&utm_medium=referral&utm_content=troian/jwtpp&utm_campaign=badger) 5 | [![Build Status](https://travis-ci.com/troian/jwtpp.svg?branch=master)](https://travis-ci.com/troian/jwtpp) 6 | [![Codecov](https://codecov.io/gh/troian/jwtpp/branch/master/graph/badge.svg)](https://codecov.io/gh/troian/jwtpp) 7 | 8 | 9 | #### Dependencies: 10 | - [jsoncpp](https://github.com/open-source-parsers/jsoncpp) 11 | - OpenSSL 12 | 13 | #### Built and tested with: 14 | - GCC 15 | - C++11 16 | - С++14 17 | - С++17 18 | - СLang 19 | - C++11 20 | - С++14 21 | - С++17 22 | 23 | #### Supported features: 24 | - Sign 25 | - Verify 26 | 27 | #### Supported algorithms 28 | |Alg|Status| 29 | |:---:|:------:| 30 | | HS256 | **Supported** | 31 | | HS384 | **Supported** | 32 | | HS512 | **Supported** | 33 | | RS256 | **Supported** | 34 | | RS384 | **Supported** | 35 | | RS512 | **Supported** | 36 | | ES256 | **Supported** | 37 | | ES384 | **Supported** | 38 | | ES512 | **Supported** | 39 | | PS256 | **Supported** | 40 | | PS384 | **Supported** | 41 | | PS512 | **Supported** | 42 | | EdDSA | **Supported** | 43 | 44 | #### Claims 45 | |Claim|Options|Status| 46 | |:---:|:---:|:----:| 47 | |**_ess_**|set,verify| **Supported** 48 | |**_sub_**|set,verify| **Supported** 49 | |**_aud_**|set,verify| **Supported** 50 | |**_exp_**|set,verify| **Supported** 51 | |**_nbf_**|set,verify| **Supported** 52 | |**_iat_**|set,verify| **Supported** 53 | |**_jti_**|set,verify| **Supported** 54 | 55 | ### How to use 56 | Refer to tests dir 57 | 58 | ### How to build/install 59 | #### CMake sources deps 60 | add_subdirectory() 61 | #### System-wide installation 62 | On MacOS OPENSSL_ROOT_DIR might need to be specified. Add `-DOPENSSL_ROOT_DIR=$(brew --prefix openssl)` to cmake stage 63 | 64 | ```bash 65 | git clone https://github.com/troian/jwtpp 66 | mkdir build && cd build 67 | cmake -Wno-dev -DCMAKE_INSTALL_PREFIX= .. 68 | make install 69 | ``` 70 | #### Homebrew 71 | ``` 72 | brew tap troian/tap 73 | brew install jwtpp 74 | ``` 75 | 76 | ### TODO 77 | - Documentation 78 | - Examples 79 | - Tests 80 | 81 | ## How to contribute 82 | Just do it! :) 83 | -------------------------------------------------------------------------------- /cmake/modules/CodeCoverage.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012 - 2017, Lars Bilke 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | # 29 | # CHANGES: 30 | # 31 | # 2012-01-31, Lars Bilke 32 | # - Enable Code Coverage 33 | # 34 | # 2013-09-17, Joakim Söderberg 35 | # - Added support for Clang. 36 | # - Some additional usage instructions. 37 | # 38 | # 2016-02-03, Lars Bilke 39 | # - Refactored functions to use named parameters 40 | # 41 | # 2017-06-02, Lars Bilke 42 | # - Merged with modified version from github.com/ufz/ogs 43 | # 44 | # 45 | # USAGE: 46 | # 47 | # 1. Copy this file into your cmake modules path. 48 | # 49 | # 2. Add the following line to your CMakeLists.txt: 50 | # include(CodeCoverage) 51 | # 52 | # 3. Append necessary compiler flags: 53 | # APPEND_COVERAGE_COMPILER_FLAGS() 54 | # 55 | # 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og 56 | # 57 | # 4. If you need to exclude additional directories from the report, specify them 58 | # using the COVERAGE_LCOV_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE_LCOV. 59 | # Example: 60 | # set(COVERAGE_LCOV_EXCLUDES 'dir1/*' 'dir2/*') 61 | # 62 | # 5. Use the functions described below to create a custom make target which 63 | # runs your test executable and produces a code coverage report. 64 | # 65 | # 6. Build a Debug build: 66 | # cmake -DCMAKE_BUILD_TYPE=Debug .. 67 | # make 68 | # make my_coverage_target 69 | # 70 | 71 | include(CMakeParseArguments) 72 | 73 | # Check prereqs 74 | find_program( GCOV_PATH gcov ) 75 | find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) 76 | find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) 77 | find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) 78 | find_package(Python COMPONENTS Interpreter) 79 | 80 | if(NOT GCOV_PATH) 81 | message(FATAL_ERROR "gcov not found! Aborting...") 82 | endif() # NOT GCOV_PATH 83 | 84 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") 85 | if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) 86 | message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") 87 | endif() 88 | elseif(NOT CMAKE_COMPILER_IS_GNUCXX) 89 | message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") 90 | endif() 91 | 92 | set(COVERAGE_COMPILER_FLAGS "-g --coverage -fprofile-arcs -ftest-coverage" 93 | CACHE INTERNAL "") 94 | 95 | set(CMAKE_CXX_FLAGS_COVERAGE 96 | ${COVERAGE_COMPILER_FLAGS} 97 | CACHE STRING "Flags used by the C++ compiler during coverage builds." 98 | FORCE ) 99 | set(CMAKE_C_FLAGS_COVERAGE 100 | ${COVERAGE_COMPILER_FLAGS} 101 | CACHE STRING "Flags used by the C compiler during coverage builds." 102 | FORCE ) 103 | set(CMAKE_EXE_LINKER_FLAGS_COVERAGE 104 | "" 105 | CACHE STRING "Flags used for linking binaries during coverage builds." 106 | FORCE ) 107 | set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE 108 | "" 109 | CACHE STRING "Flags used by the shared libraries linker during coverage builds." 110 | FORCE ) 111 | mark_as_advanced( 112 | CMAKE_CXX_FLAGS_COVERAGE 113 | CMAKE_C_FLAGS_COVERAGE 114 | CMAKE_EXE_LINKER_FLAGS_COVERAGE 115 | CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) 116 | 117 | if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") 118 | message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") 119 | endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" 120 | 121 | if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 122 | link_libraries(gcov) 123 | else() 124 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") 125 | endif() 126 | 127 | # Defines a target for running and collection code coverage information 128 | # Builds dependencies, runs the given executable and outputs reports. 129 | # NOTE! The executable should always have a ZERO as exit code otherwise 130 | # the coverage generation will not complete. 131 | # 132 | # SETUP_TARGET_FOR_COVERAGE_LCOV( 133 | # NAME testrunner_coverage # New target name 134 | # EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 135 | # DEPENDENCIES testrunner # Dependencies to build first 136 | # ) 137 | function(SETUP_TARGET_FOR_COVERAGE_LCOV) 138 | 139 | set(options NONE) 140 | set(oneValueArgs NAME) 141 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) 142 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 143 | 144 | if(NOT LCOV_PATH) 145 | message(FATAL_ERROR "lcov not found! Aborting...") 146 | endif() # NOT LCOV_PATH 147 | 148 | if(NOT GENHTML_PATH) 149 | message(FATAL_ERROR "genhtml not found! Aborting...") 150 | endif() # NOT GENHTML_PATH 151 | 152 | # Setup target 153 | add_custom_target(${Coverage_NAME} 154 | 155 | # Cleanup lcov 156 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . --zerocounters 157 | # Create baseline to make sure untouched files show up in the report 158 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base 159 | 160 | # Run tests 161 | COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 162 | 163 | # Capturing lcov counters and generating report 164 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info 165 | # add baseline counters 166 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total 167 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 168 | COMMAND ${GENHTML_PATH} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 169 | COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 170 | 171 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 172 | DEPENDS ${Coverage_DEPENDENCIES} 173 | COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." 174 | ) 175 | 176 | # Show where to find the lcov info report 177 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 178 | COMMAND ; 179 | COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info." 180 | ) 181 | 182 | # Show info where to find the report 183 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 184 | COMMAND ; 185 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." 186 | ) 187 | 188 | endfunction() # SETUP_TARGET_FOR_COVERAGE_LCOV 189 | 190 | # Defines a target for running and collection code coverage information 191 | # Builds dependencies, runs the given executable and outputs reports. 192 | # NOTE! The executable should always have a ZERO as exit code otherwise 193 | # the coverage generation will not complete. 194 | # 195 | # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML( 196 | # NAME ctest_coverage # New target name 197 | # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 198 | # DEPENDENCIES executable_target # Dependencies to build first 199 | # ) 200 | function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML) 201 | 202 | set(options NONE) 203 | set(oneValueArgs NAME) 204 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) 205 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 206 | 207 | if(NOT Python_FOUND) 208 | message(FATAL_ERROR "python not found! Aborting...") 209 | endif() 210 | 211 | if(NOT GCOVR_PATH) 212 | message(FATAL_ERROR "gcovr not found! Aborting...") 213 | endif() # NOT GCOVR_PATH 214 | 215 | # Combine excludes to several -e arguments 216 | set(GCOVR_EXCLUDES "") 217 | foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) 218 | string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE}) 219 | list(APPEND GCOVR_EXCLUDES "-e") 220 | list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}") 221 | endforeach() 222 | 223 | add_custom_target(${Coverage_NAME} 224 | # Run tests 225 | ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 226 | 227 | # Running gcovr 228 | COMMAND ${GCOVR_PATH} --xml 229 | -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} 230 | --object-directory=${PROJECT_BINARY_DIR} 231 | -o ${Coverage_NAME}.xml 232 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 233 | DEPENDS ${Coverage_DEPENDENCIES} 234 | COMMENT "Running gcovr to produce Cobertura code coverage report." 235 | ) 236 | 237 | # Show info where to find the report 238 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 239 | COMMAND ; 240 | COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." 241 | ) 242 | 243 | endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML 244 | 245 | # Defines a target for running and collection code coverage information 246 | # Builds dependencies, runs the given executable and outputs reports. 247 | # NOTE! The executable should always have a ZERO as exit code otherwise 248 | # the coverage generation will not complete. 249 | # 250 | # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML( 251 | # NAME ctest_coverage # New target name 252 | # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 253 | # DEPENDENCIES executable_target # Dependencies to build first 254 | # ) 255 | function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) 256 | 257 | set(options NONE) 258 | set(oneValueArgs NAME) 259 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) 260 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 261 | 262 | if(NOT Python_FOUND) 263 | message(FATAL_ERROR "python not found! Aborting...") 264 | endif() 265 | 266 | if(NOT GCOVR_PATH) 267 | message(FATAL_ERROR "gcovr not found! Aborting...") 268 | endif() # NOT GCOVR_PATH 269 | 270 | # Combine excludes to several -e arguments 271 | set(GCOVR_EXCLUDES "") 272 | foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) 273 | string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE}) 274 | list(APPEND GCOVR_EXCLUDES "-e") 275 | list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}") 276 | endforeach() 277 | 278 | add_custom_target(${Coverage_NAME} 279 | # Run tests 280 | ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 281 | 282 | # Create folder 283 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME} 284 | 285 | # Running gcovr 286 | COMMAND ${Python_EXECUTABLE} ${GCOVR_PATH} --html --html-details 287 | -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} 288 | --object-directory=${PROJECT_BINARY_DIR} 289 | -o ${Coverage_NAME}/index.html 290 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 291 | DEPENDS ${Coverage_DEPENDENCIES} 292 | COMMENT "Running gcovr to produce HTML code coverage report." 293 | ) 294 | 295 | # Show info where to find the report 296 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 297 | COMMAND ; 298 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." 299 | ) 300 | 301 | endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML 302 | 303 | function(APPEND_COVERAGE_COMPILER_FLAGS) 304 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) 305 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) 306 | message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") 307 | endfunction() # APPEND_COVERAGE_COMPILER_FLAGS 308 | -------------------------------------------------------------------------------- /include/export/jwtpp/jwtpp.hh: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #if __cplusplus >= 201703L 44 | # define __NODISCARD [[nodiscard]] 45 | #else 46 | # define __NODISCARD 47 | #endif 48 | 49 | #if OPENSSL_VERSION_NUMBER >= 0x10101000L 50 | # define JWTPP_SUPPORTED_EDDSA 51 | #endif 52 | 53 | namespace jwtpp { 54 | 55 | class claims; 56 | class crypto; 57 | class hmac; 58 | class rsa; 59 | class ecdsa; 60 | 61 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 62 | enum alg_t { 63 | #else 64 | enum class alg_t { 65 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 66 | NONE = 0, 67 | HS256, 68 | HS384, 69 | HS512, 70 | RS256, 71 | RS384, 72 | RS512, 73 | ES256, 74 | ES384, 75 | ES512, 76 | PS256, 77 | PS384, 78 | PS512, 79 | #if defined(JWTPP_SUPPORTED_EDDSA) 80 | EdDSA, 81 | #endif // defined(JWTPP_SUPPORTED_EDDSA) 82 | UNKNOWN 83 | }; 84 | 85 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 86 | # define final 87 | 88 | typedef std::shared_ptr sp_claims; 89 | typedef std::unique_ptr up_claims; 90 | typedef std::shared_ptr sp_crypto; 91 | typedef std::shared_ptr sp_hmac; 92 | typedef std::shared_ptr sp_rsa; 93 | typedef std::shared_ptr sp_ecdsa; 94 | typedef std::shared_ptr sp_rsa_key; 95 | typedef std::shared_ptr sp_ecdsa_key; 96 | typedef std::shared_ptr sp_evp_key; 97 | 98 | typedef std::shared_ptr sp_evp_md_ctx; 99 | typedef std::shared_ptr sp_evp_pkey_ctx; 100 | 101 | typedef std::unique_ptr up_file; 102 | #else 103 | using sp_claims = typename std::shared_ptr; 104 | using up_claims = typename std::unique_ptr; 105 | using sp_crypto = typename std::shared_ptr; 106 | using sp_hmac = typename std::shared_ptr; 107 | using sp_rsa = typename std::shared_ptr; 108 | using sp_ecdsa = typename std::shared_ptr; 109 | using sp_rsa_key = typename std::shared_ptr; 110 | using sp_ecdsa_key = typename std::shared_ptr; 111 | using sp_evp_key = typename std::shared_ptr; 112 | 113 | using sp_evp_md_ctx = typename std::shared_ptr; 114 | using sp_evp_pkey_ctx = typename std::shared_ptr; 115 | 116 | using up_file = typename std::unique_ptr; 117 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 118 | 119 | template 120 | class secure_allocator : public std::allocator { 121 | public: 122 | template 123 | struct rebind { 124 | typedef secure_allocator other; 125 | }; 126 | 127 | secure_allocator() noexcept = default; 128 | 129 | secure_allocator(const secure_allocator &) noexcept 130 | : std::allocator() 131 | {} 132 | 133 | template 134 | explicit secure_allocator(const secure_allocator &) noexcept {} 135 | 136 | void deallocate(T *p, std::size_t n) noexcept { 137 | OPENSSL_cleanse(p, n); 138 | std::allocator::deallocate(p, n); 139 | } 140 | }; 141 | 142 | using secure_string = std::basic_string, secure_allocator>; 143 | 144 | class b64 final { 145 | private: 146 | static const std::string base64_chars; 147 | 148 | static inline bool is_base64(unsigned char c) { 149 | return (isalnum(c) || (c == '+') || (c == '/')); 150 | } 151 | 152 | static void uri_enc(char *buf, size_t len); 153 | 154 | static void uri_dec(char *buf, size_t len); 155 | 156 | public: 157 | /** 158 | * \brief 159 | * 160 | * \param[out] b64: output data in base64 161 | * \param[in] 162 | * 163 | * \return None 164 | */ 165 | static std::string encode(const uint8_t *stream, size_t in_len); 166 | static std::string encode(const std::vector &stream); 167 | static std::string encode(const std::vector *stream); 168 | static std::string encode(const std::string &stream); 169 | 170 | static std::string encode_uri(const uint8_t * stream, size_t in_len); 171 | static std::string encode_uri(const std::string &stream); 172 | static std::string encode_uri(const std::vector &stream); 173 | static std::string encode_uri(const std::vector * stream); 174 | 175 | static std::vector decode(const char *in, size_t in_size); 176 | static std::vector decode_uri(const char *in, size_t in_size); 177 | static std::string decode(const std::string &in); 178 | static std::string decode_uri(const std::string &in); 179 | }; 180 | 181 | /** 182 | * \brief 183 | */ 184 | class digest final { 185 | public: 186 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 187 | enum type { 188 | #else 189 | enum class type { 190 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 191 | SHA256, 192 | SHA384, 193 | SHA512 194 | }; 195 | 196 | public: 197 | digest(digest::type type, const uint8_t *in_data, size_t in_size); 198 | ~digest(); 199 | 200 | __NODISCARD 201 | size_t size() const; 202 | 203 | uint8_t *data(); 204 | 205 | __NODISCARD 206 | std::string to_string() const; 207 | 208 | public: 209 | static const EVP_MD *md(digest::type t) { 210 | switch (t) { 211 | default: 212 | [[fallthrough]]; 213 | case type::SHA256: 214 | return EVP_sha256(); 215 | case type::SHA384: 216 | return EVP_sha384(); 217 | case type::SHA512: 218 | return EVP_sha512(); 219 | } 220 | } 221 | 222 | private: 223 | size_t _size; 224 | std::shared_ptr _data; 225 | }; 226 | 227 | /** 228 | * \brief 229 | * 230 | * TODO https://github.com/troian/jwtpp/issues/38 231 | */ 232 | class claims final { 233 | private: 234 | class has { 235 | public: 236 | explicit has(Json::Value *c) : _claims(c) {} 237 | public: 238 | bool any(const std::string &key) { return _claims->isMember(key); } 239 | bool iss() { return any("iss"); } 240 | bool sub() { return any("sub"); } 241 | bool aud() { return any("aud"); } 242 | bool exp() { return any("exp"); } 243 | bool nbf() { return any("nbf"); } 244 | bool iat() { return any("iat"); } 245 | bool jti() { return any("jti"); } 246 | private: 247 | Json::Value *_claims; 248 | }; 249 | 250 | class check { 251 | public: 252 | explicit check(Json::Value *c) : _claims(c) {} 253 | public: 254 | bool any(const std::string &key, const std::string &value) { 255 | std::string s = _claims->operator[](key).asString(); 256 | return s == value; 257 | } 258 | 259 | bool any(const std::string &key, Json::UInt value) { return _claims->operator[](key).asUInt() == value; } 260 | bool any(const std::string &key, Json::Int value) { return _claims->operator[](key).asInt() == value; } 261 | bool any(const std::string &key, Json::UInt64 value) { return _claims->operator[](key).asUInt64() == value; } 262 | bool any(const std::string &key, Json::Int64 value) { return _claims->operator[](key).asInt64() == value; } 263 | bool any(const std::string &key, double value) { return _claims->operator[](key).asDouble() == value; } 264 | 265 | bool iss(const std::string &value) { return any("iss", value); } 266 | bool sub(const std::string &value) { return any("sub", value); } 267 | bool aud(const std::string &value) { return any("aud", value); } 268 | bool exp(const std::string &value) { return any("exp", value); } 269 | bool nbf(const std::string &value) { return any("nbf", value); } 270 | bool iat(const std::string &value) { return any("iat", value); } 271 | bool jti(const std::string &value) { return any("jti", value); } 272 | private: 273 | Json::Value *_claims; 274 | }; 275 | 276 | class del { 277 | public: 278 | explicit del(Json::Value *c) : _claims(c) {} 279 | public: 280 | void any(const std::string &key) { _claims->removeMember(key); } 281 | void iss() { any("iss"); } 282 | void sub() { any("sub"); } 283 | void aud() { any("aud"); } 284 | void exp() { any("exp"); } 285 | void nbf() { any("nbf"); } 286 | void iat() { any("nbf"); } 287 | void jti() { any("jti"); } 288 | private: 289 | Json::Value *_claims; 290 | }; 291 | 292 | 293 | class get { 294 | public: 295 | explicit get(Json::Value *c) : _claims(c) {} 296 | public: 297 | std::string any(const std::string &key) { 298 | return _claims->operator[](key).asString(); 299 | } 300 | 301 | Json::Int anyInt(const std::string &key) { 302 | return _claims->operator[](key).asInt(); 303 | } 304 | 305 | Json::UInt anyUInt(const std::string &key) { 306 | return _claims->operator[](key).asUInt(); 307 | } 308 | 309 | Json::Int64 anyInt64(const std::string &key) { 310 | return _claims->operator[](key).asInt64(); 311 | } 312 | 313 | Json::UInt64 anyUInt64(const std::string &key) { 314 | return _claims->operator[](key).asUInt64(); 315 | } 316 | 317 | bool anyBool(const std::string &key) { 318 | return _claims->operator[](key).asBool(); 319 | } 320 | 321 | double anyDouble(const std::string &key) { 322 | return _claims->operator[](key).asDouble(); 323 | } 324 | 325 | std::string iss() { return any("iss"); } 326 | std::string sub() { return any("sub"); } 327 | std::string aud() { return any("aud"); } 328 | std::string exp() { return any("exp"); } 329 | std::string nbf() { return any("nbf"); } 330 | std::string iat() { return any("iat"); } 331 | std::string jti() { return any("jti"); } 332 | private: 333 | Json::Value *_claims; 334 | }; 335 | 336 | class set { 337 | public: 338 | explicit set(Json::Value *c) : _claims(c) {} 339 | public: 340 | void any(const std::string &key, Json::UInt value) { _claims->operator[](key) = value; } 341 | void any(const std::string &key, Json::Int value) { _claims->operator[](key) = value; } 342 | void any(const std::string &key, Json::UInt64 value) { _claims->operator[](key) = value; } 343 | void any(const std::string &key, Json::Int64 value) { _claims->operator[](key) = value; } 344 | void any(const std::string &key, double value) { _claims->operator[](key) = value; } 345 | void any(const std::string &key, const std::string &value); 346 | 347 | void iss(const std::string &value) { any("iss", value); } 348 | void sub(const std::string &value) { any("sub", value); } 349 | void aud(const std::string &value) { any("aud", value); } 350 | void exp(const std::string &value) { any("exp", value); } 351 | void nbf(const std::string &value) { any("nbf", value); } 352 | void iat(const std::string &value) { any("iat", value); } 353 | void jti(const std::string &value) { any("jti", value); } 354 | 355 | private: 356 | Json::Value *_claims; 357 | }; 358 | public: 359 | /** 360 | * \brief 361 | */ 362 | claims(); 363 | 364 | /** 365 | * \brief 366 | * 367 | * \param d 368 | */ 369 | explicit claims(const std::string &d, bool b64 = false); 370 | 371 | /** 372 | * \brief 373 | * 374 | * \param key 375 | * \param value 376 | * 377 | * \return 378 | */ 379 | class claims::set &set() { return _set; } 380 | 381 | /** 382 | * \brief 383 | * 384 | * \param key 385 | * 386 | * \return 387 | */ 388 | class claims::has &has() { return _has; } 389 | 390 | /** 391 | * \brief 392 | * 393 | * \param key 394 | * 395 | * \return 396 | */ 397 | class claims::del &del() { return _del; } 398 | 399 | /** 400 | * \brief 401 | * 402 | * \param key 403 | * 404 | * \return 405 | */ 406 | class claims::get &get() { return _get; } 407 | 408 | class claims::check &check() { return _check; } 409 | 410 | std::string b64(); 411 | 412 | #if !(defined(_MSC_VER) && (_MSC_VER < 1700)) 413 | public: 414 | template 415 | static sp_claims make_shared(_Args&&... __args) { 416 | return std::make_shared(__args...); 417 | } 418 | #endif // !(defined(_MSC_VER) && (_MSC_VER < 1700)) 419 | 420 | private: 421 | Json::Value _claims; 422 | 423 | class set _set; 424 | class get _get; 425 | class has _has; 426 | class del _del; 427 | class check _check; 428 | }; 429 | 430 | class hdr final { 431 | public: 432 | explicit hdr(jwtpp::alg_t alg); 433 | 434 | explicit hdr(const std::string &data); 435 | 436 | std::string b64(); 437 | 438 | private: 439 | Json::Value _h; 440 | }; 441 | 442 | /** 443 | * \brief 444 | */ 445 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 446 | typedef std::shared_ptr sp_jws; 447 | #else 448 | using sp_jws = typename std::shared_ptr; 449 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 450 | 451 | class jws final { 452 | public: 453 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 454 | typedef std::function verify_cb; 455 | #else 456 | using verify_cb = typename std::function; 457 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 458 | 459 | private: 460 | /** 461 | * \brief 462 | * 463 | * \param alg 464 | * \param data 465 | * \param cl 466 | * \param sig 467 | */ 468 | jws(alg_t a, const std::string &data, sp_claims cl, const std::string &sig); 469 | 470 | public: 471 | /** 472 | * \brief 473 | * 474 | * \return 475 | */ 476 | bool is_jwt(); 477 | 478 | /** 479 | * \brief 480 | * 481 | * \param c 482 | * \param v 483 | * \return 484 | */ 485 | bool verify(sp_crypto c, verify_cb v = nullptr); 486 | 487 | /** 488 | * \brief 489 | * 490 | * \return 491 | */ 492 | class claims &claims() { 493 | return *(_claims.get()); 494 | } 495 | 496 | public: 497 | /** 498 | * \brief 499 | * 500 | * \param b 501 | * 502 | * \return 503 | */ 504 | static sp_jws parse(const std::string &b); 505 | 506 | /** 507 | * \brief Sign content and return signature 508 | * 509 | * \param[in] data - data to be signed 510 | * \param[in] c - crypto to sign with 511 | * 512 | * \return signature 513 | */ 514 | static std::string sign(const std::string &data, sp_crypto c); 515 | 516 | static std::string sign_claims(class claims &cl, sp_crypto c); 517 | 518 | static std::string sign_bearer(class claims &cl, sp_crypto c); 519 | private: 520 | /** 521 | * \brief 522 | * 523 | * \param text 524 | * \param sep 525 | * \return 526 | */ 527 | static std::vector tokenize(const std::string &text, char sep); 528 | 529 | private: 530 | alg_t _alg; 531 | std::string _data; 532 | sp_claims _claims; 533 | std::string _sig; 534 | }; 535 | 536 | class crypto { 537 | public: 538 | using password_cb = std::function; 539 | 540 | protected: 541 | struct on_password_wrap { 542 | explicit on_password_wrap(password_cb cb) 543 | : cb(cb) 544 | , required(false) 545 | {} 546 | 547 | password_cb cb; 548 | bool required; 549 | }; 550 | 551 | public: 552 | /** 553 | * \brief 554 | * 555 | * \param alg 556 | */ 557 | explicit crypto(alg_t a = alg_t::NONE); 558 | 559 | virtual ~crypto() = 0; 560 | 561 | public: 562 | /** 563 | * \brief 564 | * 565 | * \return 566 | */ 567 | __NODISCARD 568 | alg_t alg() { return _alg; } 569 | 570 | __NODISCARD 571 | alg_t alg() const { return _alg; } 572 | 573 | /** 574 | * \brief 575 | * 576 | * \param data 577 | * 578 | * \return 579 | */ 580 | virtual std::string sign(const std::string &data) = 0; 581 | 582 | /** 583 | * \brief 584 | * 585 | * \param data 586 | * \param sig 587 | * 588 | * \return 589 | */ 590 | virtual bool verify(const std::string &data, const std::string &sig) = 0; 591 | 592 | public: 593 | /** 594 | * \brief 595 | * 596 | * \param alg 597 | * 598 | * \return 599 | */ 600 | static const char *alg2str(alg_t a); 601 | 602 | static alg_t str2alg(const std::string &a); 603 | 604 | 605 | protected: 606 | static int hash2nid(digest::type type); 607 | 608 | protected: 609 | alg_t _alg; 610 | Json::Value _hdr; 611 | digest::type _hash_type; 612 | }; 613 | 614 | class hmac : public crypto { 615 | public: 616 | explicit hmac(const secure_string &secret, alg_t a = alg_t::HS256); 617 | 618 | ~hmac() override = default; 619 | 620 | public: 621 | std::string sign(const std::string &data) override; 622 | bool verify(const std::string &data, const std::string &sig) override; 623 | 624 | #if !(defined(_MSC_VER) && (_MSC_VER < 1700)) 625 | public: 626 | template 627 | static sp_hmac make_shared(_Args&&... __args) { 628 | return std::make_shared(__args...); 629 | } 630 | #endif // !(defined(_MSC_VER) && (_MSC_VER < 1700)) 631 | 632 | private: 633 | secure_string _secret; 634 | }; 635 | 636 | class rsa : public crypto { 637 | public: 638 | explicit rsa(sp_rsa_key key, alg_t a = alg_t::RS256); 639 | 640 | ~rsa() override; 641 | 642 | public: 643 | std::string sign(const std::string &data) override; 644 | bool verify(const std::string &data, const std::string &sig) override; 645 | 646 | public: 647 | #if !(defined(_MSC_VER) && (_MSC_VER < 1700)) 648 | template 649 | static sp_rsa make_shared(_Args&&... __args) { 650 | return std::make_shared(__args...); 651 | } 652 | #endif // !(defined(_MSC_VER) && (_MSC_VER < 1700)) 653 | 654 | static sp_rsa_key gen(int size); 655 | 656 | static sp_rsa_key load_from_file(const std::string &path, password_cb on_password = nullptr); 657 | 658 | static sp_rsa_key load_from_string(const std::string &str, password_cb on_password = nullptr); 659 | 660 | private: 661 | static int password_loader(char *buf, int size, int rwflag, void *u); 662 | 663 | private: 664 | sp_rsa_key _r; 665 | unsigned int _key_size; 666 | }; 667 | 668 | class ecdsa : public crypto { 669 | public: 670 | explicit ecdsa(sp_ecdsa_key key, alg_t a = alg_t::ES256); 671 | 672 | ~ecdsa() override = default; 673 | 674 | public: 675 | std::string sign(const std::string &data) override; 676 | bool verify(const std::string &data, const std::string &sig) override; 677 | 678 | public: 679 | 680 | #if !(defined(_MSC_VER) && (_MSC_VER < 1700)) 681 | template 682 | static sp_ecdsa make_shared(_Args&&... __args) { 683 | return std::make_shared(__args...); 684 | } 685 | #endif // !(defined(_MSC_VER) && (_MSC_VER < 1700)) 686 | 687 | static sp_ecdsa_key gen(int nid); 688 | 689 | private: 690 | sp_ecdsa_key _e; 691 | }; 692 | 693 | #if defined(JWTPP_SUPPORTED_EDDSA) 694 | class eddsa : public crypto { 695 | public: 696 | explicit eddsa(sp_evp_key key, alg_t a = alg_t::EdDSA); 697 | 698 | ~eddsa() override = default; 699 | 700 | public: 701 | std::string sign(const std::string &data) override; 702 | bool verify(const std::string &data, const std::string &sig) override; 703 | 704 | public: 705 | 706 | #if !(defined(_MSC_VER) && (_MSC_VER < 1700)) 707 | template 708 | static sp_ecdsa make_shared(_Args&&... __args) { 709 | return std::make_shared(__args...); 710 | } 711 | #endif // !(defined(_MSC_VER) && (_MSC_VER < 1700)) 712 | 713 | static sp_evp_key gen(); 714 | static sp_evp_key get_pub(sp_evp_key priv); 715 | 716 | private: 717 | sp_evp_key _e; 718 | }; 719 | #endif // defined(JWTPP_SUPPORTED_EDDSA) 720 | 721 | class pss : public crypto { 722 | public: 723 | explicit pss(sp_rsa_key key, alg_t a = alg_t::PS256); 724 | 725 | ~pss() override = default; 726 | 727 | public: 728 | std::string sign(const std::string &data) override; 729 | bool verify(const std::string &data, const std::string &sig) override; 730 | 731 | private: 732 | sp_rsa_key _r; 733 | size_t _key_size; 734 | }; 735 | 736 | class BIODeleter { 737 | public: 738 | inline void operator()(BIO* bio) const { 739 | (void)BIO_free(bio); 740 | } 741 | }; 742 | 743 | std::string marshal(const Json::Value &json); 744 | 745 | std::string marshal_b64(const Json::Value &json); 746 | 747 | Json::Value unmarshal(const std::string &in); 748 | 749 | Json::Value unmarshal_b64(const std::string &b); 750 | 751 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 752 | # undef final 753 | #endif 754 | 755 | } // namespace jwtpp 756 | -------------------------------------------------------------------------------- /include/local/jwtpp/statics.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artur Troian on 16.10.2019 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace jwtpp { 16 | 17 | template 18 | T *instantiate(Args && ...args) noexcept { 19 | auto buf = new uint8_t[sizeof(T)]; 20 | return new(buf) T(std::forward(args)...); 21 | } 22 | 23 | class static_init { 24 | public: 25 | static_init() noexcept { 26 | #if OPENSSL_VERSION_NUMBER < 0x10100000L 27 | SSL_library_init(); 28 | #else 29 | OPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, nullptr); 30 | #endif 31 | 32 | OpenSSL_add_all_algorithms(); 33 | OpenSSL_add_all_ciphers(); 34 | ERR_load_crypto_strings(); 35 | } 36 | 37 | void operator()() {} 38 | 39 | static static_init &inst() noexcept { 40 | static static_init __inst; 41 | return __inst; 42 | } 43 | }; 44 | 45 | extern static_init &static_instance; 46 | 47 | } // namespace jwtpp 48 | -------------------------------------------------------------------------------- /pkgconfig.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=@CMAKE_INSTALL_PREFIX@ 3 | libdir=@CMAKE_INSTALL_PREFIX@/lib 4 | sharedlibdir=@CMAKE_INSTALL_PREFIX@/lib 5 | includedir=@CMAKE_INSTALL_PREFIX@/include 6 | 7 | Name: jwtpp 8 | Description: JSON Object Signing and Encryption library for C++ 9 | Version: @VERSION@ 10 | URL: https://github.com/troian/jwtpp 11 | Libs: -L${libdir} -L${sharedlibdir} -ljwtpp 12 | Cflags: -I${includedir} 13 | -------------------------------------------------------------------------------- /src/b64.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | namespace jwtpp { 26 | 27 | const std::string b64::base64_chars = 28 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 29 | "abcdefghijklmnopqrstuvwxyz" 30 | "0123456789+/"; 31 | 32 | void b64::uri_enc(char *buf, size_t len) { 33 | size_t i, t; 34 | 35 | for (i = t = 0; i < len; i++) { 36 | switch (buf[i]) { 37 | case '+': 38 | buf[t] = '-'; 39 | break; 40 | case '/': 41 | buf[t] = '_'; 42 | break; 43 | case '=': 44 | continue; 45 | default: 46 | break; 47 | } 48 | t++; 49 | } 50 | } 51 | 52 | void b64::uri_dec(char *buf, size_t len) { 53 | size_t i, t; 54 | 55 | for (i = t = 0; i < len; i++) { 56 | switch (buf[i]) { 57 | case '-': 58 | buf[t] = '+'; 59 | break; 60 | case '_': 61 | buf[t] = '/'; 62 | break; 63 | case '=': 64 | continue; 65 | default: 66 | break; 67 | } 68 | t++; 69 | } 70 | } 71 | 72 | std::string b64::encode(const uint8_t * const stream, size_t in_len) { 73 | int i = 0; 74 | int k = 0; 75 | uint8_t array_3[3]; 76 | uint8_t array_4[4]; 77 | std::string out; 78 | 79 | while (in_len--) { 80 | array_3[i++] = stream[k++]; 81 | if (i == 3) { 82 | array_4[0] = static_cast((array_3[0] & 0xfc) >> 2); 83 | array_4[1] = static_cast((((array_3[0] & 0x03) << 4) + ((array_3[1] & 0xf0) >> 4))); 84 | array_4[2] = static_cast((((array_3[1] & 0x0f) << 2) + ((array_3[2] & 0xc0) >> 6))); 85 | array_4[3] = static_cast((array_3[2] & 0x3f)); 86 | 87 | for (i = 0; (i < 4); i++) { 88 | out += base64_chars[array_4[i]]; 89 | } 90 | i = 0; 91 | } 92 | } 93 | 94 | if (i) { 95 | for (int j = i; j < 3; j++) { 96 | array_3[j] = '\0'; 97 | } 98 | 99 | array_4[0] = static_cast(((array_3[0] & 0xfc) >> 2)); 100 | array_4[1] = static_cast((((array_3[0] & 0x03) << 4) + ((array_3[1] & 0xf0) >> 4))); 101 | array_4[2] = static_cast((((array_3[1] & 0x0f) << 2) + ((array_3[2] & 0xc0) >> 6))); 102 | array_4[3] = static_cast((array_3[2] & 0x3f)); 103 | 104 | for (int j = 0; (j < i + 1); j++) { 105 | out += base64_chars[array_4[j]]; 106 | } 107 | 108 | // while ((i++ < 3)) { 109 | // out += '='; 110 | // } 111 | } 112 | 113 | return out; 114 | } 115 | 116 | std::string b64::encode(const std::vector &stream) { 117 | return encode(stream.data(), stream.size()); 118 | } 119 | 120 | std::string b64::encode(const std::vector * const stream) { 121 | return encode(stream->data(), stream->size()); 122 | } 123 | 124 | std::string b64::encode(const std::string &stream) { 125 | return encode(reinterpret_cast(stream.c_str()), stream.size()); 126 | } 127 | 128 | std::string b64::encode_uri(const uint8_t * const stream, size_t in_len) { 129 | std::string out = encode(stream, in_len); 130 | uri_enc(const_cast(out.data()), out.length()); 131 | 132 | return out; 133 | } 134 | 135 | std::string b64::encode_uri(const std::string &stream) { 136 | return encode_uri(reinterpret_cast(stream.data()), stream.length()); 137 | } 138 | 139 | std::string b64::encode_uri(const std::vector &stream) { 140 | return encode_uri(stream.data(), stream.size()); 141 | } 142 | 143 | std::string b64::encode_uri(const std::vector * const stream) { 144 | return encode_uri(stream->data(), stream->size()); 145 | } 146 | 147 | std::vector b64::decode(const char *in, size_t in_size) { 148 | size_t in_len = in_size; 149 | size_t i = 0; 150 | size_t in_ = 0; 151 | uint8_t array_4[4]; 152 | uint8_t array_3[3]; 153 | std::vector ret; 154 | 155 | while (in_len-- && (in[in_] != '=') && is_base64(static_cast(in[in_]))) { 156 | array_4[i++] = static_cast(in[in_]); 157 | in_++; 158 | if (i == 4) { 159 | for (i = 0; i < 4; i++) { 160 | array_4[i] = static_cast(base64_chars.find(array_4[i])); 161 | } 162 | 163 | array_3[0] = static_cast((array_4[0] << 2) + ((array_4[1] & 0x30) >> 4)); 164 | array_3[1] = static_cast(((array_4[1] & 0xf) << 4) + ((array_4[2] & 0x3c) >> 2)); 165 | array_3[2] = static_cast(((array_4[2] & 0x3) << 6) + array_4[3]); 166 | 167 | for (i = 0; (i < 3); i++) { 168 | ret.push_back(array_3[i]); 169 | } 170 | 171 | i = 0; 172 | } 173 | } 174 | 175 | if (i) { 176 | for (size_t j = i; j < 4; j++) { 177 | array_4[j] = 0; 178 | } 179 | 180 | for (size_t j = 0; j < 4; j++) { 181 | array_4[j] = static_cast(base64_chars.find(array_4[j])); 182 | } 183 | 184 | array_3[0] = static_cast((array_4[0] << 2) + ((array_4[1] & 0x30) >> 4)); 185 | array_3[1] = static_cast(static_cast(((array_4[1] & 0xf) << 4) + ((array_4[2] & 0x3c) >> 2))); 186 | array_3[2] = static_cast(static_cast(((array_4[2] & 0x3) << 6) + array_4[3])); 187 | 188 | for (size_t j = 0; (j < i - 1); j++) { 189 | ret.push_back(array_3[j]); 190 | } 191 | } 192 | 193 | return ret; 194 | } 195 | 196 | std::string b64::decode(const std::string &in) { 197 | std::vector tmp = decode(in.data(), in.length()); 198 | return std::string(tmp.data(), tmp.data() + tmp.size()); 199 | } 200 | 201 | std::string b64::decode_uri(const std::string &in) { 202 | std::string tmp(in); 203 | uri_dec(const_cast(tmp.data()), tmp.length()); 204 | 205 | std::vector tmpd = decode(tmp.data(), tmp.length()); 206 | return std::string(tmpd.data(), tmpd.data() + tmpd.size()); 207 | } 208 | 209 | std::vector b64::decode_uri(const char *in, size_t in_size) { 210 | std::string tmp(in, in_size); 211 | uri_dec(const_cast(tmp.data()), tmp.length()); 212 | 213 | return decode(tmp.data(), tmp.length()); 214 | } 215 | 216 | } // namespace jwtpp 217 | -------------------------------------------------------------------------------- /src/claims.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace jwtpp { 28 | 29 | void claims::set::any(const std::string &key, const std::string &value) { 30 | if (key.empty() || value.empty()) 31 | throw std::invalid_argument("Invalid params"); 32 | 33 | _claims->operator[](key) = value; 34 | } 35 | 36 | claims::claims() 37 | : _claims() 38 | , _set(&_claims) 39 | , _get(&_claims) 40 | , _has(&_claims) 41 | , _del(&_claims) 42 | , _check(&_claims) 43 | {} 44 | 45 | claims::claims(const std::string &d, bool b64) : 46 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 47 | _claims() 48 | , _set(&_claims) 49 | , _get(&_claims) 50 | , _has(&_claims) 51 | , _del(&_claims) 52 | , _check(&_claims) 53 | #else 54 | claims() 55 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 56 | { 57 | if (b64) { 58 | std::string decoded = b64::decode_uri(d); 59 | 60 | std::stringstream(decoded) >> _claims; 61 | } else { 62 | std::stringstream(d) >> _claims; 63 | } 64 | } 65 | 66 | std::string claims::b64() { 67 | return marshal_b64(_claims); 68 | } 69 | 70 | } // namespace jwtpp 71 | -------------------------------------------------------------------------------- /src/crypto.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | namespace jwtpp { 26 | 27 | crypto::crypto(alg_t a) 28 | : _alg(a) 29 | , _hdr() 30 | , _hash_type(digest::type::SHA256) 31 | { 32 | if (a == alg_t::HS256 || a == alg_t::RS256 || a == alg_t::ES256 || a == alg_t::PS256) { 33 | _hash_type = digest::type::SHA256; 34 | } else if (a == alg_t::HS384 || a == alg_t::RS384 || a == alg_t::ES384 || a == alg_t::PS384) { 35 | _hash_type = digest::type::SHA384; 36 | } else if (a == alg_t::HS512 || a == alg_t::RS512 || a == alg_t::ES512 || a == alg_t::PS512) { 37 | _hash_type = digest::type::SHA512; 38 | #if defined(JWTPP_SUPPORTED_EDDSA) 39 | } else if (a == alg_t::EdDSA) { 40 | // ED25519 does not support digests 41 | #endif // defined(JWTPP_SUPPORTED_EDDSA) 42 | } else { 43 | throw std::runtime_error("invalid algorithm"); 44 | } 45 | } 46 | 47 | crypto::~crypto() {} 48 | 49 | const char *crypto::alg2str(alg_t a) { 50 | switch (a) { 51 | case alg_t::NONE: 52 | return "none"; 53 | case alg_t::HS256: 54 | return "HS256"; 55 | case alg_t::HS384: 56 | return "HS384"; 57 | case alg_t::HS512: 58 | return "HS512"; 59 | case alg_t::RS256: 60 | return "RS256"; 61 | case alg_t::RS384: 62 | return "RS384"; 63 | case alg_t::RS512: 64 | return "RS512"; 65 | case alg_t::ES256: 66 | return "ES256"; 67 | case alg_t::ES384: 68 | return "ES384"; 69 | case alg_t::ES512: 70 | return "ES512"; 71 | case alg_t::PS256: 72 | return "PS256"; 73 | case alg_t::PS384: 74 | return "PS384"; 75 | case alg_t::PS512: 76 | return "PS512"; 77 | #if defined(JWTPP_SUPPORTED_EDDSA) 78 | case alg_t::EdDSA: 79 | return "EdDSA"; 80 | #endif // defined(JWTPP_SUPPORTED_EDDSA) 81 | default: 82 | return nullptr; 83 | } 84 | } 85 | 86 | alg_t crypto::str2alg(const std::string &a) { 87 | if (a == "none") { 88 | return alg_t::NONE; 89 | } else if (a == "HS256") { 90 | return alg_t::HS256; 91 | } else if (a == "HS384") { 92 | return alg_t::HS384; 93 | } else if (a == "HS512") { 94 | return alg_t::HS512; 95 | } else if (a == "RS256") { 96 | return alg_t::RS256; 97 | } else if (a == "RS384") { 98 | return alg_t::RS384; 99 | } else if (a == "RS512") { 100 | return alg_t::RS512; 101 | } else if (a == "ES256") { 102 | return alg_t::ES256; 103 | } else if (a == "ES384") { 104 | return alg_t::ES384; 105 | } else if (a == "ES512") { 106 | return alg_t::ES512; 107 | } else if (a == "PS256") { 108 | return alg_t::PS256; 109 | } else if (a == "PS384") { 110 | return alg_t::PS384; 111 | } else if (a == "PS512") { 112 | return alg_t::PS512; 113 | } else if (a == "EdDSA") { 114 | #if defined(JWTPP_SUPPORTED_EDDSA) 115 | return alg_t::EdDSA; 116 | #endif // defined(JWTPP_SUPPORTED_EDDSA) 117 | } else { 118 | return alg_t::UNKNOWN; 119 | } 120 | } 121 | 122 | int crypto::hash2nid(digest::type type) { 123 | int ret = NID_sha256; 124 | 125 | switch (type) { 126 | case digest::type::SHA256: 127 | ret = NID_sha256; 128 | break; 129 | case digest::type::SHA384: 130 | ret = NID_sha384; 131 | break; 132 | case digest::type::SHA512: 133 | ret = NID_sha512; 134 | break; 135 | } 136 | 137 | return ret; 138 | } 139 | 140 | } // namespace jwtpp 141 | -------------------------------------------------------------------------------- /src/digest.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #include 30 | 31 | namespace jwtpp { 32 | 33 | digest::digest(digest::type type, const uint8_t *in_data, size_t in_size) 34 | : _size(SHA256_DIGEST_LENGTH) 35 | , _data(new uint8_t[SHA512_DIGEST_LENGTH], std::default_delete()) { 36 | 37 | switch (type) { 38 | case digest::type::SHA256: { 39 | _size = SHA256_DIGEST_LENGTH; 40 | SHA256_CTX sha_ctx; 41 | if (SHA256_Init(&sha_ctx) != 1) { 42 | throw std::runtime_error("Couldn't init SHA256"); 43 | } 44 | 45 | if (SHA256_Update(&sha_ctx, in_data, in_size) != 1) { 46 | throw std::runtime_error("Couldn't calculate hash"); 47 | } 48 | 49 | if (SHA256_Final(_data.get(), &sha_ctx) != 1) { 50 | throw std::runtime_error("Couldn't finalize SHA"); 51 | } 52 | break; 53 | } 54 | case digest::type::SHA384: { 55 | _size = SHA384_DIGEST_LENGTH; 56 | SHA512_CTX sha_ctx; 57 | 58 | if (SHA384_Init(&sha_ctx) != 1) { 59 | throw std::runtime_error("Couldn't init SHA384"); 60 | } 61 | 62 | if (SHA384_Update(&sha_ctx, in_data, in_size) != 1) { 63 | throw std::runtime_error("Couldn't calculate hash"); 64 | } 65 | 66 | if (SHA384_Final(_data.get(), &sha_ctx) != 1) { 67 | throw std::runtime_error("Couldn't finalize SHA"); 68 | } 69 | break; 70 | } 71 | case digest::type::SHA512: { 72 | SHA512_CTX sha_ctx; 73 | _size = SHA512_DIGEST_LENGTH; 74 | 75 | if (SHA512_Init(&sha_ctx) != 1) { 76 | throw std::runtime_error("Couldn't init SHA512"); 77 | } 78 | 79 | if (SHA512_Update(&sha_ctx, in_data, in_size) != 1) { 80 | throw std::runtime_error("Couldn't calculate hash"); 81 | } 82 | 83 | if (SHA512_Final(_data.get(), &sha_ctx) != 1) { 84 | throw std::runtime_error("Couldn't finalize SHA"); 85 | } 86 | break; 87 | } 88 | } 89 | } 90 | 91 | digest::~digest() { 92 | std::memset(_data.get(), 0, _size); 93 | } 94 | 95 | size_t digest::size() const { 96 | return _size; 97 | } 98 | 99 | uint8_t *digest::data() { 100 | return _data.get(); 101 | } 102 | 103 | std::string digest::to_string() const { 104 | std::stringstream s; 105 | for (size_t i = 0; i < size() / 2; ++i) { 106 | s << std::hex << std::setfill('0') << std::setw(2) << (_data.get()[i * 2] << 8 | _data.get()[(i * 2) + 1]); 107 | } 108 | 109 | return s.str(); 110 | } 111 | 112 | } // namespace jwtpp 113 | -------------------------------------------------------------------------------- /src/ecdsa.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace jwtpp { 28 | 29 | ecdsa::ecdsa(sp_ecdsa_key key, alg_t a) 30 | : crypto(a) 31 | , _e(key) 32 | { 33 | if (a != alg_t::ES256 && a != alg_t::ES384 && a != alg_t::ES512) { 34 | throw std::invalid_argument("Invalid algorithm"); 35 | } 36 | } 37 | 38 | std::string ecdsa::sign(const std::string &data) { 39 | if (data.empty()) { 40 | throw std::invalid_argument("data is empty"); 41 | } 42 | 43 | auto sig = std::shared_ptr(new uint8_t[ECDSA_size(_e.get())], std::default_delete()); 44 | 45 | digest d(_hash_type, reinterpret_cast(data.data()), data.length()); 46 | 47 | uint32_t sig_len; 48 | 49 | if (ECDSA_sign(0, d.data(), static_cast(d.size()), sig.get(), &sig_len, _e.get()) != 1) { 50 | throw std::runtime_error("Couldn't sign ECDSA"); 51 | } 52 | 53 | return b64::encode_uri(sig.get(), sig_len); 54 | } 55 | 56 | bool ecdsa::verify(const std::string &data, const std::string &sig) { 57 | digest d(_hash_type, reinterpret_cast(data.data()), data.length()); 58 | 59 | auto s = b64::decode_uri(sig.data(), sig.length()); 60 | 61 | return ECDSA_verify( 62 | 0 63 | , d.data() 64 | , static_cast(d.size()) 65 | , reinterpret_cast(s.data()) 66 | , static_cast(s.size()) 67 | , _e.get()) == 1; 68 | } 69 | 70 | sp_ecdsa_key ecdsa::gen(int nid) { 71 | sp_ecdsa_key key = std::shared_ptr(EC_KEY_new(), ::EC_KEY_free); 72 | std::shared_ptr group = std::shared_ptr(EC_GROUP_new_by_curve_name(nid), ::EC_GROUP_free); 73 | std::shared_ptr point = std::shared_ptr(EC_POINT_new(group.get()), ::EC_POINT_free); 74 | 75 | if (EC_KEY_set_group(key.get(), group.get()) != 1) { 76 | throw std::runtime_error("Couldn't set EC KEY group"); 77 | } 78 | 79 | int degree = EC_GROUP_get_degree(EC_KEY_get0_group(key.get())); 80 | if (degree < 160) { 81 | std::stringstream str; 82 | str << "Skip the curve [" << OBJ_nid2sn(nid) << "] (degree = " << degree << ")"; 83 | throw std::runtime_error(str.str()); 84 | } 85 | 86 | if (EC_KEY_generate_key(key.get()) != 1) { 87 | throw std::runtime_error("Couldn't generate EC KEY"); 88 | } 89 | 90 | const BIGNUM *priv = EC_KEY_get0_private_key(key.get()); 91 | 92 | if (EC_POINT_mul(group.get(), point.get(), priv, nullptr, nullptr, nullptr) != 1) { 93 | throw std::runtime_error("Couldn't generate EC PUB KEY"); 94 | } 95 | 96 | if (EC_KEY_set_public_key(key.get(), point.get()) != 1) { 97 | throw std::runtime_error("Couldn't set EC PUB KEY"); 98 | } 99 | 100 | if (EC_KEY_check_key(key.get()) != 1) { 101 | throw std::runtime_error("EC check failed"); 102 | } 103 | 104 | return key; 105 | } 106 | 107 | } // namespace jwtpp 108 | -------------------------------------------------------------------------------- /src/eddsa.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #if defined(JWTPP_SUPPORTED_EDDSA) 26 | #include 27 | #include 28 | #include 29 | 30 | namespace jwtpp { 31 | 32 | eddsa::eddsa(sp_evp_key key, alg_t a) 33 | : crypto(a) 34 | , _e(key) 35 | { 36 | if (a != alg_t::EdDSA) { 37 | throw std::invalid_argument("Invalid algorithm"); 38 | } 39 | } 40 | 41 | std::string eddsa::sign(const std::string &data) { 42 | if (data.empty()) { 43 | throw std::invalid_argument("data is empty"); 44 | } 45 | 46 | auto md = sp_evp_md_ctx(EVP_MD_CTX_new(), ::EVP_MD_CTX_free); 47 | 48 | EVP_MD_CTX_init(md.get()); 49 | 50 | if (EVP_DigestSignInit(md.get(), nullptr, nullptr, nullptr, _e.get()) != 1) { 51 | throw std::runtime_error("eddsa: digest sign init"); 52 | } 53 | 54 | size_t sig_len = EVP_PKEY_size(_e.get()); 55 | 56 | auto sig = std::shared_ptr(new uint8_t[sig_len], std::default_delete()); 57 | 58 | if (EVP_DigestSign(md.get(), sig.get(), &sig_len, (const uint8_t *)data.data(), data.size()) != 1) { 59 | throw std::runtime_error("eddsa: digest sign"); 60 | } 61 | 62 | return b64::encode_uri(sig.get(), sig_len); 63 | } 64 | 65 | bool eddsa::verify(const std::string &data, const std::string &sig) { 66 | auto s = b64::decode_uri(sig.data(), sig.length()); 67 | 68 | auto md = sp_evp_md_ctx(EVP_MD_CTX_new(), ::EVP_MD_CTX_free); 69 | 70 | EVP_MD_CTX_init(md.get()); 71 | 72 | if (EVP_DigestVerifyInit(md.get(), nullptr, nullptr, nullptr, _e.get()) != 1) { 73 | throw std::runtime_error("eddsa: digest verify init"); 74 | } 75 | 76 | return EVP_DigestVerify(md.get(), s.data(), s.size(), (const uint8_t *)data.data(), data.size()) == 1; 77 | } 78 | 79 | sp_evp_key eddsa::gen() { 80 | auto ctx = sp_evp_pkey_ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, nullptr), ::EVP_PKEY_CTX_free); 81 | if (EVP_PKEY_keygen_init(ctx.get()) != 1) { 82 | throw std::runtime_error("eddsa: couldn't init evp keygen"); 83 | } 84 | 85 | EVP_PKEY *key = nullptr; 86 | 87 | if (EVP_PKEY_keygen(ctx.get(), &key) != 1) { 88 | throw std::runtime_error("eddsa: couldn't generate ED25519 key"); 89 | } 90 | 91 | return sp_evp_key(key, ::EVP_PKEY_free); 92 | } 93 | 94 | sp_evp_key eddsa::get_pub(sp_evp_key priv) { 95 | size_t key_len; 96 | 97 | if (EVP_PKEY_get_raw_public_key(priv.get(), nullptr, &key_len) != 1) { 98 | throw std::runtime_error("eddsa: couldn't read size of public key"); 99 | } 100 | 101 | auto k = std::shared_ptr(new uint8_t[key_len], std::default_delete()); 102 | 103 | if (EVP_PKEY_get_raw_public_key(priv.get(), k.get(), &key_len) != 1) { 104 | throw std::runtime_error("eddsa: couldn't extract public key"); 105 | } 106 | 107 | return sp_evp_key(EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, nullptr, k.get(), key_len), ::EVP_PKEY_free); 108 | } 109 | 110 | } // namespace jwtpp 111 | 112 | #endif // defined(JWTPP_SUPPORTED_EDDSA) 113 | -------------------------------------------------------------------------------- /src/header.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | namespace jwtpp { 26 | 27 | hdr::hdr(alg_t a) 28 | : _h() 29 | { 30 | _h["typ"] = "JWT"; 31 | _h["alg"] = crypto::alg2str(a); 32 | } 33 | 34 | hdr::hdr(const std::string &data) 35 | : _h() 36 | { 37 | std::stringstream(data) >> _h; 38 | 39 | if (!_h.isMember("typ") || !_h["typ"].isString()) { 40 | throw std::runtime_error("stream does not have valid \"typ\" field"); 41 | } 42 | 43 | if (_h["typ"].asString() != "JWT") { 44 | throw std::runtime_error("invalid \"typ\" value"); 45 | } 46 | 47 | if (!_h.isMember("alg") || !_h["alg"].isString()) { 48 | throw std::runtime_error("stream does not have valid \"alg\" field"); 49 | } 50 | 51 | if (crypto::str2alg(_h["alg"].asString()) == alg_t::UNKNOWN) { 52 | throw std::runtime_error("invalid \"alg\" value"); 53 | } 54 | } 55 | 56 | std::string hdr::b64() { 57 | return marshal_b64(_h); 58 | } 59 | 60 | } // namespace jwtpp 61 | -------------------------------------------------------------------------------- /src/hmac.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace jwtpp { 28 | 29 | hmac::hmac(const secure_string &secret, alg_t a) 30 | : crypto(a) 31 | , _secret(secret) 32 | { 33 | if (a != alg_t::HS256 && a != alg_t::HS384 && a != alg_t::HS512) { 34 | throw std::invalid_argument("Invalid algorithm"); 35 | } 36 | 37 | if (secret.empty()) { 38 | throw std::invalid_argument("Invalid secret"); 39 | } 40 | } 41 | 42 | std::string hmac::sign(const std::string &data) { 43 | if (data.empty()) { 44 | throw std::invalid_argument("data is empty"); 45 | } 46 | 47 | const EVP_MD *evp; 48 | 49 | switch (_alg) { 50 | case alg_t::HS256: evp = EVP_sha256(); break; 51 | case alg_t::HS384: evp = EVP_sha384(); break; 52 | case alg_t::HS512: evp = EVP_sha512(); break; 53 | default: 54 | // Should never happen 55 | throw std::runtime_error("Invalid alg"); 56 | } 57 | 58 | HMAC_CTX *hmac; 59 | 60 | #if OPENSSL_VERSION_NUMBER < 0x10100000L 61 | HMAC_CTX hmac_l; 62 | HMAC_CTX_init(&hmac_l); 63 | hmac = &hmac_l; 64 | #else 65 | hmac = HMAC_CTX_new(); 66 | #endif 67 | 68 | HMAC_Init_ex(hmac, _secret.data(), static_cast(_secret.length()), evp, nullptr); 69 | HMAC_Update(hmac, reinterpret_cast(data.c_str()), data.size()); 70 | 71 | auto res = std::shared_ptr(new uint8_t[EVP_MD_size(evp)], std::default_delete()); 72 | uint32_t size; 73 | 74 | HMAC_Final(hmac, res.get(), &size); 75 | 76 | #if OPENSSL_VERSION_NUMBER < 0x10100000L 77 | HMAC_CTX_cleanup(hmac); 78 | #else 79 | HMAC_CTX_free(hmac); 80 | #endif 81 | 82 | return b64::encode_uri(res.get(), size); 83 | } 84 | 85 | bool hmac::verify(const std::string &data, const std::string &sig) { 86 | return sig == sign(data); 87 | } 88 | 89 | } // namespace jwtpp 90 | -------------------------------------------------------------------------------- /src/jwtpp.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | namespace jwtpp { 26 | 27 | static const std::string bearer_hdr("bearer "); 28 | 29 | jws::jws(alg_t a, const std::string &data, sp_claims cl, const std::string &sig) 30 | : _alg(a) 31 | , _data(data) 32 | , _claims(cl) 33 | , _sig(sig) { 34 | 35 | } 36 | 37 | bool jws::verify(sp_crypto c, verify_cb v) { 38 | if (!c) { 39 | throw std::runtime_error("uninitialized crypto"); 40 | } 41 | 42 | if (c->alg() != _alg) { 43 | throw std::runtime_error("invalid crypto alg"); 44 | } 45 | 46 | if (!c->verify(_data, _sig)) { 47 | return false; 48 | } 49 | 50 | if (v) { 51 | return v(_claims); 52 | } 53 | 54 | return true; 55 | } 56 | 57 | sp_jws jws::parse(const std::string &full_bearer) { 58 | if (full_bearer.empty() || full_bearer.length() < bearer_hdr.length()) { 59 | throw std::invalid_argument("Bearer is invalid or empty"); 60 | } 61 | 62 | for (size_t i = 0; i < bearer_hdr.length(); i++) { 63 | 64 | if (bearer_hdr[i] != tolower(full_bearer[i])) { 65 | throw std::invalid_argument("Bearer header is invalid"); 66 | } 67 | } 68 | 69 | std::string bearer = full_bearer.substr(bearer_hdr.length()); 70 | 71 | std::vector tokens; 72 | tokens = tokenize(bearer, '.'); 73 | 74 | if (tokens.size() != 3) { 75 | throw std::runtime_error("Bearer is invalid"); 76 | } 77 | 78 | Json::Value hdr; 79 | 80 | try { 81 | hdr = unmarshal_b64(tokens[0]); 82 | } catch (...) { 83 | throw; 84 | } 85 | 86 | if (!hdr.isMember("typ") || !hdr.isMember("alg")) { 87 | throw std::runtime_error("Invalid JWT header"); 88 | } 89 | 90 | if (hdr["typ"].asString() != "JWT") { 91 | throw std::runtime_error("Is not JWT"); 92 | } 93 | 94 | alg_t a = crypto::str2alg(hdr["alg"].asString()); 95 | if (a >= alg_t::UNKNOWN) { 96 | throw std::runtime_error("Invalid alg"); 97 | } 98 | 99 | sp_claims cl; 100 | 101 | try { 102 | cl = std::make_shared(tokens[1], true); 103 | } catch (...) { 104 | throw; 105 | } 106 | 107 | std::string d = tokens[0]; 108 | d += "."; 109 | d += tokens[1]; 110 | 111 | jws *j; 112 | 113 | try { 114 | j = new jws(a, d, cl, tokens[2]); 115 | } catch (...) { 116 | throw; 117 | } 118 | 119 | return sp_jws(j); 120 | } 121 | 122 | std::string jws::sign(const std::string &data, sp_crypto c) { 123 | return c->sign(data); 124 | } 125 | 126 | std::string jws::sign_claims(class claims &cl, sp_crypto c) { 127 | std::string out; 128 | 129 | hdr h(c->alg()); 130 | out = h.b64(); 131 | out += "."; 132 | out += cl.b64(); 133 | 134 | std::string sig; 135 | sig = jws::sign(out, c); 136 | out += "."; 137 | out += sig; 138 | 139 | return out; 140 | } 141 | 142 | std::string jws::sign_bearer(class claims &cl, sp_crypto c) { 143 | std::string bearer("Bearer "); 144 | bearer += jws::sign_claims(cl, c); 145 | return bearer; 146 | } 147 | 148 | std::vector jws::tokenize(const std::string &text, char sep) { 149 | std::vector tokens; 150 | std::size_t start = 0; 151 | std::size_t end = 0; 152 | 153 | while ((end = text.find(sep, start)) != std::string::npos) { 154 | tokens.push_back(text.substr(start, end - start)); 155 | start = end + 1; 156 | } 157 | 158 | tokens.push_back(text.substr(start)); 159 | 160 | return tokens; 161 | } 162 | 163 | } // namespace jwtpp 164 | -------------------------------------------------------------------------------- /src/pss.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artur Troian on 2019-08-14 3 | // 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace jwtpp { 10 | 11 | pss::pss(sp_rsa_key key, alg_t a) 12 | : crypto(a) 13 | , _r(key) 14 | { 15 | if (a != alg_t::PS256 && a != alg_t::PS384 && a != alg_t::PS512) { 16 | throw std::invalid_argument("Invalid algorithm"); 17 | } 18 | 19 | _key_size = static_cast(RSA_size(_r.get())); 20 | 21 | if (_alg == alg_t::PS512 && (_key_size < 256)) { 22 | throw std::runtime_error("insufficient key size"); 23 | } 24 | } 25 | 26 | std::string pss::sign(const std::string &data) { 27 | if (data.empty()) { 28 | throw std::invalid_argument("data is empty"); 29 | } 30 | 31 | digest d(_hash_type, reinterpret_cast(data.data()), data.length()); 32 | 33 | auto padded = std::shared_ptr(new uint8_t[_key_size], std::default_delete()); 34 | 35 | auto sig = std::shared_ptr(new uint8_t[_key_size], std::default_delete()); 36 | 37 | if (RSA_padding_add_PKCS1_PSS(_r.get(), padded.get(), d.data(), digest::md(_hash_type), -1) != 1) { 38 | throw std::runtime_error("failed to create signature"); 39 | } 40 | 41 | if (RSA_private_encrypt(_key_size, padded.get(), sig.get(), _r.get(), RSA_NO_PADDING) < 0) { 42 | throw std::runtime_error("couldn't sign RSA"); 43 | } 44 | 45 | return b64::encode_uri(sig.get(), _key_size); 46 | } 47 | 48 | bool pss::verify(const std::string &data, const std::string &sig) { 49 | digest d(_hash_type, reinterpret_cast(data.data()), data.length()); 50 | 51 | auto decrypted_sig = std::shared_ptr(new uint8_t[_key_size], std::default_delete()); 52 | auto decoded_sig = b64::decode_uri(sig.data(), sig.length()); 53 | 54 | if(RSA_public_decrypt(decoded_sig.size(), decoded_sig.data(), decrypted_sig.get(), _r.get(), RSA_NO_PADDING) < 0) { 55 | throw std::runtime_error("invalid signature"); 56 | } 57 | 58 | return RSA_verify_PKCS1_PSS(_r.get(), d.data(), digest::md(_hash_type), decrypted_sig.get(), -1) == 1; 59 | } 60 | 61 | } // namespace jwtpp 62 | -------------------------------------------------------------------------------- /src/rsa.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | namespace jwtpp { 29 | 30 | rsa::rsa(sp_rsa_key key, alg_t a) 31 | : crypto(a) 32 | , _r(key) 33 | { 34 | if (a != alg_t::RS256 && a != alg_t::RS384 && a != alg_t::RS512) { 35 | throw std::invalid_argument("Invalid algorithm"); 36 | } 37 | 38 | _key_size = static_cast(RSA_size(_r.get())); 39 | } 40 | 41 | rsa::~rsa() { 42 | static_instance(); 43 | } 44 | 45 | std::string rsa::sign(const std::string &data) { 46 | if (data.empty()) { 47 | throw std::invalid_argument("data is empty"); 48 | } 49 | 50 | std::shared_ptr sig = std::shared_ptr(new uint8_t[_key_size], std::default_delete()); 51 | 52 | digest d(_hash_type, reinterpret_cast(data.data()), data.length()); 53 | 54 | if (RSA_sign(hash2nid(_hash_type), d.data(), static_cast(d.size()), sig.get(), &_key_size, _r.get()) != 1) { 55 | throw std::runtime_error("Couldn't sign RSA"); 56 | } 57 | 58 | return b64::encode_uri(sig.get(), _key_size); 59 | } 60 | 61 | bool rsa::verify(const std::string &data, const std::string &sig) { 62 | digest d(_hash_type, reinterpret_cast(data.data()), data.length()); 63 | 64 | std::vector s = b64::decode_uri(sig.data(), sig.length()); 65 | 66 | return RSA_verify( 67 | hash2nid(_hash_type) 68 | , d.data() 69 | , static_cast(d.size()) 70 | , reinterpret_cast(s.data()) 71 | , static_cast(s.size()) 72 | , _r.get()) == 1; 73 | } 74 | 75 | sp_rsa_key rsa::gen(int size) { 76 | // keys less than 1024 bits are insecure 77 | if ((size % 1024) != 0) { 78 | throw std::invalid_argument("Invalid keys size"); 79 | } 80 | 81 | sp_rsa_key key = std::shared_ptr(RSA_new(), ::RSA_free); 82 | BIGNUM *bn = BN_new(); 83 | BN_set_word(bn, RSA_F4); 84 | RSA_generate_key_ex(key.get(), size, bn, nullptr); 85 | 86 | return key; 87 | } 88 | 89 | sp_rsa_key rsa::load_from_file(const std::string &path, password_cb on_password) { 90 | RSA *r; 91 | 92 | auto f = up_file(::std::fopen(path.c_str(), "re"), ::std::fclose); 93 | if (!f) { 94 | throw std::runtime_error("cannot open file " + path); 95 | } 96 | 97 | on_password_wrap wrap(on_password); 98 | 99 | r = PEM_read_RSAPrivateKey(f.get(), nullptr, password_loader, &wrap); 100 | if (wrap.required) { 101 | throw std::runtime_error("password required"); 102 | } else if (r == nullptr) { 103 | throw std::runtime_error("read rsa key"); 104 | } 105 | 106 | return std::shared_ptr(r, ::RSA_free); 107 | } 108 | 109 | sp_rsa_key rsa::load_from_string(const std::string& str, password_cb on_password) { 110 | RSA *r; 111 | 112 | auto bio = std::unique_ptr{BIO_new_mem_buf(str.data(), str.size())}; 113 | 114 | on_password_wrap wrap(on_password); 115 | 116 | r = PEM_read_bio_RSAPrivateKey(bio.get(), nullptr, password_loader, &wrap); 117 | if (wrap.required) { 118 | throw std::runtime_error("password required"); 119 | } else if (r == nullptr) { 120 | throw std::runtime_error("read rsa key"); 121 | } 122 | 123 | return std::shared_ptr(r, ::RSA_free); 124 | } 125 | 126 | int rsa::password_loader(char *buf, int size, int rwflag, void *u) { 127 | auto wrap = reinterpret_cast(u); 128 | 129 | if (wrap->cb == nullptr) { 130 | wrap->required = true; 131 | return 0; 132 | } 133 | 134 | secure_string pass; 135 | int pass_size = 0; 136 | 137 | try { 138 | wrap->cb(pass, rwflag); 139 | pass_size = pass.copy(buf, secure_string::size_type(size), 0); 140 | } catch (...) { 141 | pass_size = 0; 142 | } 143 | 144 | return pass_size; 145 | } 146 | 147 | } // namespace jwtpp 148 | -------------------------------------------------------------------------------- /src/statics.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artur Troian on 16.10.2019 3 | // 4 | 5 | #include 6 | 7 | namespace jwtpp { 8 | 9 | //#if defined(__GNUC__) 10 | //__attribute__((used)) 11 | //#endif 12 | //static_init *instance = instantiate(); 13 | 14 | static_init &static_instance = static_init::inst(); 15 | 16 | } // namespace jwtpp 17 | -------------------------------------------------------------------------------- /src/tools.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace jwtpp { 28 | 29 | std::string marshal(const Json::Value &json) { 30 | Json::StreamWriterBuilder builder; 31 | builder["commentStyle"] = "None"; 32 | builder["indentation"] = ""; // Write in one line 33 | std::string out = Json::writeString(builder, json); 34 | return out; 35 | } 36 | 37 | std::string marshal_b64(const Json::Value &json) { 38 | std::string s = marshal(json); 39 | return b64::encode_uri(s); 40 | } 41 | 42 | Json::Value unmarshal(const std::string &in) { 43 | Json::Value j; 44 | std::stringstream(in) >> j; 45 | 46 | return j; 47 | } 48 | 49 | Json::Value unmarshal_b64(const std::string &b64) { 50 | std::string decoded; 51 | decoded = b64::decode(b64); 52 | return unmarshal(decoded); 53 | } 54 | 55 | } // namespace jwtpp 56 | -------------------------------------------------------------------------------- /tests/b64.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | TEST(jwtpp, b64) 32 | { 33 | std::vector in; 34 | in.resize(128); 35 | 36 | std::string b64; 37 | 38 | std::random_device rnd_device; 39 | // Specify the engine and distribution. 40 | std::mt19937 mersenne_engine(rnd_device()); 41 | std::uniform_int_distribution dist(0, 256); 42 | 43 | auto gen = std::bind(dist, mersenne_engine); 44 | 45 | std::generate(std::begin(in), std::end(in), gen); 46 | 47 | b64 = jwtpp::b64::encode(in); 48 | 49 | std::vector out; 50 | 51 | out = jwtpp::b64::decode(b64.data(), b64.length()); 52 | 53 | EXPECT_EQ(in.size(), out.size()); 54 | EXPECT_EQ(in, out); 55 | 56 | b64.clear(); 57 | out.clear(); 58 | 59 | b64 = jwtpp::b64::encode_uri(in); 60 | out = jwtpp::b64::decode_uri(b64.data(), b64.length()); 61 | 62 | EXPECT_EQ(in.size(), out.size()); 63 | EXPECT_EQ(in, out); 64 | } 65 | -------------------------------------------------------------------------------- /tests/claims.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | TEST(jwtpp, create_close_claims) 28 | { 29 | EXPECT_NO_THROW(jwtpp::claims cl); 30 | EXPECT_THROW(jwtpp::claims cl(""), std::exception); 31 | EXPECT_THROW(jwtpp::claims cl("", true), std::exception); 32 | EXPECT_THROW(jwtpp::claims cl("jkhfkjsgdfg"), std::exception); 33 | 34 | jwtpp::sp_claims cl; 35 | 36 | EXPECT_NO_THROW(cl = std::make_shared()); 37 | 38 | EXPECT_THROW(cl->set().any("", "val"), std::exception); 39 | EXPECT_THROW(cl->set().any("key", ""), std::exception); 40 | 41 | EXPECT_NO_THROW(cl->set().iss("troian")); 42 | EXPECT_NO_THROW(cl->set().iss("troian")); 43 | 44 | EXPECT_FALSE(cl->has().aud()); 45 | 46 | EXPECT_EQ("troian", cl->get().iss()); 47 | } 48 | 49 | TEST(jwtpp, set_other_types_claims) 50 | { 51 | jwtpp::claims cl; 52 | const Json::Int ts = 1593345759; 53 | cl.set().any("iat", ts); 54 | EXPECT_TRUE(cl.has().any("iat")); 55 | EXPECT_TRUE(cl.get().anyInt("iat") == ts); 56 | EXPECT_TRUE(cl.check().any("iat", ts)); 57 | 58 | const Json::UInt uintval = 0x1d; 59 | cl.set().any("uintval", uintval); 60 | EXPECT_TRUE(cl.has().any("uintval")); 61 | EXPECT_TRUE(cl.get().anyUInt("uintval") == uintval); 62 | EXPECT_TRUE(cl.check().any("uintval", uintval)); 63 | 64 | const Json::Int64 int64val = 0x1122334455667788; 65 | cl.set().any("int64val", int64val); 66 | EXPECT_TRUE(cl.has().any("int64val")); 67 | EXPECT_TRUE(cl.get().anyInt64("int64val") == int64val); 68 | EXPECT_TRUE(cl.check().any("int64val", int64val)); 69 | 70 | const Json::UInt64 unsig64int = 0x8877665544332211; 71 | cl.set().any("unsig64int", unsig64int); 72 | EXPECT_TRUE(cl.has().any("unsig64int")); 73 | EXPECT_TRUE(cl.get().anyUInt64("unsig64int") == unsig64int); 74 | EXPECT_TRUE(cl.check().any("unsig64int", unsig64int)); 75 | 76 | const double realval = 0.01; 77 | cl.set().any("realval", realval); 78 | EXPECT_TRUE(cl.has().any("realval")); 79 | EXPECT_TRUE(cl.get().anyDouble("realval")); 80 | EXPECT_TRUE(cl.check().any("realval", realval)); 81 | } 82 | 83 | TEST(jwtpp, set__claim) 84 | { 85 | jwtpp::claims cl; 86 | const Json::Int ts = 1593345759; 87 | cl.set().any("iat", ts); 88 | EXPECT_TRUE(cl.has().any("iat")); 89 | EXPECT_TRUE(cl.get().anyInt("iat") == ts); 90 | } 91 | -------------------------------------------------------------------------------- /tests/crypto.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | TEST(jwtpp, crypto_str2alg) { 28 | EXPECT_EQ(jwtpp::alg_t::NONE, jwtpp::crypto::str2alg("none")); 29 | EXPECT_EQ(jwtpp::alg_t::HS256, jwtpp::crypto::str2alg("HS256")); 30 | EXPECT_EQ(jwtpp::alg_t::HS384, jwtpp::crypto::str2alg("HS384")); 31 | EXPECT_EQ(jwtpp::alg_t::HS512, jwtpp::crypto::str2alg("HS512")); 32 | EXPECT_EQ(jwtpp::alg_t::RS256, jwtpp::crypto::str2alg("RS256")); 33 | EXPECT_EQ(jwtpp::alg_t::RS384, jwtpp::crypto::str2alg("RS384")); 34 | EXPECT_EQ(jwtpp::alg_t::RS512, jwtpp::crypto::str2alg("RS512")); 35 | EXPECT_EQ(jwtpp::alg_t::ES256, jwtpp::crypto::str2alg("ES256")); 36 | EXPECT_EQ(jwtpp::alg_t::ES384, jwtpp::crypto::str2alg("ES384")); 37 | EXPECT_EQ(jwtpp::alg_t::ES512, jwtpp::crypto::str2alg("ES512")); 38 | EXPECT_EQ(jwtpp::alg_t::PS256, jwtpp::crypto::str2alg("PS256")); 39 | EXPECT_EQ(jwtpp::alg_t::PS384, jwtpp::crypto::str2alg("PS384")); 40 | EXPECT_EQ(jwtpp::alg_t::PS512, jwtpp::crypto::str2alg("PS512")); 41 | #if defined(JWTPP_SUPPORTED_EDDSA) 42 | EXPECT_EQ(jwtpp::alg_t::EdDSA, jwtpp::crypto::str2alg("EdDSA")); 43 | #endif // defined(JWTPP_SUPPORTED_EDDSA) 44 | EXPECT_EQ(jwtpp::alg_t::UNKNOWN, jwtpp::crypto::str2alg("bsd")); 45 | } 46 | 47 | TEST(jwtpp, crypto_alg2str) { 48 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::NONE)), std::string("none")); 49 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::HS256)), std::string("HS256")); 50 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::HS384)), std::string("HS384")); 51 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::HS512)), std::string("HS512")); 52 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::RS256)), std::string("RS256")); 53 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::RS384)), std::string("RS384")); 54 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::RS512)), std::string("RS512")); 55 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::ES256)), std::string("ES256")); 56 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::ES384)), std::string("ES384")); 57 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::ES512)), std::string("ES512")); 58 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::PS256)), std::string("PS256")); 59 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::PS384)), std::string("PS384")); 60 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::PS512)), std::string("PS512")); 61 | #if defined(JWTPP_SUPPORTED_EDDSA) 62 | EXPECT_EQ(std::string(jwtpp::crypto::alg2str(jwtpp::alg_t::EdDSA)), std::string("EdDSA")); 63 | #endif // defined(JWTPP_SUPPORTED_EDDSA) 64 | EXPECT_EQ(jwtpp::crypto::alg2str(jwtpp::alg_t::UNKNOWN), nullptr); 65 | } 66 | -------------------------------------------------------------------------------- /tests/digest.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | 29 | static const uint32_t test_payload_size = 4080; 30 | 31 | extern unsigned char test_payload[test_payload_size]; 32 | 33 | static std::string payload_hash("71fca3dd7c9d12dd33dc1979a72829de5f3fe9e1d77ec205cf6517d125f7c8f8"); 34 | 35 | TEST(jwtpp, digest_to_string_valid) { 36 | EXPECT_NO_THROW(jwtpp::digest d(jwtpp::digest::type::SHA256, test_payload, test_payload_size)); 37 | 38 | jwtpp::digest d(jwtpp::digest::type::SHA256, test_payload, test_payload_size); 39 | 40 | EXPECT_EQ(payload_hash, d.to_string()); 41 | } 42 | 43 | TEST(jwtpp, digest_to_string_invalid) { 44 | jwtpp::digest d(jwtpp::digest::type::SHA384, test_payload, test_payload_size); 45 | 46 | EXPECT_NE(payload_hash, d.to_string()); 47 | } 48 | 49 | unsigned char test_payload[] = { 50 | 0xe9, 0x03, 0x00, 0x00, 0x7c, 0x05, 0x10, 0x40, 0x00, 0x00, 0x10, 0x40, 51 | 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 55 | 0x00, 0x00, 0x00, 0x00, 0xfc, 0x82, 0xfe, 0x3f, 0x1c, 0x4b, 0x00, 0x40, 56 | 0xcc, 0x24, 0x00, 0x40, 0x12, 0xc1, 0xe0, 0x3d, 0x01, 0x1c, 0x04, 0x02, 57 | 0x61, 0x07, 0x01, 0xfb, 0xff, 0xc0, 0x00, 0x00, 0x32, 0x01, 0x00, 0x22, 58 | 0xa0, 0xe9, 0x27, 0x13, 0x1c, 0x32, 0x11, 0x00, 0x22, 0xa4, 0xea, 0x27, 59 | 0x93, 0x05, 0x28, 0x31, 0x06, 0x04, 0x00, 0x00, 0x21, 0xf3, 0xff, 0x01, 60 | 0xf4, 0xff, 0xc0, 0x00, 0x00, 0x7c, 0xf2, 0x46, 0x00, 0x00, 0x0c, 0x02, 61 | 0x08, 0x71, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0xaa, 0x84, 0xfe, 0x3f, 62 | 0x08, 0xfc, 0x10, 0x40, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x02, 0x20, 0xc2, 63 | 0x20, 0x21, 0xfb, 0xff, 0xc0, 0x3c, 0x20, 0x09, 0x31, 0x01, 0xe8, 0xff, 64 | 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0xc5, 0xf9, 0xff, 0x26, 0x02, 0x14, 0x31, 65 | 0xf7, 0xff, 0xcc, 0x32, 0x2d, 0x0c, 0x06, 0x01, 0x00, 0xc2, 0xcc, 0x10, 66 | 0x2a, 0x2c, 0xc0, 0x03, 0x00, 0x46, 0x00, 0x00, 0x0c, 0x12, 0x08, 0x31, 67 | 0xc8, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, 68 | 0x14, 0x10, 0x00, 0x00, 0x18, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 69 | 0x20, 0x10, 0x00, 0x00, 0xb4, 0x18, 0x00, 0x40, 0x00, 0x4a, 0x00, 0x40, 70 | 0x4c, 0x4a, 0x00, 0x40, 0x91, 0xfc, 0xff, 0x12, 0xc1, 0xe0, 0x51, 0xf7, 71 | 0xff, 0x09, 0x71, 0xc9, 0x61, 0xd9, 0x51, 0xe9, 0x41, 0xf9, 0x31, 0x90, 72 | 0x11, 0xc0, 0x3b, 0xf2, 0x7d, 0x03, 0xc2, 0xd1, 0x10, 0x1a, 0x55, 0x40, 73 | 0xef, 0x11, 0x79, 0x05, 0xdd, 0x02, 0x3d, 0x0c, 0x42, 0xa0, 0x04, 0xe0, 74 | 0x2e, 0x20, 0x01, 0xc8, 0xff, 0xc0, 0x00, 0x00, 0x22, 0x0c, 0x00, 0x0c, 75 | 0x15, 0x0c, 0x26, 0x8d, 0x05, 0x20, 0x86, 0x93, 0xda, 0x28, 0x81, 0xe9, 76 | 0xff, 0x41, 0xe6, 0xff, 0x1a, 0x88, 0x59, 0x08, 0x81, 0xe8, 0xff, 0x3d, 77 | 0x01, 0x10, 0x88, 0x80, 0x62, 0x68, 0x00, 0x40, 0x22, 0x11, 0x01, 0xbd, 78 | 0xff, 0xc0, 0x00, 0x00, 0x31, 0xe2, 0xff, 0x81, 0xe2, 0xff, 0x1a, 0x33, 79 | 0x58, 0x03, 0x31, 0xde, 0xff, 0x22, 0x0c, 0x00, 0x1a, 0x88, 0x1a, 0x33, 80 | 0x68, 0x08, 0x78, 0x03, 0xcc, 0x62, 0x52, 0x4c, 0x00, 0x5d, 0x06, 0x06, 81 | 0x01, 0x00, 0x0c, 0x02, 0x22, 0x4c, 0x00, 0x61, 0xd8, 0xff, 0x3d, 0x07, 82 | 0x1a, 0x66, 0x52, 0x66, 0x00, 0x0c, 0x84, 0x10, 0x21, 0x20, 0x01, 0xd7, 83 | 0xff, 0xc0, 0x00, 0x00, 0x81, 0xd3, 0xff, 0x1a, 0x88, 0x58, 0x08, 0xda, 84 | 0xd5, 0x2d, 0x0d, 0x01, 0xd4, 0xff, 0xc0, 0x00, 0x00, 0x41, 0xcc, 0xff, 85 | 0x10, 0x31, 0x20, 0x40, 0x2d, 0x11, 0x01, 0xd1, 0xff, 0xc0, 0x00, 0x00, 86 | 0x2d, 0x0f, 0x01, 0xce, 0xff, 0xc0, 0x00, 0x00, 0x2d, 0x0e, 0x3d, 0x0c, 87 | 0x0c, 0x44, 0x01, 0xcc, 0xff, 0xc0, 0x00, 0x00, 0x91, 0xc8, 0xff, 0x9a, 88 | 0x11, 0x08, 0x71, 0xc8, 0x61, 0xd8, 0x51, 0xe8, 0x41, 0xf8, 0x31, 0x12, 89 | 0xc1, 0x20, 0x0d, 0xf0, 0x04, 0x09, 0x00, 0x60, 0x00, 0x09, 0x00, 0x60, 90 | 0x20, 0x4e, 0x00, 0x00, 0xcc, 0x2e, 0x00, 0x40, 0x21, 0xfc, 0xff, 0x12, 91 | 0xc1, 0xf0, 0x09, 0x31, 0x0c, 0x03, 0xc0, 0x20, 0x00, 0x39, 0x02, 0x21, 92 | 0xf9, 0xff, 0x3c, 0x83, 0xc0, 0x20, 0x00, 0x48, 0x02, 0x30, 0x34, 0x20, 93 | 0xc0, 0x20, 0x00, 0x39, 0x02, 0xc0, 0x20, 0x00, 0x48, 0x02, 0x7c, 0x93, 94 | 0x30, 0x34, 0x10, 0x0c, 0x44, 0x40, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x39, 95 | 0x02, 0xc0, 0x20, 0x00, 0x48, 0x02, 0x0c, 0x13, 0x30, 0x34, 0x20, 0xc0, 96 | 0x20, 0x00, 0x39, 0x02, 0x21, 0xed, 0xff, 0x01, 0xed, 0xff, 0xc0, 0x00, 97 | 0x00, 0xc6, 0xfc, 0xff, 0xdc, 0x11, 0x00, 0x60, 0x00, 0x5a, 0x5a, 0x5a, 98 | 0x78, 0x56, 0x34, 0x12, 0x0a, 0x83, 0xfe, 0x3f, 0x1e, 0x83, 0xfe, 0x3f, 99 | 0x30, 0x83, 0xfe, 0x3f, 0x3e, 0x83, 0xfe, 0x3f, 0x4d, 0x83, 0xfe, 0x3f, 100 | 0x50, 0xc3, 0x00, 0x00, 0x5c, 0x83, 0xfe, 0x3f, 0x62, 0x83, 0xfe, 0x3f, 101 | 0x51, 0xf5, 0xff, 0x71, 0xf5, 0xff, 0xc0, 0x20, 0x00, 0x48, 0x05, 0x12, 102 | 0xc1, 0xf0, 0x09, 0x31, 0xc9, 0x21, 0xd9, 0x11, 0x70, 0x84, 0x10, 0x40, 103 | 0x60, 0x74, 0x77, 0x18, 0x06, 0xc0, 0x20, 0x00, 0x49, 0x05, 0x0c, 0x06, 104 | 0x52, 0x03, 0x00, 0x27, 0x65, 0x6e, 0xc1, 0xee, 0xff, 0xd1, 0xee, 0xff, 105 | 0xb6, 0x36, 0x29, 0x42, 0xaf, 0xfb, 0x40, 0x55, 0x10, 0x52, 0x43, 0x00, 106 | 0x05, 0xe5, 0xff, 0x31, 0xe7, 0xff, 0x21, 0xe4, 0xff, 0xd0, 0x4d, 0x20, 107 | 0xc0, 0x20, 0x00, 0x32, 0x62, 0x00, 0x21, 0xe4, 0xff, 0x3d, 0x0c, 0x01, 108 | 0x64, 0xff, 0xc0, 0x00, 0x00, 0x86, 0x0d, 0x00, 0x00, 0x21, 0xde, 0xff, 109 | 0x1b, 0x66, 0x60, 0x60, 0x74, 0x20, 0x66, 0x20, 0x21, 0xdb, 0xff, 0x3d, 110 | 0x0c, 0xc0, 0x20, 0x00, 0x69, 0x02, 0x21, 0xde, 0xff, 0x61, 0xde, 0xff, 111 | 0xd0, 0x5d, 0x20, 0x01, 0x5a, 0xff, 0xc0, 0x00, 0x00, 0xd1, 0xdc, 0xff, 112 | 0x0c, 0xac, 0x2d, 0x0d, 0x0b, 0xcc, 0x01, 0xbd, 0xff, 0xc0, 0x00, 0x00, 113 | 0x56, 0x2c, 0xff, 0x10, 0x11, 0x20, 0xc5, 0xee, 0xff, 0x31, 0xd8, 0xff, 114 | 0xb6, 0x36, 0x0b, 0x21, 0xd6, 0xff, 0x01, 0x50, 0xff, 0xc0, 0x00, 0x00, 115 | 0x06, 0x0e, 0x00, 0x21, 0xcb, 0xff, 0x1b, 0x66, 0x60, 0x60, 0x74, 0x20, 116 | 0x66, 0x20, 0x21, 0xc7, 0xff, 0x51, 0xcb, 0xff, 0xc0, 0x20, 0x00, 0x62, 117 | 0x62, 0x00, 0x21, 0xca, 0xff, 0x61, 0xca, 0xff, 0xc2, 0xa0, 0x0a, 0x01, 118 | 0x46, 0xff, 0xc0, 0x00, 0x00, 0xd1, 0xc8, 0xff, 0x2d, 0x0d, 0x0b, 0xcc, 119 | 0x01, 0xaa, 0xff, 0xc0, 0x00, 0x00, 0x56, 0x2c, 0xff, 0x86, 0xeb, 0xff, 120 | 0x08, 0x31, 0xc8, 0x21, 0xd8, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 121 | 0x1c, 0x02, 0x00, 0x60, 0x80, 0x85, 0xfe, 0x3f, 0x00, 0x80, 0x28, 0x00, 122 | 0x08, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x60, 0x00, 0x00, 0x10, 0x00, 123 | 0x41, 0xfa, 0xff, 0x0c, 0x45, 0xc0, 0x20, 0x00, 0x68, 0x04, 0x30, 0x30, 124 | 0x74, 0x50, 0x56, 0x20, 0xc0, 0x20, 0x00, 0x59, 0x04, 0x42, 0xa0, 0x00, 125 | 0xf6, 0x62, 0x08, 0x41, 0xf4, 0xff, 0x40, 0x22, 0xa0, 0x42, 0x22, 0x00, 126 | 0x21, 0x51, 0xff, 0xb6, 0x23, 0x11, 0x30, 0x21, 0x41, 0x0b, 0x53, 0x0b, 127 | 0x22, 0x80, 0x65, 0x11, 0xc0, 0x22, 0x11, 0x2a, 0x26, 0x50, 0x22, 0x80, 128 | 0x31, 0xed, 0xff, 0x30, 0x44, 0x20, 0x31, 0xec, 0xff, 0x20, 0x24, 0x20, 129 | 0xc0, 0x20, 0x00, 0x29, 0x03, 0x21, 0xea, 0xff, 0x31, 0xeb, 0xff, 0xc0, 130 | 0x20, 0x00, 0x39, 0x02, 0xc0, 0x20, 0x00, 0x38, 0x02, 0x56, 0x73, 0xff, 131 | 0x0d, 0xf0, 0x00, 0x00, 0x28, 0x00, 0xf0, 0x3f, 0x00, 0x08, 0x00, 0x60, 132 | 0x04, 0x08, 0x00, 0x60, 0x08, 0x08, 0x00, 0x60, 0x0c, 0x08, 0x00, 0x60, 133 | 0x10, 0x08, 0x00, 0x60, 0x28, 0x08, 0x00, 0x60, 0x2c, 0x08, 0x00, 0x60, 134 | 0x21, 0xf8, 0xff, 0x12, 0xc1, 0xf0, 0xc0, 0x20, 0x00, 0x42, 0x22, 0x00, 135 | 0x32, 0xa0, 0x02, 0x02, 0x61, 0x03, 0x30, 0x34, 0x20, 0xc0, 0x20, 0x00, 136 | 0x39, 0x02, 0x21, 0xf2, 0xff, 0x32, 0xac, 0xff, 0xc0, 0x20, 0x00, 0x48, 137 | 0x02, 0x30, 0x34, 0x10, 0x41, 0xf0, 0xff, 0xc0, 0x20, 0x00, 0x39, 0x02, 138 | 0xc0, 0x20, 0x00, 0x58, 0x04, 0x22, 0xae, 0xcf, 0x2c, 0x03, 0x20, 0x55, 139 | 0x10, 0x30, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x59, 0x04, 0x41, 0xe9, 0xff, 140 | 0xc0, 0x20, 0x00, 0x58, 0x04, 0x20, 0x55, 0x10, 0x30, 0x55, 0x20, 0xc0, 141 | 0x20, 0x00, 0x59, 0x04, 0x41, 0xe6, 0xff, 0xc0, 0x20, 0x00, 0x58, 0x04, 142 | 0x20, 0x55, 0x10, 0x30, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x59, 0x04, 0x41, 143 | 0xe2, 0xff, 0xc0, 0x20, 0x00, 0x58, 0x04, 0x20, 0x55, 0x10, 0x30, 0x35, 144 | 0x20, 0xc0, 0x20, 0x00, 0x39, 0x04, 0x31, 0xde, 0xff, 0x42, 0xa1, 0x00, 145 | 0xc0, 0x20, 0x00, 0x58, 0x03, 0x20, 0x55, 0x10, 0x40, 0x55, 0x20, 0xc0, 146 | 0x20, 0x00, 0x59, 0x03, 0x31, 0xda, 0xff, 0xc0, 0x20, 0x00, 0x58, 0x03, 147 | 0x20, 0x25, 0x10, 0x40, 0x42, 0x20, 0x0c, 0x42, 0xc0, 0x20, 0x00, 0x49, 148 | 0x03, 0x3d, 0x02, 0x05, 0xed, 0xff, 0x08, 0x31, 0x12, 0xc1, 0x10, 0x0d, 149 | 0xf0, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x75, 0x83, 0xfe, 0x3f, 150 | 0x18, 0x03, 0x00, 0x60, 0x97, 0x83, 0xfe, 0x3f, 0xa4, 0x83, 0xfe, 0x3f, 151 | 0xaa, 0x83, 0xfe, 0x3f, 0xb2, 0x83, 0xfe, 0x3f, 0xb8, 0x83, 0xfe, 0x3f, 152 | 0xbe, 0x83, 0xfe, 0x3f, 0xcb, 0x83, 0xfe, 0x3f, 0xcf, 0x83, 0xfe, 0x3f, 153 | 0xd4, 0x83, 0xfe, 0x3f, 0xd8, 0x83, 0xfe, 0x3f, 0xdd, 0x83, 0xfe, 0x3f, 154 | 0x18, 0x85, 0xfe, 0x3f, 0xf5, 0x83, 0xfe, 0x3f, 0x06, 0x84, 0xfe, 0x3f, 155 | 0x0c, 0x84, 0xfe, 0x3f, 0x4d, 0x84, 0xfe, 0x3f, 0x13, 0x84, 0xfe, 0x3f, 156 | 0x25, 0x84, 0xfe, 0x3f, 0x2b, 0x84, 0xfe, 0x3f, 0x31, 0x84, 0xfe, 0x3f, 157 | 0x45, 0x84, 0xfe, 0x3f, 0x4b, 0x84, 0xfe, 0x3f, 0x52, 0x84, 0xfe, 0x3f, 158 | 0x2d, 0x84, 0xfe, 0x3f, 0xff, 0xe0, 0xff, 0xff, 0x00, 0xfc, 0x10, 0x40, 159 | 0x04, 0x80, 0xfe, 0x3f, 0x00, 0x80, 0xfe, 0x3f, 0x40, 0x85, 0xfe, 0x3f, 160 | 0x34, 0x08, 0x00, 0x60, 0x18, 0x08, 0x00, 0x60, 0x38, 0x08, 0x00, 0x60, 161 | 0x14, 0x08, 0x00, 0x60, 0x3c, 0x08, 0x00, 0x60, 0x40, 0x08, 0x00, 0x60, 162 | 0x1c, 0x08, 0x00, 0x60, 0x20, 0x08, 0x00, 0x60, 0x24, 0x08, 0x00, 0x60, 163 | 0x30, 0x08, 0x00, 0x60, 0x69, 0x84, 0xfe, 0x3f, 0x14, 0x03, 0x00, 0x60, 164 | 0xff, 0xff, 0x00, 0x00, 0x7a, 0x84, 0xfe, 0x3f, 0x9b, 0x84, 0xfe, 0x3f, 165 | 0xb2, 0x84, 0xfe, 0x3f, 0xc9, 0x84, 0xfe, 0x3f, 0xd5, 0x84, 0xfe, 0x3f, 166 | 0xe9, 0x84, 0xfe, 0x3f, 0xfa, 0x84, 0xfe, 0x3f, 0xfc, 0x84, 0xfe, 0x3f, 167 | 0xfe, 0x84, 0xfe, 0x3f, 0xec, 0x48, 0x00, 0x40, 0xa4, 0x18, 0x00, 0x40, 168 | 0xf0, 0x4c, 0x00, 0x40, 0x92, 0xa0, 0xb0, 0x21, 0xc7, 0xff, 0x90, 0x11, 169 | 0xc0, 0x02, 0x61, 0x2b, 0xc2, 0x61, 0x2a, 0xd2, 0x61, 0x29, 0x01, 0xaa, 170 | 0xfe, 0xc0, 0x00, 0x00, 0x21, 0xc3, 0xff, 0xc0, 0x20, 0x00, 0x38, 0x02, 171 | 0x30, 0x30, 0x25, 0x26, 0x43, 0x21, 0xc0, 0x20, 0x00, 0x38, 0x02, 0x30, 172 | 0x30, 0x25, 0x26, 0x53, 0x16, 0xc0, 0x20, 0x00, 0x32, 0x22, 0x00, 0x30, 173 | 0x30, 0x25, 0x26, 0x63, 0x0a, 0xc0, 0x20, 0x00, 0x28, 0x02, 0x20, 0x20, 174 | 0x25, 0x66, 0x72, 0x02, 0x85, 0xe1, 0xff, 0x32, 0xa0, 0x88, 0x30, 0x31, 175 | 0x80, 0x42, 0xa0, 0x08, 0x22, 0xa0, 0x00, 0x01, 0x98, 0xfe, 0xc0, 0x00, 176 | 0x00, 0x21, 0xb2, 0xff, 0x01, 0x97, 0xfe, 0xc0, 0x00, 0x00, 0x22, 0x21, 177 | 0x22, 0x20, 0x28, 0x35, 0x26, 0x12, 0x1c, 0xe6, 0x22, 0x05, 0x8c, 0xe2, 178 | 0x46, 0x0b, 0x00, 0x00, 0x26, 0x22, 0x18, 0x0c, 0xf3, 0x37, 0x12, 0x1b, 179 | 0x46, 0x08, 0x00, 0x00, 0x21, 0xaa, 0xff, 0x06, 0x05, 0x00, 0x00, 0x00, 180 | 0x21, 0xa9, 0xff, 0x06, 0x03, 0x00, 0x00, 0x00, 0x21, 0xa8, 0xff, 0x06, 181 | 0x01, 0x00, 0x00, 0x00, 0x21, 0xa7, 0xff, 0x01, 0x87, 0xfe, 0xc0, 0x00, 182 | 0x00, 0x21, 0xa5, 0xff, 0x01, 0x85, 0xfe, 0xc0, 0x00, 0x00, 0x22, 0x01, 183 | 0x8a, 0x26, 0x12, 0x0a, 0xac, 0x02, 0x26, 0x22, 0x0b, 0x26, 0x32, 0x0f, 184 | 0xc6, 0x04, 0x00, 0x21, 0xa1, 0xff, 0x46, 0x05, 0x00, 0x21, 0xa0, 0xff, 185 | 0xc6, 0x03, 0x00, 0x00, 0x21, 0xa0, 0xff, 0x06, 0x02, 0x00, 0x00, 0x0c, 186 | 0x02, 0x22, 0x41, 0x8a, 0x21, 0x9a, 0xff, 0x01, 0x78, 0xfe, 0xc0, 0x00, 187 | 0x00, 0x21, 0x9b, 0xff, 0x01, 0x76, 0xfe, 0xc0, 0x00, 0x00, 0x21, 0x8e, 188 | 0xff, 0xc0, 0x20, 0x00, 0x28, 0x02, 0x20, 0x20, 0x25, 0x66, 0x52, 0x08, 189 | 0x22, 0x01, 0x8a, 0x01, 0xbe, 0xff, 0xc0, 0x00, 0x00, 0x22, 0x21, 0x22, 190 | 0x0c, 0x93, 0x20, 0x2c, 0x35, 0x27, 0xb3, 0x02, 0x46, 0x27, 0x00, 0x31, 191 | 0x91, 0xff, 0x30, 0x22, 0xa0, 0x28, 0x02, 0xa0, 0x02, 0x00, 0x00, 0x21, 192 | 0x8f, 0xff, 0x86, 0x23, 0x00, 0x21, 0x8f, 0xff, 0x3c, 0xcc, 0x01, 0x65, 193 | 0xfe, 0xc0, 0x00, 0x00, 0x06, 0x23, 0x00, 0x00, 0x00, 0x21, 0x8c, 0xff, 194 | 0x31, 0x8d, 0xff, 0xc2, 0xa0, 0xfc, 0x01, 0x60, 0xfe, 0xc0, 0x00, 0x00, 195 | 0x06, 0x1e, 0x00, 0x21, 0x8a, 0xff, 0x31, 0x88, 0xff, 0x86, 0x03, 0x00, 196 | 0x21, 0x89, 0xff, 0x31, 0x86, 0xff, 0x06, 0x06, 0x00, 0x21, 0x85, 0xff, 197 | 0x31, 0x87, 0xff, 0x01, 0x58, 0xfe, 0xc0, 0x00, 0x00, 0xc2, 0xa1, 0xfc, 198 | 0x06, 0x15, 0x00, 0x00, 0x21, 0x82, 0xff, 0x31, 0x82, 0xff, 0x01, 0x53, 199 | 0xfe, 0xc0, 0x00, 0x00, 0xc2, 0xa3, 0xfc, 0x46, 0x10, 0x00, 0x21, 0x7f, 200 | 0xff, 0x31, 0x7d, 0xff, 0xc2, 0xa7, 0xfc, 0x01, 0x4e, 0xfe, 0xc0, 0x00, 201 | 0x00, 0xc6, 0x0b, 0x00, 0x21, 0x7c, 0xff, 0x31, 0x79, 0xff, 0x01, 0x4a, 202 | 0xfe, 0xc0, 0x00, 0x00, 0xc1, 0x61, 0xff, 0x46, 0x07, 0x00, 0x00, 0x21, 203 | 0x78, 0xff, 0x01, 0x46, 0xfe, 0xc0, 0x00, 0x00, 0x06, 0xb4, 0x00, 0x00, 204 | 0x00, 0x21, 0x75, 0xff, 0x31, 0x6b, 0xff, 0xc2, 0xa0, 0x7c, 0x01, 0x41, 205 | 0xfe, 0xc0, 0x00, 0x00, 0x3b, 0xdc, 0x40, 0xdd, 0x11, 0x32, 0xa0, 0x90, 206 | 0x3a, 0x31, 0x0c, 0x44, 0x2d, 0x0d, 0x01, 0x3b, 0xfe, 0xc0, 0x00, 0x00, 207 | 0x42, 0x01, 0x90, 0x0c, 0x22, 0x0c, 0x13, 0x40, 0x32, 0x93, 0xca, 0x23, 208 | 0x32, 0xa0, 0x80, 0x40, 0x22, 0x11, 0x3a, 0x31, 0x0c, 0x84, 0x01, 0x34, 209 | 0xfe, 0xc0, 0x00, 0x00, 0x22, 0x01, 0x81, 0x20, 0x20, 0x44, 0x66, 0x72, 210 | 0x08, 0x22, 0x01, 0x80, 0x20, 0x20, 0x14, 0x66, 0x32, 0x32, 0x22, 0xa0, 211 | 0x80, 0x32, 0xa0, 0xff, 0x10, 0x22, 0x80, 0x42, 0xa0, 0x08, 0x01, 0x7b, 212 | 0xff, 0xc0, 0x00, 0x00, 0x32, 0x11, 0x40, 0x7c, 0xc2, 0x20, 0x23, 0x10, 213 | 0x31, 0x5c, 0xff, 0x30, 0x22, 0x10, 0x32, 0xa7, 0x00, 0x30, 0x22, 0x20, 214 | 0x32, 0xa0, 0x80, 0x22, 0x51, 0x40, 0x1a, 0x33, 0x2d, 0x0c, 0x85, 0x93, 215 | 0xff, 0x41, 0x58, 0xff, 0x31, 0x57, 0xff, 0x48, 0x04, 0x21, 0x54, 0xff, 216 | 0x01, 0x48, 0xfe, 0xc0, 0x00, 0x00, 0x3d, 0x01, 0x42, 0xa0, 0x80, 0x22, 217 | 0xdd, 0xd0, 0x01, 0x1b, 0xfe, 0xc0, 0x00, 0x00, 0x22, 0x01, 0x77, 0x42, 218 | 0xa0, 0xfd, 0x0b, 0x32, 0x30, 0x30, 0x74, 0x37, 0xb4, 0x02, 0x06, 0x3c, 219 | 0x00, 0x22, 0xc2, 0x60, 0x20, 0x20, 0x74, 0x0c, 0xf3, 0x27, 0xb3, 0x02, 220 | 0x46, 0x22, 0x00, 0x31, 0x4a, 0xff, 0x30, 0x22, 0xa0, 0x28, 0x02, 0x32, 221 | 0xae, 0xcf, 0xa0, 0x02, 0x00, 0x21, 0x47, 0xff, 0x86, 0x0b, 0x00, 0x21, 222 | 0x47, 0xff, 0xc0, 0x20, 0x00, 0x48, 0x02, 0x30, 0x34, 0x10, 0x3c, 0x04, 223 | 0x40, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x39, 0x02, 0x0c, 0x13, 0xc6, 0x19, 224 | 0x00, 0x21, 0x41, 0xff, 0x86, 0x03, 0x00, 0x21, 0x41, 0xff, 0x06, 0xf7, 225 | 0xff, 0x21, 0x40, 0xff, 0x86, 0x00, 0x00, 0x21, 0x40, 0xff, 0xc0, 0x20, 226 | 0x00, 0x48, 0x02, 0x30, 0x34, 0x10, 0x46, 0xf5, 0xff, 0x21, 0x3d, 0xff, 227 | 0x86, 0xf0, 0xff, 0x21, 0x3d, 0xff, 0x06, 0xef, 0xff, 0x21, 0x3c, 0xff, 228 | 0x86, 0xed, 0xff, 0x21, 0xe3, 0xfe, 0x06, 0xec, 0xff, 0x21, 0xe2, 0xfe, 229 | 0x86, 0xea, 0xff, 0x21, 0x39, 0xff, 0x06, 0xe9, 0xff, 0x21, 0xda, 0xfe, 230 | 0x86, 0xe7, 0xff, 0x21, 0xda, 0xfe, 0x06, 0xe6, 0xff, 0x21, 0xd9, 0xfe, 231 | 0x86, 0xe4, 0xff, 0x21, 0xd9, 0xfe, 0x06, 0xe3, 0xff, 0x21, 0x32, 0xff, 232 | 0x01, 0xf0, 0xfd, 0xc0, 0x00, 0x00, 0x32, 0xa0, 0x00, 0x41, 0x31, 0xff, 233 | 0x21, 0x30, 0xff, 0xc0, 0x20, 0x00, 0x42, 0x62, 0x00, 0x66, 0x13, 0x3d, 234 | 0x01, 0x3a, 0xff, 0xc0, 0x00, 0x00, 0x32, 0x01, 0x77, 0x30, 0x30, 0x34, 235 | 0x37, 0xd2, 0x2e, 0x21, 0x2b, 0xff, 0x01, 0xe5, 0xfd, 0xc0, 0x00, 0x00, 236 | 0x22, 0xa0, 0x82, 0x2a, 0x21, 0x85, 0x15, 0x00, 0xdd, 0x02, 0x21, 0x27, 237 | 0xff, 0x3d, 0x0d, 0x01, 0xe0, 0xfd, 0xc0, 0x00, 0x00, 0x2d, 0x0d, 0x45, 238 | 0x7c, 0xff, 0x66, 0x12, 0x08, 0x21, 0x23, 0xff, 0x01, 0xdc, 0xfd, 0xc0, 239 | 0x00, 0x00, 0x22, 0x01, 0x81, 0x32, 0xa0, 0x60, 0x30, 0x32, 0x10, 0x26, 240 | 0xc3, 0x0a, 0x32, 0xaf, 0x80, 0x37, 0x02, 0x17, 0xc6, 0x1b, 0x00, 0x00, 241 | 0x00, 0x22, 0xa0, 0x82, 0x2a, 0x21, 0xc5, 0x11, 0x00, 0xdd, 0x02, 0x21, 242 | 0x1a, 0xff, 0x06, 0x09, 0x00, 0x00, 0x00, 0x00, 0x32, 0x01, 0x80, 0x27, 243 | 0x63, 0x0a, 0x32, 0xa0, 0x80, 0x1a, 0x33, 0x5b, 0x23, 0x46, 0x02, 0x00, 244 | 0x00, 0x32, 0xa0, 0x80, 0x10, 0x33, 0x80, 0x22, 0xc3, 0x02, 0x45, 0x0f, 245 | 0x00, 0xdd, 0x02, 0x21, 0x11, 0xff, 0x01, 0xc7, 0xfd, 0xc0, 0x00, 0x00, 246 | 0x21, 0x0c, 0xff, 0x3d, 0x0d, 0x01, 0xc4, 0xfd, 0xc0, 0x00, 0x00, 0x2d, 247 | 0x0d, 0x45, 0x75, 0xff, 0x26, 0x12, 0x02, 0x46, 0x30, 0x00, 0x22, 0x01, 248 | 0x81, 0x32, 0xa0, 0x60, 0x30, 0x32, 0x10, 0x66, 0xc3, 0x02, 0x86, 0x2c, 249 | 0x00, 0x32, 0xaf, 0x80, 0x37, 0x02, 0x02, 0x46, 0x2a, 0x00, 0x06, 0x22, 250 | 0x00, 0x00, 0x00, 0x21, 0x03, 0xff, 0x01, 0xb8, 0xfd, 0xc0, 0x00, 0x00, 251 | 0x32, 0x01, 0x80, 0x0c, 0x12, 0x30, 0x30, 0x24, 0x0b, 0x53, 0x0c, 0x04, 252 | 0x50, 0x42, 0x83, 0x40, 0x40, 0x74, 0xcc, 0x64, 0x52, 0xc3, 0xfc, 0x50, 253 | 0x42, 0x83, 0x8c, 0xf4, 0x21, 0xfb, 0xfe, 0x01, 0xaf, 0xfd, 0xc0, 0x00, 254 | 0x00, 0x21, 0xd0, 0xfd, 0x06, 0x13, 0x00, 0x00, 0x00, 0x30, 0x42, 0x83, 255 | 0x56, 0x84, 0x00, 0x32, 0xc3, 0xfb, 0x30, 0x24, 0x93, 0x16, 0x02, 0x05, 256 | 0x21, 0xf4, 0xfe, 0x01, 0xa7, 0xfd, 0xc0, 0x00, 0x00, 0x32, 0x21, 0x22, 257 | 0x22, 0xa0, 0x7c, 0x30, 0x3c, 0x35, 0x32, 0xc3, 0xfe, 0xf6, 0x83, 0x1d, 258 | 0x22, 0xa0, 0x01, 0x00, 0x13, 0x40, 0x00, 0x32, 0xa1, 0x42, 0xa0, 0xd8, 259 | 0x22, 0xa1, 0xfc, 0x47, 0x83, 0x0b, 0x30, 0x30, 0x24, 0x22, 0xa0, 0xfc, 260 | 0x42, 0xa0, 0x7c, 0x30, 0x24, 0x83, 0x50, 0x22, 0x11, 0x22, 0xd2, 0x30, 261 | 0xc5, 0x6a, 0xff, 0x66, 0x12, 0x1d, 0x32, 0xa0, 0x80, 0xc0, 0x2c, 0x20, 262 | 0x3a, 0x31, 0x05, 0x87, 0xff, 0xc6, 0x03, 0x00, 0x00, 0x32, 0x21, 0x20, 263 | 0x21, 0xe0, 0xfe, 0x30, 0x30, 0x14, 0x01, 0x91, 0xfd, 0xc0, 0x00, 0x00, 264 | 0x02, 0x21, 0x2b, 0x92, 0xa0, 0xb0, 0xc2, 0x21, 0x2a, 0xd2, 0x21, 0x29, 265 | 0x9a, 0x11, 0x0d, 0xf0, 0x42, 0x02, 0x02, 0x32, 0x02, 0x01, 0x00, 0x44, 266 | 0x11, 0x22, 0x02, 0x00, 0x80, 0x33, 0x11, 0x30, 0x34, 0x20, 0x20, 0x23, 267 | 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x80, 0xfe, 0x3f, 0xfc, 0x02, 0x00, 0x00, 268 | 0xf8, 0x02, 0x00, 0x00, 0x1c, 0x4b, 0x00, 0x40, 0xb4, 0x18, 0x00, 0x40, 269 | 0x1c, 0x04, 0x12, 0xc1, 0xa0, 0xd9, 0xd1, 0xe9, 0xe1, 0xf9, 0xf1, 0x3d, 270 | 0x01, 0xc9, 0xc1, 0x09, 0xb1, 0x01, 0xf9, 0xff, 0xcd, 0x02, 0xc0, 0x00, 271 | 0x00, 0x56, 0x72, 0x1c, 0x32, 0xa0, 0xe9, 0x22, 0x01, 0x00, 0xf8, 0x11, 272 | 0x30, 0x22, 0xc0, 0x32, 0x01, 0x01, 0x39, 0xa1, 0x56, 0x42, 0x1b, 0x3d, 273 | 0x01, 0x1c, 0x04, 0x02, 0x01, 0x08, 0x22, 0x01, 0x0a, 0xe2, 0x01, 0x0b, 274 | 0xd2, 0x01, 0x0f, 0x80, 0xee, 0x11, 0x80, 0xdd, 0x11, 0x20, 0xee, 0x20, 275 | 0x22, 0x01, 0x09, 0x80, 0xee, 0x11, 0x20, 0xee, 0x20, 0x22, 0x01, 0x0e, 276 | 0x80, 0xee, 0x11, 0x00, 0xee, 0x20, 0x20, 0xdd, 0x20, 0x02, 0x01, 0x0c, 277 | 0x22, 0x01, 0x0d, 0x80, 0xdd, 0x11, 0x20, 0xdd, 0x20, 0x80, 0xdd, 0x11, 278 | 0x00, 0xdd, 0x20, 0x01, 0xe2, 0xff, 0x22, 0xcc, 0x10, 0xc0, 0x00, 0x00, 279 | 0x56, 0x82, 0x16, 0xf9, 0x91, 0xe2, 0x61, 0x13, 0x22, 0xcc, 0x20, 0x08, 280 | 0xa1, 0x22, 0x61, 0x12, 0x16, 0x50, 0x21, 0xfd, 0x01, 0xc2, 0xa0, 0xef, 281 | 0x1c, 0x0a, 0xd2, 0x61, 0x14, 0x2d, 0x0e, 0x0c, 0x07, 0x72, 0x61, 0x11, 282 | 0xed, 0x01, 0x0d, 0x02, 0x0c, 0x17, 0x62, 0x21, 0x11, 0x82, 0x21, 0x14, 283 | 0x60, 0x6a, 0xc0, 0x60, 0x60, 0x74, 0x67, 0xb8, 0x01, 0x0c, 0x07, 0x16, 284 | 0x47, 0x1f, 0x0c, 0x39, 0x67, 0x09, 0x1c, 0xa6, 0x16, 0x4f, 0x0c, 0x0d, 285 | 0x1b, 0xdd, 0x22, 0x0f, 0x00, 0x22, 0x40, 0x00, 0x1b, 0xff, 0x1b, 0x00, 286 | 0xc0, 0xc2, 0x30, 0xc0, 0xc0, 0x74, 0x67, 0x9d, 0xea, 0x46, 0x0d, 0x00, 287 | 0xbc, 0x26, 0x2d, 0x00, 0x60, 0x92, 0x41, 0xa6, 0x19, 0x29, 0x0c, 0x0d, 288 | 0x1b, 0xdd, 0x42, 0x0f, 0x01, 0x02, 0x0f, 0x03, 0x32, 0x0f, 0x00, 0xc0, 289 | 0x00, 0x30, 0xc2, 0x0f, 0x02, 0x40, 0x33, 0x30, 0x30, 0xcc, 0x30, 0x00, 290 | 0xcc, 0x30, 0xc0, 0xc0, 0x74, 0x08, 0x0f, 0x09, 0x02, 0x4b, 0xff, 0x4b, 291 | 0x22, 0x97, 0x9d, 0xd7, 0x0d, 0x02, 0x16, 0x97, 0x19, 0x60, 0x28, 0xc0, 292 | 0x20, 0x24, 0x41, 0x22, 0x61, 0x10, 0x79, 0x71, 0x32, 0x21, 0x10, 0x42, 293 | 0x21, 0x11, 0x0c, 0x05, 0x4a, 0x68, 0x40, 0x40, 0x74, 0x62, 0xc6, 0xf0, 294 | 0x60, 0x60, 0x34, 0x70, 0x45, 0x93, 0x42, 0x61, 0x11, 0x70, 0x68, 0x83, 295 | 0x69, 0x81, 0xa6, 0x13, 0x4c, 0x0c, 0x0d, 0x09, 0x61, 0x22, 0x21, 0x12, 296 | 0x3d, 0x01, 0x01, 0xac, 0xff, 0x1c, 0x04, 0xc0, 0x00, 0x00, 0x56, 0x22, 297 | 0x09, 0x22, 0x21, 0x12, 0x0c, 0x00, 0x22, 0xc2, 0x10, 0x22, 0x61, 0x12, 298 | 0x1b, 0x30, 0xea, 0x20, 0x22, 0x02, 0x00, 0x30, 0x00, 0x74, 0xc0, 0xc2, 299 | 0x30, 0xc0, 0xc0, 0x74, 0x66, 0xb0, 0xec, 0x28, 0x61, 0x3d, 0x01, 0x01, 300 | 0xa2, 0xff, 0x1c, 0x04, 0xc0, 0x00, 0x00, 0x1b, 0xdd, 0x08, 0x61, 0x22, 301 | 0x21, 0x10, 0x02, 0xc0, 0x10, 0x09, 0x61, 0xd7, 0x92, 0xb6, 0x38, 0x71, 302 | 0x09, 0x61, 0x9c, 0xb3, 0x22, 0x21, 0x12, 0x3d, 0x01, 0x01, 0x98, 0xff, 303 | 0x1c, 0x04, 0xc0, 0x00, 0x00, 0x08, 0x61, 0x56, 0x12, 0x04, 0x22, 0x21, 304 | 0x12, 0xfd, 0x01, 0x22, 0xc2, 0x10, 0x22, 0x61, 0x12, 0x68, 0x81, 0x0c, 305 | 0x33, 0x60, 0x60, 0x74, 0x67, 0x83, 0x02, 0x06, 0x3e, 0x00, 0xa6, 0x16, 306 | 0x16, 0x0c, 0x0d, 0x1b, 0xdd, 0x22, 0x0f, 0x00, 0x22, 0x40, 0x00, 0x1b, 307 | 0xff, 0x1b, 0x00, 0xc0, 0xc2, 0x30, 0xc0, 0xc0, 0x74, 0x67, 0x9d, 0xea, 308 | 0x38, 0xa1, 0x1c, 0x0a, 0x66, 0x13, 0x19, 0x42, 0x01, 0x0f, 0xc0, 0x44, 309 | 0xc0, 0x16, 0xc4, 0x0b, 0x0c, 0x12, 0xc8, 0xc1, 0xd8, 0xd1, 0xe8, 0xe1, 310 | 0xf8, 0xf1, 0x08, 0xb1, 0x12, 0xc1, 0x60, 0x0d, 0xf0, 0x02, 0x21, 0x11, 311 | 0x0a, 0x06, 0x00, 0xda, 0xc0, 0xd0, 0xd0, 0x74, 0xb6, 0x8d, 0x46, 0x92, 312 | 0x0f, 0x06, 0x32, 0x0f, 0x02, 0x82, 0x0f, 0x07, 0x22, 0x0f, 0x03, 0x80, 313 | 0x88, 0x11, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x90, 0x88, 0x20, 0x32, 314 | 0x0f, 0x01, 0x80, 0x22, 0x11, 0x92, 0x0f, 0x05, 0x80, 0x88, 0x11, 0x90, 315 | 0x88, 0x20, 0x30, 0x22, 0x20, 0x92, 0x0f, 0x04, 0x80, 0x88, 0x11, 0x32, 316 | 0x0f, 0x00, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x90, 0x88, 0x20, 0x8b, 317 | 0x30, 0x30, 0x30, 0x74, 0x32, 0x61, 0x11, 0x06, 0x10, 0x00, 0x22, 0xc1, 318 | 0x10, 0xea, 0x30, 0x01, 0x6b, 0xff, 0x4d, 0x0d, 0xc0, 0x00, 0x00, 0x22, 319 | 0x21, 0x12, 0x3d, 0x01, 0x01, 0x67, 0xff, 0x1c, 0x04, 0xc0, 0x00, 0x00, 320 | 0xfc, 0x92, 0x01, 0x65, 0xff, 0x32, 0x21, 0x12, 0x0c, 0x84, 0x22, 0xc1, 321 | 0x10, 0x2a, 0x2d, 0xd0, 0x44, 0xc0, 0x40, 0x40, 0x74, 0x32, 0xc3, 0x10, 322 | 0x32, 0x61, 0x12, 0x42, 0x61, 0x11, 0x3d, 0x01, 0xc0, 0x00, 0x00, 0x28, 323 | 0x41, 0x88, 0x51, 0x1c, 0x0a, 0x82, 0x61, 0x14, 0xf2, 0x21, 0x11, 0x48, 324 | 0xa1, 0xea, 0xff, 0x0b, 0x04, 0x00, 0x40, 0x74, 0x49, 0xa1, 0x56, 0xc4, 325 | 0xdf, 0x08, 0x91, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x86, 0xce, 0xff, 0x0c, 326 | 0x02, 0x22, 0x61, 0x10, 0x86, 0x99, 0xff, 0x16, 0xd6, 0xf1, 0x2d, 0x00, 327 | 0x60, 0x72, 0x41, 0xe6, 0x17, 0x02, 0x86, 0xc4, 0xff, 0x0c, 0x0d, 0x1b, 328 | 0xdd, 0x42, 0x0f, 0x01, 0x02, 0x0f, 0x03, 0x32, 0x0f, 0x00, 0xc0, 0x00, 329 | 0x30, 0xc2, 0x0f, 0x02, 0x40, 0x33, 0x30, 0x30, 0xcc, 0x30, 0x00, 0xcc, 330 | 0x30, 0xc0, 0xc0, 0x74, 0x08, 0x0f, 0x09, 0x02, 0x4b, 0xff, 0x4b, 0x22, 331 | 0x77, 0x9d, 0xd7, 0x46, 0xb9, 0xff, 0x00, 0x00, 0xfc, 0x82, 0xfe, 0x3f, 332 | 0xa4, 0x02, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6d, 0x61, 333 | 0x67, 0x69, 0x63, 0x21, 0x0a, 0x00, 0x25, 0x73, 0x2c, 0x20, 0x25, 0x73, 334 | 0x20, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x20, 0x62, 0x69, 0x6e, 0x0a, 335 | 0x0a, 0x00, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x62, 0x6f, 0x6f, 0x74, 336 | 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x00, 0x72, 0x65, 0x62, 0x6f, 337 | 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x79, 0x00, 0x25, 0x73, 338 | 0x20, 0x25, 0x78, 0x2c, 0x20, 0x25, 0x73, 0x20, 0x25, 0x73, 0x0a, 0x0a, 339 | 0x00, 0x74, 0x68, 0x69, 0x73, 0x20, 0x62, 0x69, 0x6e, 0x20, 0x61, 0x67, 340 | 0x61, 0x69, 0x6e, 0x00, 0x25, 0x73, 0x2e, 0x0a, 0x0a, 0x00, 0x62, 0x61, 341 | 0x63, 0x6b, 0x75, 0x70, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x20, 0x66, 0x61, 342 | 0x69, 0x6c, 0x65, 0x64, 0x00, 0x0a, 0x32, 0x6e, 0x64, 0x20, 0x62, 0x6f, 343 | 0x6f, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3a, 344 | 0x20, 0x31, 0x2e, 0x37, 0x28, 0x35, 0x64, 0x36, 0x66, 0x38, 0x37, 0x37, 345 | 0x29, 0x0a, 0x00, 0x53, 0x50, 0x49, 0x20, 0x53, 0x70, 0x65, 0x65, 0x64, 346 | 0x20, 0x3a, 0x20, 0x00, 0x34, 0x30, 0x4d, 0x48, 0x7a, 0x00, 0x32, 0x36, 347 | 0x2e, 0x37, 0x4d, 0x48, 0x7a, 0x00, 0x32, 0x30, 0x4d, 0x48, 0x7a, 0x00, 348 | 0x38, 0x30, 0x4d, 0x48, 0x7a, 0x00, 0x0a, 0x53, 0x50, 0x49, 0x20, 0x4d, 349 | 0x6f, 0x64, 0x65, 0x20, 0x3a, 0x20, 0x00, 0x51, 0x49, 0x4f, 0x00, 0x51, 350 | 0x4f, 0x55, 0x54, 0x00, 0x44, 0x49, 0x4f, 0x00, 0x44, 0x4f, 0x55, 0x54, 351 | 0x00, 0x0a, 0x53, 0x50, 0x49, 0x20, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x20, 352 | 0x53, 0x69, 0x7a, 0x65, 0x20, 0x26, 0x20, 0x4d, 0x61, 0x70, 0x3a, 0x20, 353 | 0x00, 0x25, 0x73, 0x28, 0x32, 0x35, 0x36, 0x4b, 0x42, 0x2b, 0x32, 0x35, 354 | 0x36, 0x4b, 0x42, 0x29, 0x0a, 0x00, 0x34, 0x4d, 0x62, 0x69, 0x74, 0x00, 355 | 0x32, 0x4d, 0x62, 0x69, 0x74, 0x0a, 0x00, 0x4d, 0x62, 0x69, 0x74, 0x28, 356 | 0x35, 0x31, 0x32, 0x4b, 0x42, 0x2b, 0x35, 0x31, 0x32, 0x4b, 0x42, 0x29, 357 | 0x00, 0x31, 0x36, 0x25, 0x73, 0x0a, 0x00, 0x33, 0x32, 0x25, 0x73, 0x0a, 358 | 0x00, 0x4d, 0x62, 0x69, 0x74, 0x28, 0x31, 0x30, 0x32, 0x34, 0x4b, 0x42, 359 | 0x2b, 0x31, 0x30, 0x32, 0x34, 0x4b, 0x42, 0x29, 0x00, 0x36, 0x34, 0x25, 360 | 0x73, 0x0a, 0x00, 0x31, 0x32, 0x38, 0x25, 0x73, 0x0a, 0x00, 0x66, 0x6c, 361 | 0x61, 0x73, 0x68, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x6e, 0x6f, 0x74, 0x20, 362 | 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x0a, 0x00, 0x6e, 0x6f, 0x20, 363 | 0x47, 0x50, 0x49, 0x4f, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x21, 364 | 0x0a, 0x00, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 365 | 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x2c, 0x20, 0x67, 0x70, 0x69, 0x6f, 0x20, 366 | 0x25, 0x64, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x6f, 0x77, 0x0a, 0x00, 0x6a, 367 | 0x75, 0x6d, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x62, 368 | 0x69, 0x6e, 0x20, 0x40, 0x20, 0x25, 0x78, 0x0a, 0x0a, 0x00, 0x74, 0x65, 369 | 0x73, 0x74, 0x20, 0x62, 0x69, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 370 | 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x21, 0x0a, 0x00, 0x74, 0x65, 0x73, 371 | 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x00, 0x65, 0x6e, 0x68, 372 | 0x61, 0x6e, 0x63, 0x65, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x20, 0x6d, 0x6f, 373 | 0x64, 0x65, 0x2c, 0x20, 0x00, 0x6a, 0x75, 0x6d, 0x70, 0x20, 0x74, 0x6f, 374 | 0x20, 0x72, 0x75, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x72, 0x00, 0x31, 0x00, 375 | 0x32, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x75, 0x73, 0x65, 0x72, 376 | 0x20, 0x62, 0x69, 0x6e, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x20, 0x3d, 0x20, 377 | 0x25, 0x78, 0x0a, 0x00, 0x97, 0x06, 0x10, 0x40, 0x9d, 0x06, 0x10, 0x40, 378 | 0xad, 0x06, 0x10, 0x40, 0xbf, 0x06, 0x10, 0x40, 0xc8, 0x06, 0x10, 0x40, 379 | 0xd1, 0x06, 0x10, 0x40, 0xe4, 0x06, 0x10, 0x40, 0x1b, 0x07, 0x10, 0x40, 380 | 0xf6, 0x06, 0x10, 0x40, 0x08, 0x07, 0x10, 0x40, 0xf9, 0x07, 0x10, 0x40, 381 | 0xff, 0x07, 0x10, 0x40, 0x19, 0x08, 0x10, 0x40, 0x1f, 0x08, 0x10, 0x40, 382 | 0x25, 0x08, 0x10, 0x40, 0x2b, 0x08, 0x10, 0x40, 0x39, 0x08, 0x10, 0x40, 383 | 0x3f, 0x08, 0x10, 0x40, 0x45, 0x08, 0x10, 0x40, 0x4b, 0x08, 0x10, 0x40, 384 | 0x51, 0x08, 0x10, 0x40, 0x57, 0x08, 0x10, 0x40, 0x5d, 0x08, 0x10, 0x40, 385 | 0x63, 0x08, 0x10, 0x40, 0x69, 0x08, 0x10, 0x40, 0x6f, 0x08, 0x10, 0x40, 386 | 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 387 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 388 | 0xa0, 0x85, 0xfe, 0x3f, 0xa0, 0x85, 0xfe, 0x3f, 0x00, 0x00, 0x00, 0x00, 389 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22 390 | }; 391 | -------------------------------------------------------------------------------- /tests/ecdsa.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | TEST(jwtpp, sign_verify_ecdsa256) { 29 | jwtpp::claims cl; 30 | 31 | jwtpp::sp_ecdsa_key key; 32 | jwtpp::sp_ecdsa_key pubkey; 33 | 34 | EXPECT_NO_THROW(key = jwtpp::ecdsa::gen(NID_secp256k1)); 35 | EXPECT_NO_THROW(pubkey = jwtpp::sp_ecdsa_key(EC_KEY_new(), ::EC_KEY_free)); 36 | 37 | const EC_GROUP *group = EC_KEY_get0_group(key.get()); 38 | const EC_POINT *p = EC_KEY_get0_public_key(key.get()); 39 | 40 | EXPECT_EQ(EC_KEY_set_group(pubkey.get(), group), 1); 41 | EXPECT_TRUE(p != nullptr); 42 | EXPECT_EQ(EC_KEY_set_public_key(pubkey.get(), p), 1); 43 | 44 | jwtpp::sp_crypto e256; 45 | jwtpp::sp_crypto e384; 46 | jwtpp::sp_crypto e512; 47 | jwtpp::sp_crypto e256_pub; 48 | jwtpp::sp_crypto e384_pub; 49 | jwtpp::sp_crypto e512_pub; 50 | 51 | EXPECT_THROW(e256 = std::make_shared(key, jwtpp::alg_t::RS256), std::exception); 52 | 53 | EXPECT_NO_THROW(e256 = std::make_shared(key, jwtpp::alg_t::ES256)); 54 | EXPECT_NO_THROW(e384 = std::make_shared(key, jwtpp::alg_t::ES256)); 55 | EXPECT_NO_THROW(e512 = std::make_shared(key, jwtpp::alg_t::ES256)); 56 | EXPECT_NO_THROW(e256_pub = std::make_shared(pubkey, jwtpp::alg_t::ES256)); 57 | EXPECT_NO_THROW(e384_pub = std::make_shared(pubkey, jwtpp::alg_t::ES256)); 58 | EXPECT_NO_THROW(e512_pub = std::make_shared(pubkey, jwtpp::alg_t::ES256)); 59 | 60 | std::string bearer = jwtpp::jws::sign_bearer(cl, e256); 61 | 62 | EXPECT_TRUE(!bearer.empty()); 63 | 64 | jwtpp::sp_jws jws; 65 | 66 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 67 | 68 | EXPECT_TRUE(jws->verify(e256_pub)); 69 | 70 | auto vf = [](jwtpp::sp_claims cl) { 71 | return !cl->check().iss("troian"); 72 | }; 73 | 74 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 75 | EXPECT_TRUE(jws->verify(e256_pub, vf)); 76 | #else 77 | EXPECT_TRUE(jws->verify(e256_pub, std::bind(vf, std::placeholders::_1))); 78 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 79 | 80 | bearer = "ghdfgddf"; 81 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 82 | 83 | bearer = "Bearer "; 84 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 85 | 86 | bearer = "Bearer bla.bla.bla"; 87 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 88 | } 89 | -------------------------------------------------------------------------------- /tests/eddsa.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #if defined(JWTPP_SUPPORTED_EDDSA) 26 | 27 | #include 28 | 29 | TEST(jwtpp, sign_verify_eddsa) { 30 | jwtpp::claims cl; 31 | 32 | jwtpp::sp_evp_key key; 33 | jwtpp::sp_evp_key pubkey; 34 | 35 | jwtpp::sp_evp_key key_alien; 36 | 37 | // generating 2 keys. 38 | // key used to sign/verify 39 | // key_alien to is expected to fail when validating bearer signed by key 40 | EXPECT_NO_THROW(key = jwtpp::eddsa::gen()); 41 | EXPECT_NO_THROW(pubkey = jwtpp::eddsa::get_pub(key)); 42 | EXPECT_NO_THROW(key_alien = jwtpp::eddsa::gen()); 43 | 44 | jwtpp::sp_crypto ed; 45 | jwtpp::sp_crypto ed_pub; 46 | jwtpp::sp_crypto ed_alien; 47 | 48 | EXPECT_NO_THROW(ed = std::make_shared(key)); 49 | EXPECT_NO_THROW(ed_pub = std::make_shared(pubkey)); 50 | 51 | EXPECT_NO_THROW(ed_alien = std::make_shared(key_alien)); 52 | 53 | std::string bearer; 54 | 55 | EXPECT_NO_THROW(bearer = jwtpp::jws::sign_bearer(cl, ed)); 56 | 57 | EXPECT_TRUE(!bearer.empty()); 58 | 59 | jwtpp::sp_jws jws; 60 | 61 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 62 | 63 | EXPECT_FALSE(jws->verify(ed_alien)); 64 | 65 | EXPECT_TRUE(jws->verify(ed)); 66 | EXPECT_TRUE(jws->verify(ed_pub)); 67 | 68 | auto vf = [](jwtpp::sp_claims cl) { 69 | return !cl->check().iss("troian"); 70 | }; 71 | 72 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 73 | EXPECT_TRUE(jws->verify(ed, vf)); 74 | #else 75 | EXPECT_TRUE(jws->verify(ed, std::bind(vf, std::placeholders::_1))); 76 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 77 | 78 | bearer = "ghdfgddf"; 79 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 80 | 81 | bearer = "Bearer "; 82 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 83 | 84 | bearer = "Bearer bla.bla.bla"; 85 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 86 | } 87 | 88 | #endif // defined(JWTPP_SUPPORTED_EDDSA) 89 | -------------------------------------------------------------------------------- /tests/expire.cpp: -------------------------------------------------------------------------------- 1 | 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2020 ihmc3jn09hk 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | TEST(jwtpp, check_expire) { 30 | auto future_t = std::chrono::system_clock::now() + std::chrono::seconds{30}; 31 | auto future = std::chrono::system_clock::to_time_t(future_t); 32 | 33 | jwtpp::claims cl; 34 | 35 | cl.set().exp(std::to_string(future)); 36 | 37 | jwtpp::sp_rsa_key key; 38 | jwtpp::sp_rsa_key pubkey; 39 | 40 | jwtpp::sp_crypto r512; 41 | jwtpp::sp_crypto r512_pub; 42 | 43 | EXPECT_NO_THROW(key = jwtpp::rsa::gen(4096)); 44 | EXPECT_NO_THROW(pubkey = jwtpp::sp_rsa_key(RSAPublicKey_dup(key.get()), ::RSA_free)); 45 | 46 | EXPECT_NO_THROW(r512 = std::make_shared(key, jwtpp::alg_t::RS512)); 47 | EXPECT_NO_THROW(r512_pub = std::make_shared(pubkey, jwtpp::alg_t::RS512)); 48 | 49 | std::string bearer = jwtpp::jws::sign_bearer(cl, r512); 50 | 51 | jwtpp::sp_jws jws; 52 | 53 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 54 | 55 | auto now_t = std::chrono::system_clock::now(); 56 | auto now =std::chrono::system_clock::to_time_t(now_t); 57 | 58 | auto vf = [&now](jwtpp::sp_claims cl) { 59 | time_t &&future_s = std::stoll(cl->get().exp()); 60 | return 0 < difftime(future_s, now); 61 | }; 62 | 63 | EXPECT_TRUE(jws->verify(r512_pub, vf)); 64 | 65 | auto vf_ = [&now](jwtpp::sp_claims cl) { 66 | time_t &&future_s = std::stoll(cl->get().exp()); 67 | return 0 > difftime(now, future_s); 68 | }; 69 | 70 | EXPECT_TRUE(jws->verify(r512_pub, vf_)); 71 | } 72 | -------------------------------------------------------------------------------- /tests/header.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | 29 | TEST(jwtpp, header_decode_valid) { 30 | EXPECT_NO_THROW(jwtpp::hdr("{\"typ\":\"JWT\",\"alg\":\"RS256\"}")); 31 | 32 | EXPECT_THROW(jwtpp::hdr("{\"typ\":\"Jwt\",\"alg\":\"RS256\"}"), std::exception); 33 | EXPECT_THROW(jwtpp::hdr("{,\"alg\":\"RS256\"}"), std::exception); 34 | EXPECT_THROW(jwtpp::hdr("{\"alg\":\"RS256\"}"), std::exception); 35 | EXPECT_THROW(jwtpp::hdr("{\"alg\":\"BB6\"}"), std::exception); 36 | } 37 | 38 | TEST(jwtpp, header_decode_invalid_typ) { 39 | EXPECT_THROW(jwtpp::hdr("{\"typ\":\"Jwt\",\"alg\":\"RS256\"}"), std::exception); 40 | } 41 | 42 | TEST(jwtpp, header_invalid_json) { 43 | EXPECT_THROW(jwtpp::hdr("{,\"alg\":\"RS256\"}"), std::exception); 44 | } 45 | 46 | 47 | TEST(jwtpp, header_no_typ) { 48 | EXPECT_THROW(jwtpp::hdr("{\"alg\":\"RS256\"}"), std::exception); 49 | } 50 | 51 | TEST(jwtpp, header_no_alg) { 52 | EXPECT_THROW(jwtpp::hdr("{\"typ\":\"JWT\"}"), std::exception); 53 | } 54 | 55 | TEST(jwtpp, header_invalid_alg) { 56 | EXPECT_THROW(jwtpp::hdr("{\"typ\":\"JWT\",\"alg\":\"BBs\"}"), std::exception); 57 | } 58 | -------------------------------------------------------------------------------- /tests/hmac.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | TEST(jwtpp, create_close_hmac_crypto) 28 | { 29 | EXPECT_NO_THROW(std::make_shared("secret", jwtpp::alg_t::HS256)); 30 | EXPECT_NO_THROW(std::make_shared("secret", jwtpp::alg_t::HS384)); 31 | EXPECT_NO_THROW(std::make_shared("secret", jwtpp::alg_t::HS512)); 32 | 33 | EXPECT_THROW(std::make_shared("", jwtpp::alg_t::HS256), std::exception); 34 | EXPECT_THROW(std::make_shared("", jwtpp::alg_t::HS384), std::exception); 35 | EXPECT_THROW(std::make_shared("", jwtpp::alg_t::HS512), std::exception); 36 | EXPECT_THROW(std::make_shared("secret", jwtpp::alg_t::NONE), std::exception); 37 | EXPECT_THROW(std::make_shared("secret", jwtpp::alg_t::UNKNOWN), std::exception); 38 | 39 | EXPECT_THROW(std::make_shared("", jwtpp::alg_t::ES512), std::exception); 40 | EXPECT_THROW(std::make_shared("", jwtpp::alg_t::RS256), std::exception); 41 | } 42 | 43 | TEST(jwtpp, sign_verify_hmac256) 44 | { 45 | jwtpp::claims cl; 46 | 47 | cl.set().iss("troian"); 48 | 49 | jwtpp::sp_crypto h256 = std::make_shared("secret", jwtpp::alg_t::HS256); 50 | jwtpp::sp_crypto h384 = std::make_shared("secret", jwtpp::alg_t::HS384); 51 | jwtpp::sp_crypto h512 = std::make_shared("secret", jwtpp::alg_t::HS512); 52 | 53 | std::string bearer = jwtpp::jws::sign_bearer(cl, h256); 54 | 55 | jwtpp::sp_jws jws; 56 | 57 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 58 | 59 | EXPECT_TRUE(jws->verify(h256)); 60 | 61 | auto vf = [](jwtpp::sp_claims cl) { 62 | return cl->check().iss("troian"); 63 | }; 64 | 65 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 66 | EXPECT_TRUE(jws->verify(h256, vf)); 67 | #else 68 | EXPECT_TRUE(jws->verify(h256, std::bind(vf, std::placeholders::_1))); 69 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 70 | 71 | EXPECT_THROW(jws->verify(h384), std::exception); 72 | EXPECT_THROW(jws->verify(h512), std::exception); 73 | 74 | bearer = "ghdfgddf"; 75 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 76 | 77 | bearer = "Bearer "; 78 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 79 | 80 | bearer = "Bearer bla.bla.bla"; 81 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 82 | } 83 | 84 | TEST(jwtpp, sign_verify_hmac384) 85 | { 86 | jwtpp::claims cl; 87 | 88 | cl.set().iss("troian"); 89 | 90 | jwtpp::sp_crypto h256 = std::make_shared("secret", jwtpp::alg_t::HS256); 91 | jwtpp::sp_crypto h384 = std::make_shared("secret", jwtpp::alg_t::HS384); 92 | jwtpp::sp_crypto h512 = std::make_shared("secret", jwtpp::alg_t::HS512); 93 | 94 | std::string bearer = jwtpp::jws::sign_bearer(cl, h384); 95 | 96 | jwtpp::sp_jws jws; 97 | 98 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 99 | 100 | EXPECT_TRUE(jws->verify(h384)); 101 | 102 | auto vf = [](jwtpp::sp_claims cl) { 103 | return cl->check().iss("troian"); 104 | }; 105 | 106 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 107 | EXPECT_TRUE(jws->verify(h384, vf)); 108 | #else 109 | EXPECT_TRUE(jws->verify(h384, std::bind(vf, std::placeholders::_1))); 110 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 111 | 112 | EXPECT_THROW(jws->verify(h256), std::exception); 113 | EXPECT_THROW(jws->verify(h512), std::exception); 114 | 115 | bearer = "ghdfgddf"; 116 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 117 | 118 | bearer = "Bearer "; 119 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 120 | 121 | bearer = "Bearer bla.bla.bla"; 122 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 123 | } 124 | 125 | TEST(jwtpp, sign_verify_hmac512) 126 | { 127 | jwtpp::claims cl; 128 | 129 | cl.set().iss("troian"); 130 | 131 | jwtpp::sp_crypto h256 = std::make_shared("secret", jwtpp::alg_t::HS256); 132 | jwtpp::sp_crypto h384 = std::make_shared("secret", jwtpp::alg_t::HS384); 133 | jwtpp::sp_crypto h512 = std::make_shared("secret", jwtpp::alg_t::HS512); 134 | 135 | std::string bearer = jwtpp::jws::sign_bearer(cl, h512); 136 | 137 | jwtpp::sp_jws jws; 138 | 139 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 140 | 141 | EXPECT_TRUE(jws->verify(h512)); 142 | 143 | auto vf = [](jwtpp::sp_claims cl) { 144 | return cl->check().iss("troian"); 145 | }; 146 | 147 | #if defined(_MSC_VER) && (_MSC_VER < 1700) 148 | EXPECT_TRUE(jws->verify(h512, vf)); 149 | #else 150 | EXPECT_TRUE(jws->verify(h512, std::bind(vf, std::placeholders::_1))); 151 | #endif // defined(_MSC_VER) && (_MSC_VER < 1700) 152 | 153 | EXPECT_THROW(jws->verify(h384), std::exception); 154 | EXPECT_THROW(jws->verify(h256), std::exception); 155 | 156 | bearer = "ghdfgddf"; 157 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 158 | 159 | bearer = "Bearer "; 160 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 161 | 162 | bearer = "Bearer bla.bla.bla"; 163 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 164 | } 165 | 166 | -------------------------------------------------------------------------------- /tests/pss.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | TEST(jwtpp, create_close_pss_crypto) { 28 | jwtpp::sp_rsa_key key; 29 | 30 | EXPECT_NO_THROW(key = jwtpp::rsa::gen(1024)); 31 | 32 | EXPECT_NO_THROW(std::make_shared(key, jwtpp::alg_t::PS256)); 33 | EXPECT_NO_THROW(std::make_shared(key, jwtpp::alg_t::PS384)); 34 | EXPECT_THROW(std::make_shared(key, jwtpp::alg_t::PS512), std::exception); 35 | 36 | EXPECT_THROW(std::make_shared(key, jwtpp::alg_t::HS256), std::exception); 37 | EXPECT_THROW(std::make_shared(key, jwtpp::alg_t::ES384), std::exception); 38 | } 39 | 40 | TEST(jwtpp, sign_verify_pss256) { 41 | jwtpp::claims cl; 42 | 43 | jwtpp::sp_rsa_key key; 44 | jwtpp::sp_rsa_key pubkey; 45 | jwtpp::sp_crypto r256; 46 | jwtpp::sp_crypto r256_pub; 47 | jwtpp::sp_crypto r384; 48 | jwtpp::sp_crypto r384_pub; 49 | jwtpp::sp_crypto r512; 50 | jwtpp::sp_crypto r512_pub; 51 | 52 | EXPECT_NO_THROW(key = jwtpp::rsa::gen(1024)); 53 | EXPECT_NO_THROW(pubkey = jwtpp::sp_rsa_key(RSAPublicKey_dup(key.get()), ::RSA_free)); 54 | EXPECT_NO_THROW(r256 = std::make_shared(key, jwtpp::alg_t::PS256)); 55 | EXPECT_NO_THROW(r256_pub = std::make_shared(pubkey, jwtpp::alg_t::PS256)); 56 | EXPECT_NO_THROW(r384 = std::make_shared(key, jwtpp::alg_t::PS384)); 57 | EXPECT_NO_THROW(r384_pub = std::make_shared(pubkey, jwtpp::alg_t::PS384)); 58 | EXPECT_THROW(r512 = std::make_shared(key, jwtpp::alg_t::PS512), std::exception); 59 | EXPECT_THROW(r512_pub = std::make_shared(pubkey, jwtpp::alg_t::PS512), std::exception); 60 | 61 | std::string bearer = jwtpp::jws::sign_bearer(cl, r256); 62 | 63 | jwtpp::sp_jws jws; 64 | 65 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 66 | 67 | EXPECT_TRUE(jws->verify(r256)); 68 | EXPECT_TRUE(jws->verify(r256_pub)); 69 | 70 | auto vf = [](jwtpp::sp_claims cl) { 71 | return !cl->check().iss("troian"); 72 | }; 73 | 74 | EXPECT_TRUE(jws->verify(r256_pub, vf)); 75 | EXPECT_THROW(jws->verify(r384_pub, vf), std::exception); 76 | EXPECT_THROW(jws->verify(r512_pub, vf), std::exception); 77 | 78 | bearer = "ghdfgddf"; 79 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 80 | 81 | bearer = "Bearer "; 82 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 83 | 84 | bearer = "Bearer bla.bla.bla"; 85 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 86 | } 87 | 88 | TEST(jwtpp, sign_verify_pss384) { 89 | jwtpp::claims cl; 90 | 91 | jwtpp::sp_rsa_key key; 92 | jwtpp::sp_rsa_key pubkey; 93 | jwtpp::sp_crypto r256; 94 | jwtpp::sp_crypto r256_pub; 95 | jwtpp::sp_crypto r384; 96 | jwtpp::sp_crypto r384_pub; 97 | jwtpp::sp_crypto r512; 98 | jwtpp::sp_crypto r512_pub; 99 | 100 | EXPECT_NO_THROW(key = jwtpp::rsa::gen(1024)); 101 | EXPECT_NO_THROW(pubkey = jwtpp::sp_rsa_key(RSAPublicKey_dup(key.get()), ::RSA_free)); 102 | EXPECT_NO_THROW(r256 = std::make_shared(key, jwtpp::alg_t::PS256)); 103 | EXPECT_NO_THROW(r256_pub = std::make_shared(pubkey, jwtpp::alg_t::PS256)); 104 | EXPECT_NO_THROW(r384 = std::make_shared(key, jwtpp::alg_t::PS384)); 105 | EXPECT_NO_THROW(r384_pub = std::make_shared(pubkey, jwtpp::alg_t::PS384)); 106 | EXPECT_THROW(r512 = std::make_shared(key, jwtpp::alg_t::PS512), std::exception); 107 | EXPECT_THROW(r512_pub = std::make_shared(pubkey, jwtpp::alg_t::PS512), std::exception); 108 | 109 | std::string bearer = jwtpp::jws::sign_bearer(cl, r384); 110 | 111 | jwtpp::sp_jws jws; 112 | 113 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 114 | 115 | EXPECT_TRUE(jws->verify(r384_pub)); 116 | 117 | auto vf = [](jwtpp::sp_claims cl) { 118 | return !cl->check().iss("troian"); 119 | }; 120 | 121 | EXPECT_TRUE(jws->verify(r384_pub, vf)); 122 | EXPECT_THROW(jws->verify(r256_pub, vf), std::exception); 123 | EXPECT_THROW(jws->verify(r512_pub, vf), std::exception); 124 | 125 | bearer = "ghdfgddf"; 126 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 127 | 128 | bearer = "Bearer "; 129 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 130 | 131 | bearer = "Bearer bla.bla.bla"; 132 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 133 | } 134 | 135 | TEST(jwtpp, sign_verify_pss512) { 136 | jwtpp::claims cl; 137 | 138 | jwtpp::sp_rsa_key key; 139 | jwtpp::sp_rsa_key pubkey; 140 | jwtpp::sp_crypto r256; 141 | jwtpp::sp_crypto r256_pub; 142 | jwtpp::sp_crypto r384; 143 | jwtpp::sp_crypto r384_pub; 144 | jwtpp::sp_crypto r512; 145 | jwtpp::sp_crypto r512_pub; 146 | 147 | EXPECT_NO_THROW(key = jwtpp::rsa::gen(2048)); 148 | EXPECT_NO_THROW(pubkey = jwtpp::sp_rsa_key(RSAPublicKey_dup(key.get()), ::RSA_free)); 149 | EXPECT_NO_THROW(r256 = std::make_shared(key, jwtpp::alg_t::PS256)); 150 | EXPECT_NO_THROW(r256_pub = std::make_shared(pubkey, jwtpp::alg_t::PS256)); 151 | EXPECT_NO_THROW(r384 = std::make_shared(key, jwtpp::alg_t::PS384)); 152 | EXPECT_NO_THROW(r384_pub = std::make_shared(pubkey, jwtpp::alg_t::PS384)); 153 | EXPECT_NO_THROW(r512 = std::make_shared(key, jwtpp::alg_t::PS512)); 154 | EXPECT_NO_THROW(r512_pub = std::make_shared(pubkey, jwtpp::alg_t::PS512)); 155 | 156 | std::string bearer = jwtpp::jws::sign_bearer(cl, r512); 157 | 158 | jwtpp::sp_jws jws; 159 | 160 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 161 | 162 | EXPECT_TRUE(jws->verify(r512_pub)); 163 | 164 | auto vf = [](jwtpp::sp_claims cl) { 165 | return !cl->check().iss("troian"); 166 | }; 167 | 168 | EXPECT_TRUE(jws->verify(r512_pub, vf)); 169 | EXPECT_THROW(jws->verify(r384_pub, vf), std::exception); 170 | EXPECT_THROW(jws->verify(r256_pub, vf), std::exception); 171 | 172 | bearer = "ghdfgddf"; 173 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 174 | 175 | bearer = "Bearer "; 176 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 177 | 178 | bearer = "Bearer bla.bla.bla"; 179 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 180 | } 181 | -------------------------------------------------------------------------------- /tests/rsa.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2016-2020 Artur Troian 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | 29 | TEST(jwtpp, rsa_gen_invalid_size) { 30 | jwtpp::sp_rsa_key key; 31 | 32 | EXPECT_THROW(key = jwtpp::rsa::gen(1023), std::exception); 33 | } 34 | 35 | TEST(jwtpp, create_close_rsa_crypto) { 36 | jwtpp::sp_rsa_key key; 37 | 38 | EXPECT_NO_THROW(key = jwtpp::rsa::gen(1024)); 39 | 40 | EXPECT_NO_THROW(std::make_shared(key, jwtpp::alg_t::RS256)); 41 | EXPECT_NO_THROW(std::make_shared(key, jwtpp::alg_t::RS384)); 42 | EXPECT_NO_THROW(std::make_shared(key, jwtpp::alg_t::RS512)); 43 | 44 | EXPECT_THROW(std::make_shared(key, jwtpp::alg_t::HS256), std::exception); 45 | EXPECT_THROW(std::make_shared(key, jwtpp::alg_t::ES384), std::exception); 46 | } 47 | 48 | TEST(jwtpp, sign_verify_rsa256) { 49 | jwtpp::claims cl; 50 | 51 | jwtpp::sp_rsa_key key; 52 | jwtpp::sp_rsa_key pubkey; 53 | jwtpp::sp_crypto r256; 54 | jwtpp::sp_crypto r256_pub; 55 | jwtpp::sp_crypto r384; 56 | jwtpp::sp_crypto r384_pub; 57 | jwtpp::sp_crypto r512; 58 | jwtpp::sp_crypto r512_pub; 59 | 60 | EXPECT_NO_THROW(key = jwtpp::rsa::gen(1024)); 61 | EXPECT_NO_THROW(pubkey = jwtpp::sp_rsa_key(RSAPublicKey_dup(key.get()), ::RSA_free)); 62 | EXPECT_NO_THROW(r256 = std::make_shared(key, jwtpp::alg_t::RS256)); 63 | EXPECT_NO_THROW(r256_pub = std::make_shared(pubkey, jwtpp::alg_t::RS256)); 64 | EXPECT_NO_THROW(r384 = std::make_shared(key, jwtpp::alg_t::RS384)); 65 | EXPECT_NO_THROW(r384_pub = std::make_shared(pubkey, jwtpp::alg_t::RS384)); 66 | EXPECT_NO_THROW(r512 = std::make_shared(key, jwtpp::alg_t::RS512)); 67 | EXPECT_NO_THROW(r512_pub = std::make_shared(pubkey, jwtpp::alg_t::RS512)); 68 | 69 | std::string bearer = jwtpp::jws::sign_bearer(cl, r256); 70 | 71 | jwtpp::sp_jws jws; 72 | 73 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 74 | 75 | EXPECT_TRUE(jws->verify(r256_pub)); 76 | 77 | auto vf = [](jwtpp::sp_claims cl) { 78 | return !cl->check().iss("troian"); 79 | }; 80 | 81 | EXPECT_TRUE(jws->verify(r256_pub, vf)); 82 | EXPECT_THROW(jws->verify(r384_pub, vf), std::exception); 83 | EXPECT_THROW(jws->verify(r512_pub, vf), std::exception); 84 | 85 | bearer = "ghdfgddf"; 86 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 87 | 88 | bearer = "Bearer "; 89 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 90 | 91 | bearer = "Bearer bla.bla.bla"; 92 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 93 | } 94 | 95 | TEST(jwtpp, sign_verify_rsa384) { 96 | jwtpp::claims cl; 97 | 98 | jwtpp::sp_rsa_key key; 99 | jwtpp::sp_rsa_key pubkey; 100 | jwtpp::sp_crypto r256; 101 | jwtpp::sp_crypto r256_pub; 102 | jwtpp::sp_crypto r384; 103 | jwtpp::sp_crypto r384_pub; 104 | jwtpp::sp_crypto r512; 105 | jwtpp::sp_crypto r512_pub; 106 | 107 | EXPECT_NO_THROW(key = jwtpp::rsa::gen(1024)); 108 | EXPECT_NO_THROW(pubkey = jwtpp::sp_rsa_key(RSAPublicKey_dup(key.get()), ::RSA_free)); 109 | EXPECT_NO_THROW(r256 = std::make_shared(key, jwtpp::alg_t::RS256)); 110 | EXPECT_NO_THROW(r256_pub = std::make_shared(pubkey, jwtpp::alg_t::RS256)); 111 | EXPECT_NO_THROW(r384 = std::make_shared(key, jwtpp::alg_t::RS384)); 112 | EXPECT_NO_THROW(r384_pub = std::make_shared(pubkey, jwtpp::alg_t::RS384)); 113 | EXPECT_NO_THROW(r512 = std::make_shared(key, jwtpp::alg_t::RS512)); 114 | EXPECT_NO_THROW(r512_pub = std::make_shared(pubkey, jwtpp::alg_t::RS512)); 115 | 116 | std::string bearer = jwtpp::jws::sign_bearer(cl, r384); 117 | 118 | jwtpp::sp_jws jws; 119 | 120 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 121 | 122 | EXPECT_TRUE(jws->verify(r384_pub)); 123 | 124 | auto vf = [](jwtpp::sp_claims cl) { 125 | return !cl->check().iss("troian"); 126 | }; 127 | 128 | EXPECT_TRUE(jws->verify(r384_pub, vf)); 129 | EXPECT_THROW(jws->verify(r256_pub, vf), std::exception); 130 | EXPECT_THROW(jws->verify(r512_pub, vf), std::exception); 131 | 132 | bearer = "ghdfgddf"; 133 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 134 | 135 | bearer = "Bearer "; 136 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 137 | 138 | bearer = "Bearer bla.bla.bla"; 139 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 140 | } 141 | 142 | TEST(jwtpp, sign_verify_rsa512) { 143 | jwtpp::claims cl; 144 | 145 | jwtpp::sp_rsa_key key; 146 | jwtpp::sp_rsa_key pubkey; 147 | jwtpp::sp_crypto r256; 148 | jwtpp::sp_crypto r256_pub; 149 | jwtpp::sp_crypto r384; 150 | jwtpp::sp_crypto r384_pub; 151 | jwtpp::sp_crypto r512; 152 | jwtpp::sp_crypto r512_pub; 153 | 154 | EXPECT_NO_THROW(key = jwtpp::rsa::gen(1024)); 155 | EXPECT_NO_THROW(pubkey = jwtpp::sp_rsa_key(RSAPublicKey_dup(key.get()), ::RSA_free)); 156 | EXPECT_NO_THROW(r256 = std::make_shared(key, jwtpp::alg_t::RS256)); 157 | EXPECT_NO_THROW(r256_pub = std::make_shared(pubkey, jwtpp::alg_t::RS256)); 158 | EXPECT_NO_THROW(r384 = std::make_shared(key, jwtpp::alg_t::RS384)); 159 | EXPECT_NO_THROW(r384_pub = std::make_shared(pubkey, jwtpp::alg_t::RS384)); 160 | EXPECT_NO_THROW(r512 = std::make_shared(key, jwtpp::alg_t::RS512)); 161 | EXPECT_NO_THROW(r512_pub = std::make_shared(pubkey, jwtpp::alg_t::RS512)); 162 | 163 | std::string bearer = jwtpp::jws::sign_bearer(cl, r512); 164 | 165 | jwtpp::sp_jws jws; 166 | 167 | EXPECT_NO_THROW(jws = jwtpp::jws::parse(bearer)); 168 | 169 | EXPECT_TRUE(jws->verify(r512_pub)); 170 | 171 | auto vf = [](jwtpp::sp_claims cl) { 172 | return !cl->check().iss("troian"); 173 | }; 174 | 175 | EXPECT_TRUE(jws->verify(r512_pub, vf)); 176 | EXPECT_THROW(jws->verify(r384_pub, vf), std::exception); 177 | EXPECT_THROW(jws->verify(r256_pub, vf), std::exception); 178 | 179 | bearer = "ghdfgddf"; 180 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 181 | 182 | bearer = "Bearer "; 183 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 184 | 185 | bearer = "Bearer bla.bla.bla"; 186 | EXPECT_THROW(jws = jwtpp::jws::parse(bearer), std::exception); 187 | } 188 | 189 | TEST(jwtpp, load_rsa_from_file) { 190 | jwtpp::sp_rsa_key key; 191 | 192 | EXPECT_NO_THROW(key = jwtpp::rsa::load_from_file(TEST_RSA_KEY_PATH, [](jwtpp::secure_string &pass, int rwflag) { 193 | pass.assign("12345"); 194 | })); 195 | 196 | EXPECT_THROW(key = jwtpp::rsa::load_from_file(TEST_RSA_KEY_PATH), std::exception); 197 | } 198 | -------------------------------------------------------------------------------- /tests/rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,A753DE120115C746 4 | 5 | vkYqvTQ6LUHnTTPpk0hxefjZoWtbO0KoxITs5r6Q7BkuyCbAWSKcAr6/obb19Fjr 6 | vVS7sjpbhoUTwEWHRDSCd+kScsZsMBpP08Qb2ggN0O+VwysZMB4UjhlUQs5FEL6G 7 | 5yRT/tlnW8Fcycnt6J2Ogxp3NWC6vWwFjFP3zUXvICzh289IpIs0O43wPEA0ly24 8 | aHcXdkWaNiGM3FhGum4EZbDgk7jnr0D5qFiNINCp+jjqXj3z7M0iDkv1WAxpel6q 9 | hf7IsbBW6naUVBGVM9sudLTUaM557UcOhh8yUlK5w795j0yROvTQsa7dYGiRjOYL 10 | 3RfTRhDPK1Rf/T0b2v9eZzEXCbwxjKyWL2s63Mn0+i+UVO7+iy86MYRvE8D4dGEF 11 | rgapU7bwfgVd11RMnhKvg4Uhx518sG5e/ZkY0i/Xa7hwYMO2f6ysw7tPQXiC+JHs 12 | dwUG9QNdRk4EMpcO4ag87npqDQA2EK76/eZ5ahksQlCSrIM3BaFY0Cu70fSmh+yM 13 | oEyifUVQa5BObetrWvsLFpiCquev8e0k/dYTgRaSfB/zP5zJubD1jmkSHx+4E2cX 14 | fqJYPTCJPNrmygfboRWyuiKacoHK695Dhrgpt7IOyjzLHJzuOCkcRJmC+3ihiXvr 15 | n6tV2iEtCrMGInUviqC4aVwcvDWmRXdIVwGAh1MJLMQxJEcoMFtLOiOBddkAoRmc 16 | GQIgT28VloYfMH4I89sjacMwbC7Hijxj5ew2CFGszcFsZmXfEkOjHCTl1nc9zwwI 17 | ZkLrCVn9d3x3UF5yUlBcQAWGpqnuJpamT9UoSJlXRB2xAr/SERkeRoDDGnxWmnLq 18 | 6j5nJPX/2pq6UyXE51mc1EfCXa5Ss6f82HVB5YpCM6I1RhmMtlKDV1zgDWVyUrgh 19 | l2E6QbpQu9/BRjIW6UG628B/nTa+KXDWerJgOmCdjcFEChPOhAOq6Hc+2QAfNIUC 20 | Q8hW8JbnP4QJ9gxY8DiAMcdAJwR6HNHzBgyKdXUCiwTqz/K88ocWRtJx4S1DGbl0 21 | gCS7CI8P6XGK2IBw0K44wkGZecZ+ezfJGQgI7xerOTS+f01FN8oMvwCaElE0X1ST 22 | LE5hubGjQ9eL2RBVqg1brBDb6uhrhyEXMtPCdVM+8CzWUt/d/YcfqgaNisN7SbCr 23 | 9/7eM7DG7TNp7SooYb1JVyeEFVjlgBqfZ/OvVjoevcj3UcKUmvp82ryWsajuD5R8 24 | RmSKe8yOCrkY27XBVCRaCoLFSEr9/BBKwf2pWFH60y7dKHL4uYrw9pPSZaaKyC5X 25 | OlCQGX13OgLXZa6sMsCka3WATXKsM6pr61JD7GkgP0oSDlZU9gX7QiYC0bko4ZWK 26 | 5b4V5qX9qWQISIBL8DBhkqdPlwaUNnELXeaWOouGfAnrqYuHWiwQl2gs1wA5qg3M 27 | 7DOW2ZPnpt8Gtq/azXGBMbDWzabkCFCxN8b2TtTxjgljl2HBOg/u0MQg6fc4coWp 28 | PywdutE2SdRzw43f4j4OqXU3ypksCqeRojs55XMLD0YBwBk5PIe5JiaqyTFo/yvZ 29 | d1PI8HfhCWyXf+MBepasgozmz+bt92M9ub5/U4VbPIiMRW9bjfSC1ghnMfaDEhFe 30 | -----END RSA PRIVATE KEY----- 31 | --------------------------------------------------------------------------------