├── .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 | [](https://www.codacy.com/app/troian/jwtpp?utm_source=github.com&utm_medium=referral&utm_content=troian/jwtpp&utm_campaign=badger)
5 | [](https://travis-ci.com/troian/jwtpp)
6 | [](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