diff --git a/.clang-tidy b/.clang-tidy index e9451272681..4dd8b9859c9 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -209,3 +209,5 @@ CheckOptions: # Workaround clang-tidy bug: https://github.com/llvm/llvm-project/issues/46097 - key: readability-identifier-naming.TypeTemplateParameterIgnoredRegexp value: expr-type + - key: cppcoreguidelines-avoid-do-while.IgnoreMacros + value: true diff --git a/.github/workflows/backport_branches.yml b/.github/workflows/backport_branches.yml index 7d7efc51fa9..110c06631c7 100644 --- a/.github/workflows/backport_branches.yml +++ b/.github/workflows/backport_branches.yml @@ -549,7 +549,7 @@ jobs: docker ps --all --quiet | xargs --no-run-if-empty docker rm -f ||: sudo rm -fr "$TEMP_PATH" InstallPackagesTestAarch64: - needs: [BuilderDebRelease] + needs: [BuilderDebAarch64] runs-on: [self-hosted, style-checker-aarch64] steps: - name: Set envs diff --git a/.github/workflows/docs_check.yml b/.github/workflows/docs_check.yml index d69020d810e..a0d0e49b95b 100644 --- a/.github/workflows/docs_check.yml +++ b/.github/workflows/docs_check.yml @@ -13,9 +13,11 @@ on: # yamllint disable-line rule:truthy branches: - master paths: + - 'CHANGELOG.md' + - 'README.md' + - 'SECURITY.md' - 'docker/docs/**' - 'docs/**' - - 'website/**' - 'utils/check-style/aspell-ignore/**' jobs: CheckLabels: diff --git a/.github/workflows/docs_release.yml b/.github/workflows/docs_release.yml deleted file mode 100644 index fc4b9d88c3e..00000000000 --- a/.github/workflows/docs_release.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: DocsReleaseChecks - -env: - # Force the stdout and stderr streams to be unbuffered - PYTHONUNBUFFERED: 1 - -concurrency: - group: master-release - cancel-in-progress: true -'on': - push: - branches: - - master - paths: - - '.github/**' - - 'docker/docs/release/**' - - 'docs/**' - - 'utils/list-versions/version_date.tsv' - - 'website/**' - - 'utils/check-style/aspell-ignore/**' - workflow_dispatch: -jobs: - DockerHubPushAarch64: - runs-on: [self-hosted, style-checker-aarch64] - steps: - - name: Check out repository code - uses: ClickHouse/checkout@v1 - with: - clear-repository: true - - name: Images check - run: | - cd "$GITHUB_WORKSPACE/tests/ci" - python3 docker_images_check.py --suffix aarch64 - - name: Upload images files to artifacts - uses: actions/upload-artifact@v3 - with: - name: changed_images_aarch64 - path: ${{ runner.temp }}/docker_images_check/changed_images_aarch64.json - DockerHubPushAmd64: - runs-on: [self-hosted, style-checker] - steps: - - name: Check out repository code - uses: ClickHouse/checkout@v1 - with: - clear-repository: true - - name: Images check - run: | - cd "$GITHUB_WORKSPACE/tests/ci" - python3 docker_images_check.py --suffix amd64 - - name: Upload images files to artifacts - uses: actions/upload-artifact@v3 - with: - name: changed_images_amd64 - path: ${{ runner.temp }}/docker_images_check/changed_images_amd64.json - DockerHubPush: - needs: [DockerHubPushAmd64, DockerHubPushAarch64] - runs-on: [self-hosted, style-checker] - steps: - - name: Check out repository code - uses: ClickHouse/checkout@v1 - with: - clear-repository: true - - name: Download changed aarch64 images - uses: actions/download-artifact@v3 - with: - name: changed_images_aarch64 - path: ${{ runner.temp }} - - name: Download changed amd64 images - uses: actions/download-artifact@v3 - with: - name: changed_images_amd64 - path: ${{ runner.temp }} - - name: Images check - run: | - cd "$GITHUB_WORKSPACE/tests/ci" - python3 docker_manifests_merge.py --suffix amd64 --suffix aarch64 - - name: Upload images files to artifacts - uses: actions/upload-artifact@v3 - with: - name: changed_images - path: ${{ runner.temp }}/changed_images.json - DocsRelease: - needs: DockerHubPush - runs-on: [self-hosted, func-tester] - steps: - - name: Set envs - # https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#multiline-strings - run: | - cat >> "$GITHUB_ENV" << 'EOF' - TEMP_PATH=${{runner.temp}}/docs_release - REPO_COPY=${{runner.temp}}/docs_release/ClickHouse - CLOUDFLARE_TOKEN=${{secrets.CLOUDFLARE}} - ROBOT_CLICKHOUSE_SSH_KEY<> "$GITHUB_ENV" << 'EOF' - TEMP_PATH=${{runner.temp}}/stress_thread + TEMP_PATH=${{runner.temp}}/stress_asan REPORTS_PATH=${{runner.temp}}/reports_dir CHECK_NAME=Stress test (asan) - REPO_COPY=${{runner.temp}}/stress_thread/ClickHouse + REPO_COPY=${{runner.temp}}/stress_asan/ClickHouse EOF - name: Download json reports uses: actions/download-artifact@v3 @@ -3265,6 +3267,142 @@ jobs: docker ps --quiet | xargs --no-run-if-empty docker kill ||: docker ps --all --quiet | xargs --no-run-if-empty docker rm -f ||: sudo rm -fr "$TEMP_PATH" + ############################################################################################## + ######################################### UPGRADE CHECK ###################################### + ############################################################################################## + UpgradeCheckAsan: + needs: [BuilderDebAsan] + runs-on: [self-hosted, stress-tester] + steps: + - name: Set envs + run: | + cat >> "$GITHUB_ENV" << 'EOF' + TEMP_PATH=${{runner.temp}}/upgrade_asan + REPORTS_PATH=${{runner.temp}}/reports_dir + CHECK_NAME=Upgrade check (asan) + REPO_COPY=${{runner.temp}}/upgrade_asan/ClickHouse + EOF + - name: Download json reports + uses: actions/download-artifact@v3 + with: + path: ${{ env.REPORTS_PATH }} + - name: Check out repository code + uses: ClickHouse/checkout@v1 + with: + clear-repository: true + - name: Upgrade check + run: | + sudo rm -fr "$TEMP_PATH" + mkdir -p "$TEMP_PATH" + cp -r "$GITHUB_WORKSPACE" "$TEMP_PATH" + cd "$REPO_COPY/tests/ci" + python3 upgrade_check.py "$CHECK_NAME" + - name: Cleanup + if: always() + run: | + docker ps --quiet | xargs --no-run-if-empty docker kill ||: + docker ps --all --quiet | xargs --no-run-if-empty docker rm -f ||: + sudo rm -fr "$TEMP_PATH" + UpgradeCheckTsan: + needs: [BuilderDebTsan] + # same as for stress test with tsan + runs-on: [self-hosted, func-tester] + steps: + - name: Set envs + run: | + cat >> "$GITHUB_ENV" << 'EOF' + TEMP_PATH=${{runner.temp}}/upgrade_thread + REPORTS_PATH=${{runner.temp}}/reports_dir + CHECK_NAME=Upgrade check (tsan) + REPO_COPY=${{runner.temp}}/upgrade_thread/ClickHouse + EOF + - name: Download json reports + uses: actions/download-artifact@v3 + with: + path: ${{ env.REPORTS_PATH }} + - name: Check out repository code + uses: ClickHouse/checkout@v1 + with: + clear-repository: true + - name: Upgrade check + run: | + sudo rm -fr "$TEMP_PATH" + mkdir -p "$TEMP_PATH" + cp -r "$GITHUB_WORKSPACE" "$TEMP_PATH" + cd "$REPO_COPY/tests/ci" + python3 upgrade_check.py "$CHECK_NAME" + - name: Cleanup + if: always() + run: | + docker ps --quiet | xargs --no-run-if-empty docker kill ||: + docker ps --all --quiet | xargs --no-run-if-empty docker rm -f ||: + sudo rm -fr "$TEMP_PATH" + UpgradeCheckMsan: + needs: [BuilderDebMsan] + runs-on: [self-hosted, stress-tester] + steps: + - name: Set envs + run: | + cat >> "$GITHUB_ENV" << 'EOF' + TEMP_PATH=${{runner.temp}}/upgrade_memory + REPORTS_PATH=${{runner.temp}}/reports_dir + CHECK_NAME=Upgrade check (msan) + REPO_COPY=${{runner.temp}}/upgrade_memory/ClickHouse + EOF + - name: Download json reports + uses: actions/download-artifact@v3 + with: + path: ${{ env.REPORTS_PATH }} + - name: Check out repository code + uses: ClickHouse/checkout@v1 + with: + clear-repository: true + - name: Upgrade check + run: | + sudo rm -fr "$TEMP_PATH" + mkdir -p "$TEMP_PATH" + cp -r "$GITHUB_WORKSPACE" "$TEMP_PATH" + cd "$REPO_COPY/tests/ci" + python3 upgrade_check.py "$CHECK_NAME" + - name: Cleanup + if: always() + run: | + docker ps --quiet | xargs --no-run-if-empty docker kill ||: + docker ps --all --quiet | xargs --no-run-if-empty docker rm -f ||: + sudo rm -fr "$TEMP_PATH" + UpgradeCheckDebug: + needs: [BuilderDebDebug] + runs-on: [self-hosted, stress-tester] + steps: + - name: Set envs + run: | + cat >> "$GITHUB_ENV" << 'EOF' + TEMP_PATH=${{runner.temp}}/upgrade_debug + REPORTS_PATH=${{runner.temp}}/reports_dir + CHECK_NAME=Upgrade check (debug) + REPO_COPY=${{runner.temp}}/upgrade_debug/ClickHouse + EOF + - name: Download json reports + uses: actions/download-artifact@v3 + with: + path: ${{ env.REPORTS_PATH }} + - name: Check out repository code + uses: ClickHouse/checkout@v1 + with: + clear-repository: true + - name: Upgrade check + run: | + sudo rm -fr "$TEMP_PATH" + mkdir -p "$TEMP_PATH" + cp -r "$GITHUB_WORKSPACE" "$TEMP_PATH" + cd "$REPO_COPY/tests/ci" + python3 upgrade_check.py "$CHECK_NAME" + - name: Cleanup + if: always() + run: | + docker ps --quiet | xargs --no-run-if-empty docker kill ||: + docker ps --all --quiet | xargs --no-run-if-empty docker rm -f ||: + sudo rm -fr "$TEMP_PATH" ############################################################################################## ##################################### AST FUZZERS ############################################ ############################################################################################## diff --git a/.github/workflows/release_branches.yml b/.github/workflows/release_branches.yml index 95ef60686a7..4d2a99c2106 100644 --- a/.github/workflows/release_branches.yml +++ b/.github/workflows/release_branches.yml @@ -641,7 +641,7 @@ jobs: docker ps --all --quiet | xargs --no-run-if-empty docker rm -f ||: sudo rm -fr "$TEMP_PATH" InstallPackagesTestAarch64: - needs: [BuilderDebRelease] + needs: [BuilderDebAarch64] runs-on: [self-hosted, style-checker-aarch64] steps: - name: Set envs diff --git a/.gitignore b/.gitignore index 7a513ec1a09..14b860244c2 100644 --- a/.gitignore +++ b/.gitignore @@ -161,6 +161,7 @@ website/package-lock.json tests/queries/0_stateless/test_* tests/queries/0_stateless/*.binary tests/queries/0_stateless/*.generated-expect +tests/queries/0_stateless/*.expect.history # rust /rust/**/target diff --git a/.gitmodules b/.gitmodules index 0b88bd616fb..ca55281e643 100644 --- a/.gitmodules +++ b/.gitmodules @@ -296,6 +296,9 @@ [submodule "contrib/libdivide"] path = contrib/libdivide url = https://github.com/ridiculousfish/libdivide +[submodule "contrib/ulid-c"] + path = contrib/ulid-c + url = https://github.com/ClickHouse/ulid-c.git [submodule "contrib/aws-crt-cpp"] path = contrib/aws-crt-cpp url = https://github.com/ClickHouse/aws-crt-cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index a89619aa7ca..e22377e2332 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,192 @@ ### Table of Contents +**[ClickHouse release v23.2, 2023-02-23](#232)**
**[ClickHouse release v23.1, 2023-01-25](#231)**
**[Changelog for 2022](https://clickhouse.com/docs/en/whats-new/changelog/2022/)**
# 2023 Changelog +### ClickHouse release 23.2, 2023-02-23 + +#### Backward Incompatible Change +* Extend function "toDayOfWeek()" (alias: "DAYOFWEEK") with a mode argument that encodes whether the week starts on Monday or Sunday and whether counting starts at 0 or 1. For consistency with other date time functions, the mode argument was inserted between the time and the time zone arguments. This breaks existing usage of the (previously undocumented) 2-argument syntax "toDayOfWeek(time, time_zone)". A fix is to rewrite the function into "toDayOfWeek(time, 0, time_zone)". [#45233](https://github.com/ClickHouse/ClickHouse/pull/45233) ([Robert Schulze](https://github.com/rschu1ze)). +* Rename setting `max_query_cache_size` to `filesystem_cache_max_download_size`. [#45614](https://github.com/ClickHouse/ClickHouse/pull/45614) ([Kseniia Sumarokova](https://github.com/kssenii)). +* The `default` user will not have permissions for access type `SHOW NAMED COLLECTION` by default (e.g. `default` user will no longer be able to grant ALL to other users as it was before, therefore this PR is backward incompatible). [#46010](https://github.com/ClickHouse/ClickHouse/pull/46010) ([Kseniia Sumarokova](https://github.com/kssenii)). +* If the SETTINGS clause is specified before the FORMAT clause, the settings will be applied to formatting as well. [#46003](https://github.com/ClickHouse/ClickHouse/pull/46003) ([Azat Khuzhin](https://github.com/azat)). +* Remove support for setting `materialized_postgresql_allow_automatic_update` (which was by default turned off). [#46106](https://github.com/ClickHouse/ClickHouse/pull/46106) ([Kseniia Sumarokova](https://github.com/kssenii)). +* Slightly improve performance of `countDigits` on realistic datasets. This closed [#44518](https://github.com/ClickHouse/ClickHouse/issues/44518). In previous versions, `countDigits(0)` returned `0`; now it returns `1`, which is more correct, and follows the existing documentation. [#46187](https://github.com/ClickHouse/ClickHouse/pull/46187) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* Disallow creation of new columns compressed by a combination of codecs "Delta" or "DoubleDelta" followed by codecs "Gorilla" or "FPC". This can be bypassed using setting "allow_suspicious_codecs = true". [#45652](https://github.com/ClickHouse/ClickHouse/pull/45652) ([Robert Schulze](https://github.com/rschu1ze)). + +#### New Feature +* Add `StorageIceberg` and table function `iceberg` to access iceberg table store on S3. [#45384](https://github.com/ClickHouse/ClickHouse/pull/45384) ([flynn](https://github.com/ucasfl)). +* Allow configuring storage as `SETTINGS disk = ''` (instead of `storage_policy`) and with explicit disk creation `SETTINGS disk = disk(type=s3, ...)`. [#41976](https://github.com/ClickHouse/ClickHouse/pull/41976) ([Kseniia Sumarokova](https://github.com/kssenii)). +* Expose `ProfileEvents` counters in `system.part_log`. [#38614](https://github.com/ClickHouse/ClickHouse/pull/38614) ([Bharat Nallan](https://github.com/bharatnc)). +* Enrichment of the existing `ReplacingMergeTree` engine to allow duplicate the insertion. It leverages the power of both `ReplacingMergeTree` and `CollapsingMergeTree` in one MergeTree engine. Deleted data are not returned when queried, but not removed from disk neither. [#41005](https://github.com/ClickHouse/ClickHouse/pull/41005) ([youennL-cs](https://github.com/youennL-cs)). +* Add `generateULID` function. Closes [#36536](https://github.com/ClickHouse/ClickHouse/issues/36536). [#44662](https://github.com/ClickHouse/ClickHouse/pull/44662) ([Nikolay Degterinsky](https://github.com/evillique)). +* Add `corrMatrix` aggregate function, calculating each two columns. In addition, since Aggregatefunctions `covarSamp` and `covarPop` are similar to `corr`, I add `covarSampMatrix`, `covarPopMatrix` by the way. @alexey-milovidov closes [#44587](https://github.com/ClickHouse/ClickHouse/issues/44587). [#44680](https://github.com/ClickHouse/ClickHouse/pull/44680) ([FFFFFFFHHHHHHH](https://github.com/FFFFFFFHHHHHHH)). +* Introduce arrayShuffle function for random array permutations. [#45271](https://github.com/ClickHouse/ClickHouse/pull/45271) ([Joanna Hulboj](https://github.com/jh0x)). +* Support types `FIXED_SIZE_BINARY` type in Arrow, `FIXED_LENGTH_BYTE_ARRAY` in `Parquet` and match them to `FixedString`. Add settings `output_format_parquet_fixed_string_as_fixed_byte_array/output_format_arrow_fixed_string_as_fixed_byte_array` to control default output type for FixedString. Closes [#45326](https://github.com/ClickHouse/ClickHouse/issues/45326). [#45340](https://github.com/ClickHouse/ClickHouse/pull/45340) ([Kruglov Pavel](https://github.com/Avogar)). +* Add a new column `last_exception_time` to system.replication_queue. [#45457](https://github.com/ClickHouse/ClickHouse/pull/45457) ([Frank Chen](https://github.com/FrankChen021)). +* Add two new functions which allow for user-defined keys/seeds with SipHash{64,128}. [#45513](https://github.com/ClickHouse/ClickHouse/pull/45513) ([Salvatore Mesoraca](https://github.com/aiven-sal)). +* Allow a three-argument version for table function `format`. close [#45808](https://github.com/ClickHouse/ClickHouse/issues/45808). [#45873](https://github.com/ClickHouse/ClickHouse/pull/45873) ([FFFFFFFHHHHHHH](https://github.com/FFFFFFFHHHHHHH)). +* Add `JodaTime` format support for 'x','w','S'. Refer to https://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html. [#46073](https://github.com/ClickHouse/ClickHouse/pull/46073) ([zk_kiger](https://github.com/zk-kiger)). +* Support window function `ntile`. ([lgbo](https://github.com/lgbo-ustc)). +* Add setting `final` to implicitly apply the `FINAL` modifier to every table. [#40945](https://github.com/ClickHouse/ClickHouse/pull/40945) ([Arthur Passos](https://github.com/arthurpassos)). +* Added `arrayPartialSort` and `arrayPartialReverseSort` functions. [#46296](https://github.com/ClickHouse/ClickHouse/pull/46296) ([Joanna Hulboj](https://github.com/jh0x)). +* The new http parameter `client_protocol_version` allows setting a client protocol version for HTTP responses using the Native format. [#40397](https://github.com/ClickHouse/ClickHouse/issues/40397). [#46360](https://github.com/ClickHouse/ClickHouse/pull/46360) ([Geoff Genz](https://github.com/genzgd)). +* Add new function `regexpExtract`, like spark function `REGEXP_EXTRACT` for compatibility. It is similar to the existing function `extract`. [#46469](https://github.com/ClickHouse/ClickHouse/pull/46469) ([李扬](https://github.com/taiyang-li)). +* Add new function `JSONArrayLength`, which returns the number of elements in the outermost JSON array. The function returns NULL if the input JSON string is invalid. [#46631](https://github.com/ClickHouse/ClickHouse/pull/46631) ([李扬](https://github.com/taiyang-li)). + +#### Performance Improvement +* The introduced logic works if PREWHERE condition is a conjunction of multiple conditions (cond1 AND cond2 AND ... ). It groups those conditions that require reading the same columns into steps. After each step the corresponding part of the full condition is computed and the result rows might be filtered. This allows to read fewer rows in the next steps thus saving IO bandwidth and doing less computation. This logic is disabled by default for now. It will be enabled by default in one of the future releases once it is known to not have any regressions, so it is highly encouraged to be used for testing. It can be controlled by 2 settings: "enable_multiple_prewhere_read_steps" and "move_all_conditions_to_prewhere". [#46140](https://github.com/ClickHouse/ClickHouse/pull/46140) ([Alexander Gololobov](https://github.com/davenger)). +* An option added to aggregate partitions independently if table partition key and group by key are compatible. Controlled by the setting `allow_aggregate_partitions_independently`. Disabled by default because of limited applicability (please refer to the docs). [#45364](https://github.com/ClickHouse/ClickHouse/pull/45364) ([Nikita Taranov](https://github.com/nickitat)). +* Allow using Vertical merge algorithm with parts in Compact format. This will allow ClickHouse server to use much less memory for background operations. This closes [#46084](https://github.com/ClickHouse/ClickHouse/issues/46084). [#45681](https://github.com/ClickHouse/ClickHouse/pull/45681) [#46282](https://github.com/ClickHouse/ClickHouse/pull/46282) ([Anton Popov](https://github.com/CurtizJ)). +* Optimize `Parquet` reader by using batch reader. [#45878](https://github.com/ClickHouse/ClickHouse/pull/45878) ([LiuNeng](https://github.com/liuneng1994)). +* Add new `local_filesystem_read_method` method `io_uring` based on the asynchronous Linux [io_uring](https://kernel.dk/io_uring.pdf) subsystem, improving read performance almost universally compared to the default `pread` method. [#38456](https://github.com/ClickHouse/ClickHouse/pull/38456) ([Saulius Valatka](https://github.com/sauliusvl)). +* Rewrite aggregate functions with `if` expression as argument when logically equivalent. For example, `avg(if(cond, col, null))` can be rewritten to avgIf(cond, col). It is helpful in performance. [#44730](https://github.com/ClickHouse/ClickHouse/pull/44730) ([李扬](https://github.com/taiyang-li)). +* Improve lower/upper function performance with avx512 instructions. [#37894](https://github.com/ClickHouse/ClickHouse/pull/37894) ([yaqi-zhao](https://github.com/yaqi-zhao)). +* Remove the limitation that on systems with >=32 cores and SMT disabled ClickHouse uses only half of the cores (the case when you disable Hyper Threading in BIOS). [#44973](https://github.com/ClickHouse/ClickHouse/pull/44973) ([Robert Schulze](https://github.com/rschu1ze)). +* Improve performance of function `multiIf` by columnar executing, speed up by 2.3x. [#45296](https://github.com/ClickHouse/ClickHouse/pull/45296) ([李扬](https://github.com/taiyang-li)). +* Add fast path for function `position` when the needle is empty. [#45382](https://github.com/ClickHouse/ClickHouse/pull/45382) ([李扬](https://github.com/taiyang-li)). +* Enable `query_plan_remove_redundant_sorting` optimization by default. Optimization implemented in [#45420](https://github.com/ClickHouse/ClickHouse/issues/45420). [#45567](https://github.com/ClickHouse/ClickHouse/pull/45567) ([Igor Nikonov](https://github.com/devcrafter)). +* Increased HTTP Transfer Encoding chunk size to improve performance of large queries using the HTTP interface. [#45593](https://github.com/ClickHouse/ClickHouse/pull/45593) ([Geoff Genz](https://github.com/genzgd)). +* Fixed performance of short `SELECT` queries that read from tables with large number of `Array`/`Map`/`Nested` columns. [#45630](https://github.com/ClickHouse/ClickHouse/pull/45630) ([Anton Popov](https://github.com/CurtizJ)). +* Improve performance of filtering for big integers and decimal types. [#45949](https://github.com/ClickHouse/ClickHouse/pull/45949) ([李扬](https://github.com/taiyang-li)). +* This change could effectively reduce the overhead of obtaining the filter from ColumnNullable(UInt8) and improve the overall query performance. To evaluate the impact of this change, we adopted TPC-H benchmark but revised the column types from non-nullable to nullable, and we measured the QPS of its queries as the performance indicator. [#45962](https://github.com/ClickHouse/ClickHouse/pull/45962) ([Zhiguo Zhou](https://github.com/ZhiguoZh)). +* Make the `_part` and `_partition_id` virtual column be `LowCardinality(String)` type. Closes [#45964](https://github.com/ClickHouse/ClickHouse/issues/45964). [#45975](https://github.com/ClickHouse/ClickHouse/pull/45975) ([flynn](https://github.com/ucasfl)). +* Improve the performance of Decimal conversion when the scale does not change. [#46095](https://github.com/ClickHouse/ClickHouse/pull/46095) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* Allow to increase prefetching for read data. [#46168](https://github.com/ClickHouse/ClickHouse/pull/46168) ([Kseniia Sumarokova](https://github.com/kssenii)). +* Rewrite `arrayExists(x -> x = 1, arr)` -> `has(arr, 1)`, which improve performance by 1.34x. [#46188](https://github.com/ClickHouse/ClickHouse/pull/46188) ([李扬](https://github.com/taiyang-li)). +* Fix too big memory usage for vertical merges on non-remote disk. Respect `max_insert_delayed_streams_for_parallel_write` for the remote disk. [#46275](https://github.com/ClickHouse/ClickHouse/pull/46275) ([Nikolai Kochetov](https://github.com/KochetovNicolai)). +* Update zstd to v1.5.4. It has some minor improvements in performance and compression ratio. If you run replicas with different versions of ClickHouse you may see reasonable error messages `Data after merge/mutation is not byte-identical to data on another replicas.` with explanation. These messages are Ok and you should not worry. [#46280](https://github.com/ClickHouse/ClickHouse/pull/46280) ([Raúl Marín](https://github.com/Algunenano)). +* Fix performance degradation caused by [#39737](https://github.com/ClickHouse/ClickHouse/issues/39737). [#46309](https://github.com/ClickHouse/ClickHouse/pull/46309) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* The `replicas_status` handle will answer quickly even in case of a large replication queue. [#46310](https://github.com/ClickHouse/ClickHouse/pull/46310) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* Add avx512 support for aggregate function `sum`, function unary arithmetic, function comparison. [#37870](https://github.com/ClickHouse/ClickHouse/pull/37870) ([zhao zhou](https://github.com/zzachimed)). +* Rewrote the code around marks distribution and the overall coordination of the reading in order to achieve the maximum performance improvement. This closes [#34527](https://github.com/ClickHouse/ClickHouse/issues/34527). [#43772](https://github.com/ClickHouse/ClickHouse/pull/43772) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)). +* Remove redundant DISTINCT clauses in query (subqueries). Implemented on top of query plan. It does similar optimization as `optimize_duplicate_order_by_and_distinct` regarding DISTINCT clauses. Can be enabled via `query_plan_remove_redundant_distinct` setting. Related to [#42648](https://github.com/ClickHouse/ClickHouse/issues/42648). [#44176](https://github.com/ClickHouse/ClickHouse/pull/44176) ([Igor Nikonov](https://github.com/devcrafter)). +* A few query rewrite optimizations: `sumIf(123, cond) -> 123 * countIf(1, cond)`, `sum(if(cond, 123, 0)) -> 123 * countIf(cond)`, `sum(if(cond, 0, 123)) -> 123 * countIf(not(cond))` [#44728](https://github.com/ClickHouse/ClickHouse/pull/44728) ([李扬](https://github.com/taiyang-li)). +* Improved how memory bound merging and aggregation in order on top query plan interact. Previously we fell back to explicit sorting for AIO in some cases when it wasn't actually needed. [#45892](https://github.com/ClickHouse/ClickHouse/pull/45892) ([Nikita Taranov](https://github.com/nickitat)). +* Concurrent merges are scheduled using round-robin by default to ensure fair and starvation-free operation. Previously in heavily overloaded shards, big merges could possibly be starved by smaller merges due to the use of strict priority scheduling. Added `background_merges_mutations_scheduling_policy` server config option to select scheduling algorithm (`round_robin` or `shortest_task_first`). [#46247](https://github.com/ClickHouse/ClickHouse/pull/46247) ([Sergei Trifonov](https://github.com/serxa)). + +#### Improvement +* Enable retries for INSERT by default in case of ZooKeeper session loss. We already use it in production. [#46308](https://github.com/ClickHouse/ClickHouse/pull/46308) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* Add ability to ignore unknown keys in JSON object for named tuples (`input_format_json_ignore_unknown_keys_in_named_tuple`). [#45678](https://github.com/ClickHouse/ClickHouse/pull/45678) ([Azat Khuzhin](https://github.com/azat)). +* Support optimizing the `where` clause with sorting key expression move to `prewhere` for query with `final`. [#38893](https://github.com/ClickHouse/ClickHouse/issues/38893). [#38950](https://github.com/ClickHouse/ClickHouse/pull/38950) ([hexiaoting](https://github.com/hexiaoting)). +* Add new metrics for backups: num_processed_files and processed_files_size described actual number of processed files. [#42244](https://github.com/ClickHouse/ClickHouse/pull/42244) ([Aleksandr](https://github.com/AVMusorin)). +* Added retries on interserver DNS errors. [#43179](https://github.com/ClickHouse/ClickHouse/pull/43179) ([Anton Kozlov](https://github.com/tonickkozlov)). +* Keeper improvement: try preallocating space on the disk to avoid undefined out-of-space issues. Introduce setting `max_log_file_size` for the maximum size of Keeper's Raft log files. [#44370](https://github.com/ClickHouse/ClickHouse/pull/44370) ([Antonio Andelic](https://github.com/antonio2368)). +* Optimize behavior for a replica delay api logic in case the replica is read-only. [#45148](https://github.com/ClickHouse/ClickHouse/pull/45148) ([mateng915](https://github.com/mateng0915)). +* Ask for the password in clickhouse-client interactively in a case when the empty password is wrong. Closes [#46702](https://github.com/ClickHouse/ClickHouse/issues/46702). [#46730](https://github.com/ClickHouse/ClickHouse/pull/46730) ([Nikolay Degterinsky](https://github.com/evillique)). +* Mark `Gorilla` compression on columns of non-Float* type as suspicious. [#45376](https://github.com/ClickHouse/ClickHouse/pull/45376) ([Robert Schulze](https://github.com/rschu1ze)). +* Show replica name that is executing a merge in the `postpone_reason` column. [#45458](https://github.com/ClickHouse/ClickHouse/pull/45458) ([Frank Chen](https://github.com/FrankChen021)). +* Save exception stack trace in part_log. [#45459](https://github.com/ClickHouse/ClickHouse/pull/45459) ([Frank Chen](https://github.com/FrankChen021)). +* The `regexp_tree` dictionary is polished and now it is compatible with https://github.com/ua-parser/uap-core. [#45631](https://github.com/ClickHouse/ClickHouse/pull/45631) ([Han Fei](https://github.com/hanfei1991)). +* Updated checking of `SYSTEM SYNC REPLICA`, resolves [#45508](https://github.com/ClickHouse/ClickHouse/issues/45508) [#45648](https://github.com/ClickHouse/ClickHouse/pull/45648) ([SmitaRKulkarni](https://github.com/SmitaRKulkarni)). +* Rename setting `replication_alter_partitions_sync` to `alter_sync`. [#45659](https://github.com/ClickHouse/ClickHouse/pull/45659) ([Antonio Andelic](https://github.com/antonio2368)). +* The `generateRandom` table function and the engine now support `LowCardinality` data types. This is useful for testing, for example you can write `INSERT INTO table SELECT * FROM generateRandom() LIMIT 1000`. This is needed to debug [#45590](https://github.com/ClickHouse/ClickHouse/issues/45590). [#45661](https://github.com/ClickHouse/ClickHouse/pull/45661) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* The experimental query result cache now provides more modular configuration settings. [#45679](https://github.com/ClickHouse/ClickHouse/pull/45679) ([Robert Schulze](https://github.com/rschu1ze)). +* Renamed "query result cache" to "query cache". [#45682](https://github.com/ClickHouse/ClickHouse/pull/45682) ([Robert Schulze](https://github.com/rschu1ze)). +* add `SYSTEM SYNC FILE CACHE` command. It will do the `sync` syscall. [#8921](https://github.com/ClickHouse/ClickHouse/issues/8921). [#45685](https://github.com/ClickHouse/ClickHouse/pull/45685) ([DR](https://github.com/freedomDR)). +* Add a new S3 setting `allow_head_object_request`. This PR makes usage of `GetObjectAttributes` request instead of `HeadObject` introduced in https://github.com/ClickHouse/ClickHouse/pull/45288 optional (and disabled by default). [#45701](https://github.com/ClickHouse/ClickHouse/pull/45701) ([Vitaly Baranov](https://github.com/vitlibar)). +* Add ability to override connection settings based on connection names (that said that now you can forget about storing password for each connection, you can simply put everything into `~/.clickhouse-client/config.xml` and even use different history files for them, which can be also useful). [#45715](https://github.com/ClickHouse/ClickHouse/pull/45715) ([Azat Khuzhin](https://github.com/azat)). +* Arrow format: support the duration type. Closes [#45669](https://github.com/ClickHouse/ClickHouse/issues/45669). [#45750](https://github.com/ClickHouse/ClickHouse/pull/45750) ([flynn](https://github.com/ucasfl)). +* Extend the logging in the Query Cache to improve investigations of the caching behavior. [#45751](https://github.com/ClickHouse/ClickHouse/pull/45751) ([Robert Schulze](https://github.com/rschu1ze)). +* The query cache's server-level settings are now reconfigurable at runtime. [#45758](https://github.com/ClickHouse/ClickHouse/pull/45758) ([Robert Schulze](https://github.com/rschu1ze)). +* Hide password in logs when a table function's arguments are specified with a named collection. [#45774](https://github.com/ClickHouse/ClickHouse/pull/45774) ([Vitaly Baranov](https://github.com/vitlibar)). +* Improve internal S3 client to correctly deduce regions and redirections for different types of URLs. [#45783](https://github.com/ClickHouse/ClickHouse/pull/45783) ([Antonio Andelic](https://github.com/antonio2368)). +* Add support for Map, IPv4 and IPv6 types in generateRandom. Mostly useful for testing. [#45785](https://github.com/ClickHouse/ClickHouse/pull/45785) ([Raúl Marín](https://github.com/Algunenano)). +* Support empty/notEmpty for IP types. [#45799](https://github.com/ClickHouse/ClickHouse/pull/45799) ([Yakov Olkhovskiy](https://github.com/yakov-olkhovskiy)). +* The column `num_processed_files` was split into two columns: `num_files` (for BACKUP) and `files_read` (for RESTORE). The column `processed_files_size` was split into two columns: `total_size` (for BACKUP) and `bytes_read` (for RESTORE). [#45800](https://github.com/ClickHouse/ClickHouse/pull/45800) ([Vitaly Baranov](https://github.com/vitlibar)). +* Add support for `SHOW ENGINES` query for MySQL compatibility. [#45859](https://github.com/ClickHouse/ClickHouse/pull/45859) ([Filatenkov Artur](https://github.com/FArthur-cmd)). +* Improved how the obfuscator deals with queries. [#45867](https://github.com/ClickHouse/ClickHouse/pull/45867) ([Raúl Marín](https://github.com/Algunenano)). +* Improve behaviour of conversion into Date for boundary value 65535 (2149-06-06). [#46042](https://github.com/ClickHouse/ClickHouse/pull/46042) [#45914](https://github.com/ClickHouse/ClickHouse/pull/45914) ([Joanna Hulboj](https://github.com/jh0x)). +* Add setting `check_referential_table_dependencies` to check referential dependencies on `DROP TABLE`. This PR solves [#38326](https://github.com/ClickHouse/ClickHouse/issues/38326). [#45936](https://github.com/ClickHouse/ClickHouse/pull/45936) ([Vitaly Baranov](https://github.com/vitlibar)). +* Fix `tupleElement` to return `Null` when having `Null` argument. Closes [#45894](https://github.com/ClickHouse/ClickHouse/issues/45894). [#45952](https://github.com/ClickHouse/ClickHouse/pull/45952) ([flynn](https://github.com/ucasfl)). +* Throw an error on no files satisfying the S3 wildcard. Closes [#45587](https://github.com/ClickHouse/ClickHouse/issues/45587). [#45957](https://github.com/ClickHouse/ClickHouse/pull/45957) ([chen](https://github.com/xiedeyantu)). +* Use cluster state data to check concurrent backup/restore. [#45982](https://github.com/ClickHouse/ClickHouse/pull/45982) ([SmitaRKulkarni](https://github.com/SmitaRKulkarni)). +* ClickHouse Client: Use "exact" matching for fuzzy search, which has correct case ignorance and more appropriate algorithm for matching SQL queries. [#46000](https://github.com/ClickHouse/ClickHouse/pull/46000) ([Azat Khuzhin](https://github.com/azat)). +* Forbid wrong create View syntax `CREATE View X TO Y AS SELECT`. Closes [#4331](https://github.com/ClickHouse/ClickHouse/issues/4331). [#46043](https://github.com/ClickHouse/ClickHouse/pull/46043) ([flynn](https://github.com/ucasfl)). +* Storage `Log` family support setting the `storage_policy`. Closes [#43421](https://github.com/ClickHouse/ClickHouse/issues/43421). [#46044](https://github.com/ClickHouse/ClickHouse/pull/46044) ([flynn](https://github.com/ucasfl)). +* Improve `JSONColumns` format when the result is empty. Closes [#46024](https://github.com/ClickHouse/ClickHouse/issues/46024). [#46053](https://github.com/ClickHouse/ClickHouse/pull/46053) ([flynn](https://github.com/ucasfl)). +* Add reference implementation for SipHash128. [#46065](https://github.com/ClickHouse/ClickHouse/pull/46065) ([Salvatore Mesoraca](https://github.com/aiven-sal)). +* Add a new metric to record allocations times and bytes using mmap. [#46068](https://github.com/ClickHouse/ClickHouse/pull/46068) ([李扬](https://github.com/taiyang-li)). +* Currently for functions like `leftPad`, `rightPad`, `leftPadUTF8`, `rightPadUTF8`, the second argument `length` must be UInt8|16|32|64|128|256. Which is too strict for clickhouse users, besides, it is not consistent with other similar functions like `arrayResize`, `substring` and so on. [#46103](https://github.com/ClickHouse/ClickHouse/pull/46103) ([李扬](https://github.com/taiyang-li)). +* Fix assertion in the `welchTTest` function in debug build when the resulting statistics is NaN. Unified the behavior with other similar functions. Change the behavior of `studentTTest` to return NaN instead of throwing an exception because the previous behavior was inconvenient. This closes [#41176](https://github.com/ClickHouse/ClickHouse/issues/41176) This closes [#42162](https://github.com/ClickHouse/ClickHouse/issues/42162). [#46141](https://github.com/ClickHouse/ClickHouse/pull/46141) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* More convenient usage of big integers and ORDER BY WITH FILL. Allow using plain integers for start and end points in WITH FILL when ORDER BY big (128-bit and 256-bit) integers. Fix the wrong result for big integers with negative start or end points. This closes [#16733](https://github.com/ClickHouse/ClickHouse/issues/16733). [#46152](https://github.com/ClickHouse/ClickHouse/pull/46152) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* Add `parts`, `active_parts` and `total_marks` columns to `system.tables` on [issue](https://github.com/ClickHouse/ClickHouse/issues/44336). [#46161](https://github.com/ClickHouse/ClickHouse/pull/46161) ([attack204](https://github.com/attack204)). +* Functions "multi[Fuzzy]Match(Any|AnyIndex|AllIndices}" now reject regexes which will likely evaluate very slowly in vectorscan. [#46167](https://github.com/ClickHouse/ClickHouse/pull/46167) ([Robert Schulze](https://github.com/rschu1ze)). +* When `insert_null_as_default` is enabled and column doesn't have defined default value, the default of column type will be used. Also this PR fixes using default values on nulls in case of LowCardinality columns. [#46171](https://github.com/ClickHouse/ClickHouse/pull/46171) ([Kruglov Pavel](https://github.com/Avogar)). +* Prefer explicitly defined access keys for S3 clients. If `use_environment_credentials` is set to `true`, and the user has provided the access key through query or config, they will be used instead of the ones from the environment variable. [#46191](https://github.com/ClickHouse/ClickHouse/pull/46191) ([Antonio Andelic](https://github.com/antonio2368)). +* Add an alias "DATE_FORMAT()" for function "formatDateTime()" to improve compatibility with MySQL's SQL dialect, extend function `formatDateTime` with substitutions "a", "b", "c", "h", "i", "k", "l" "r", "s", "W". ### Documentation entry for user-facing changes User-readable short description: `DATE_FORMAT` is an alias of `formatDateTime`. Formats a Time according to the given Format string. Format is a constant expression, so you cannot have multiple formats for a single result column. (Provide link to [formatDateTime](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions/#formatdatetime)). [#46302](https://github.com/ClickHouse/ClickHouse/pull/46302) ([Jake Bamrah](https://github.com/JakeBamrah)). +* Add `ProfileEvents` and `CurrentMetrics` about the callback tasks for parallel replicas (`s3Cluster` and `MergeTree` tables). [#46313](https://github.com/ClickHouse/ClickHouse/pull/46313) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* Add support for `DELETE` and `UPDATE` for tables using `KeeperMap` storage engine. [#46330](https://github.com/ClickHouse/ClickHouse/pull/46330) ([Antonio Andelic](https://github.com/antonio2368)). +* Allow writing RENAME queries with query parameters. Resolves [#45778](https://github.com/ClickHouse/ClickHouse/issues/45778). [#46407](https://github.com/ClickHouse/ClickHouse/pull/46407) ([Nikolay Degterinsky](https://github.com/evillique)). +* Fix parameterized SELECT queries with REPLACE transformer. Resolves [#33002](https://github.com/ClickHouse/ClickHouse/issues/33002). [#46420](https://github.com/ClickHouse/ClickHouse/pull/46420) ([Nikolay Degterinsky](https://github.com/evillique)). +* Exclude the internal database used for temporary/external tables from the calculation of asynchronous metric "NumberOfDatabases". This makes the behavior consistent with system table "system.databases". [#46435](https://github.com/ClickHouse/ClickHouse/pull/46435) ([Robert Schulze](https://github.com/rschu1ze)). +* Added `last_exception_time` column into distribution_queue table. [#46564](https://github.com/ClickHouse/ClickHouse/pull/46564) ([Aleksandr](https://github.com/AVMusorin)). +* Support for IN clause with parameter in parameterized views. [#46583](https://github.com/ClickHouse/ClickHouse/pull/46583) ([SmitaRKulkarni](https://github.com/SmitaRKulkarni)). +* Do not load named collections on server startup (load them on first access instead). [#46607](https://github.com/ClickHouse/ClickHouse/pull/46607) ([Kseniia Sumarokova](https://github.com/kssenii)). + + +#### Build/Testing/Packaging Improvement +* Introduce GWP-ASan implemented by the LLVM runtime. This closes [#27039](https://github.com/ClickHouse/ClickHouse/issues/27039). [#45226](https://github.com/ClickHouse/ClickHouse/pull/45226) ([Han Fei](https://github.com/hanfei1991)). +* We want to make our tests less stable and more flaky: add randomization for merge tree settings in tests. [#38983](https://github.com/ClickHouse/ClickHouse/pull/38983) ([Anton Popov](https://github.com/CurtizJ)). +* Enable the HDFS support in PowerPC and which helps to fixes the following functional tests 02113_hdfs_assert.sh, 02244_hdfs_cluster.sql and 02368_cancel_write_into_hdfs.sh. [#44949](https://github.com/ClickHouse/ClickHouse/pull/44949) ([MeenaRenganathan22](https://github.com/MeenaRenganathan22)). +* Add systemd.service file for clickhouse-keeper. Fixes [#44293](https://github.com/ClickHouse/ClickHouse/issues/44293). [#45568](https://github.com/ClickHouse/ClickHouse/pull/45568) ([Mikhail f. Shiryaev](https://github.com/Felixoid)). +* ClickHouse's fork of poco was moved from "contrib/" to "base/poco/". [#46075](https://github.com/ClickHouse/ClickHouse/pull/46075) ([Robert Schulze](https://github.com/rschu1ze)). +* Add an option for `clickhouse-watchdog` to restart the child process. This does not make a lot of use. [#46312](https://github.com/ClickHouse/ClickHouse/pull/46312) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* If the environment variable `CLICKHOUSE_DOCKER_RESTART_ON_EXIT` is set to 1, the Docker container will run `clickhouse-server` as a child instead of the first process, and restart it when it exited. [#46391](https://github.com/ClickHouse/ClickHouse/pull/46391) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* Fix Systemd service file. [#46461](https://github.com/ClickHouse/ClickHouse/pull/46461) ([SuperDJY](https://github.com/cmsxbc)). +* Raised the minimum Clang version needed to build ClickHouse from 12 to 15. [#46710](https://github.com/ClickHouse/ClickHouse/pull/46710) ([Robert Schulze](https://github.com/rschu1ze)). +* Upgrade Intel QPL from v0.3.0 to v1.0.0 2. Build libaccel-config and link it statically to QPL library instead of dynamically. [#45809](https://github.com/ClickHouse/ClickHouse/pull/45809) ([jasperzhu](https://github.com/jinjunzh)). + + +#### Bug Fix (user-visible misbehavior in official stable or prestable release) + +* Flush data exactly by `rabbitmq_flush_interval_ms` or by `rabbitmq_max_block_size` in `StorageRabbitMQ`. Closes [#42389](https://github.com/ClickHouse/ClickHouse/issues/42389). Closes [#45160](https://github.com/ClickHouse/ClickHouse/issues/45160). [#44404](https://github.com/ClickHouse/ClickHouse/pull/44404) ([Kseniia Sumarokova](https://github.com/kssenii)). +* Use PODArray to render in sparkBar function, so we can control the memory usage. Close [#44467](https://github.com/ClickHouse/ClickHouse/issues/44467). [#44489](https://github.com/ClickHouse/ClickHouse/pull/44489) ([Duc Canh Le](https://github.com/canhld94)). +* Fix functions (quantilesExactExclusive, quantilesExactInclusive) return unsorted array element. [#45379](https://github.com/ClickHouse/ClickHouse/pull/45379) ([wujunfu](https://github.com/wujunfu)). +* Fix uncaught exception in HTTPHandler when open telemetry is enabled. [#45456](https://github.com/ClickHouse/ClickHouse/pull/45456) ([Frank Chen](https://github.com/FrankChen021)). +* Don't infer Dates from 8 digit numbers. It could lead to wrong data to be read. [#45581](https://github.com/ClickHouse/ClickHouse/pull/45581) ([Kruglov Pavel](https://github.com/Avogar)). +* Fixes to correctly use `odbc_bridge_use_connection_pooling` setting. [#45591](https://github.com/ClickHouse/ClickHouse/pull/45591) ([Bharat Nallan](https://github.com/bharatnc)). +* When the callback in the cache is called, it is possible that this cache is destructed. To keep it safe, we capture members by value. It's also safe for task schedule because it will be deactivated before storage is destroyed. Resolve [#45548](https://github.com/ClickHouse/ClickHouse/issues/45548). [#45601](https://github.com/ClickHouse/ClickHouse/pull/45601) ([Han Fei](https://github.com/hanfei1991)). +* Fix data corruption when codecs Delta or DoubleDelta are combined with codec Gorilla. [#45615](https://github.com/ClickHouse/ClickHouse/pull/45615) ([Robert Schulze](https://github.com/rschu1ze)). +* Correctly check types when using N-gram bloom filter index to avoid invalid reads. [#45617](https://github.com/ClickHouse/ClickHouse/pull/45617) ([Antonio Andelic](https://github.com/antonio2368)). +* A couple of segfaults have been reported around `c-ares`. They were introduced in my previous pull requests. I have fixed them with the help of Alexander Tokmakov. [#45629](https://github.com/ClickHouse/ClickHouse/pull/45629) ([Arthur Passos](https://github.com/arthurpassos)). +* Fix key description when encountering duplicate primary keys. This can happen in projections. See [#45590](https://github.com/ClickHouse/ClickHouse/issues/45590) for details. [#45686](https://github.com/ClickHouse/ClickHouse/pull/45686) ([Amos Bird](https://github.com/amosbird)). +* Set compression method and level for backup Closes [#45690](https://github.com/ClickHouse/ClickHouse/issues/45690). [#45737](https://github.com/ClickHouse/ClickHouse/pull/45737) ([Pradeep Chhetri](https://github.com/chhetripradeep)). +* Should use `select_query_typed.limitByOffset()` instead of `select_query_typed.limitOffset()`. [#45817](https://github.com/ClickHouse/ClickHouse/pull/45817) ([刘陶峰](https://github.com/taofengliu)). +* When use experimental analyzer, queries like `SELECT number FROM numbers(100) LIMIT 10 OFFSET 10;` get wrong results (empty result for this sql). That is caused by an unnecessary offset step added by planner. [#45822](https://github.com/ClickHouse/ClickHouse/pull/45822) ([刘陶峰](https://github.com/taofengliu)). +* Backward compatibility - allow implicit narrowing conversion from UInt64 to IPv4 - required for "INSERT ... VALUES ..." expression. [#45865](https://github.com/ClickHouse/ClickHouse/pull/45865) ([Yakov Olkhovskiy](https://github.com/yakov-olkhovskiy)). +* Bugfix IPv6 parser for mixed ip4 address with missed first octet (like `::.1.2.3`). [#45871](https://github.com/ClickHouse/ClickHouse/pull/45871) ([Yakov Olkhovskiy](https://github.com/yakov-olkhovskiy)). +* Add the `query_kind` column to the `system.processes` table and the `SHOW PROCESSLIST` query. Remove duplicate code. It fixes a bug: the global configuration parameter `max_concurrent_select_queries` was not respected to queries with `INTERSECT` or `EXCEPT` chains. [#45872](https://github.com/ClickHouse/ClickHouse/pull/45872) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* Fix crash in a function `stochasticLinearRegression`. Found by WingFuzz. [#45985](https://github.com/ClickHouse/ClickHouse/pull/45985) ([Nikolai Kochetov](https://github.com/KochetovNicolai)). +* Fix crash in `SELECT` queries with `INTERSECT` and `EXCEPT` modifiers that read data from tables with enabled sparse columns (controlled by setting `ratio_of_defaults_for_sparse_serialization`). [#45987](https://github.com/ClickHouse/ClickHouse/pull/45987) ([Anton Popov](https://github.com/CurtizJ)). +* Fix read in order optimization for DESC sorting with FINAL, close [#45815](https://github.com/ClickHouse/ClickHouse/issues/45815). [#46009](https://github.com/ClickHouse/ClickHouse/pull/46009) ([Vladimir C](https://github.com/vdimir)). +* Fix reading of non existing nested columns with multiple level in compact parts. [#46045](https://github.com/ClickHouse/ClickHouse/pull/46045) ([Azat Khuzhin](https://github.com/azat)). +* Fix elapsed column in system.processes (10x error). [#46047](https://github.com/ClickHouse/ClickHouse/pull/46047) ([Azat Khuzhin](https://github.com/azat)). +* Follow-up fix for Replace domain IP types (IPv4, IPv6) with native https://github.com/ClickHouse/ClickHouse/pull/43221. [#46087](https://github.com/ClickHouse/ClickHouse/pull/46087) ([Yakov Olkhovskiy](https://github.com/yakov-olkhovskiy)). +* Fix environment variable substitution in the configuration when a parameter already has a value. This closes [#46131](https://github.com/ClickHouse/ClickHouse/issues/46131). This closes [#9547](https://github.com/ClickHouse/ClickHouse/issues/9547). [#46144](https://github.com/ClickHouse/ClickHouse/pull/46144) ([pufit](https://github.com/pufit)). +* Fix incorrect predicate push down with grouping sets. Closes [#45947](https://github.com/ClickHouse/ClickHouse/issues/45947). [#46151](https://github.com/ClickHouse/ClickHouse/pull/46151) ([flynn](https://github.com/ucasfl)). +* Fix possible pipeline stuck error on `fulls_sorting_join` with constant keys. [#46175](https://github.com/ClickHouse/ClickHouse/pull/46175) ([Vladimir C](https://github.com/vdimir)). +* Never rewrite tuple functions as literals during formatting to avoid incorrect results. [#46232](https://github.com/ClickHouse/ClickHouse/pull/46232) ([Salvatore Mesoraca](https://github.com/aiven-sal)). +* Fix possible out of bounds error while reading LowCardinality(Nullable) in Arrow format. [#46270](https://github.com/ClickHouse/ClickHouse/pull/46270) ([Kruglov Pavel](https://github.com/Avogar)). +* Fix `SYSTEM UNFREEZE` queries failing with the exception `CANNOT_PARSE_INPUT_ASSERTION_FAILED`. [#46325](https://github.com/ClickHouse/ClickHouse/pull/46325) ([Aleksei Filatov](https://github.com/aalexfvk)). +* Fix possible crash which can be caused by an integer overflow while deserializing aggregating state of a function that stores HashTable. [#46349](https://github.com/ClickHouse/ClickHouse/pull/46349) ([Nikolai Kochetov](https://github.com/KochetovNicolai)). +* Fix possible `LOGICAL_ERROR` in asynchronous inserts with invalid data sent in format `VALUES`. [#46350](https://github.com/ClickHouse/ClickHouse/pull/46350) ([Anton Popov](https://github.com/CurtizJ)). +* Fixed a LOGICAL_ERROR on an attempt to execute `ALTER ... MOVE PART ... TO TABLE`. This type of query was never actually supported. [#46359](https://github.com/ClickHouse/ClickHouse/pull/46359) ([Alexander Tokmakov](https://github.com/tavplubix)). +* Fix s3Cluster schema inference in parallel distributed insert select when `parallel_distributed_insert_select` is enabled. [#46381](https://github.com/ClickHouse/ClickHouse/pull/46381) ([Kruglov Pavel](https://github.com/Avogar)). +* Fix queries like `ALTER TABLE ... UPDATE nested.arr1 = nested.arr2 ...`, where `arr1` and `arr2` are fields of the same `Nested` column. [#46387](https://github.com/ClickHouse/ClickHouse/pull/46387) ([Anton Popov](https://github.com/CurtizJ)). +* Scheduler may fail to schedule a task. If it happens, the whole MulityPartUpload should be aborted and `UploadHelper` must wait for already scheduled tasks. [#46451](https://github.com/ClickHouse/ClickHouse/pull/46451) ([Dmitry Novik](https://github.com/novikd)). +* Fix PREWHERE for Merge with different default types (fixes some `NOT_FOUND_COLUMN_IN_BLOCK` when the default type for the column differs, also allow `PREWHERE` when the type of column is the same across tables, and prohibit it, only if it differs). [#46454](https://github.com/ClickHouse/ClickHouse/pull/46454) ([Azat Khuzhin](https://github.com/azat)). +* Fix a crash that could happen when constant values are used in `ORDER BY`. Fixes [#46466](https://github.com/ClickHouse/ClickHouse/issues/46466). [#46493](https://github.com/ClickHouse/ClickHouse/pull/46493) ([Nikolai Kochetov](https://github.com/KochetovNicolai)). +* Do not throw exception if `disk` setting was specified on query level, but `storage_policy` was specified in config merge tree settings section. `disk` will override setting from config. [#46533](https://github.com/ClickHouse/ClickHouse/pull/46533) ([Kseniia Sumarokova](https://github.com/kssenii)). +* Fix an invalid processing of constant `LowCardinality` argument in function `arrayMap`. This bug could lead to a segfault in release, and logical error `Bad cast` in debug build. [#46569](https://github.com/ClickHouse/ClickHouse/pull/46569) ([Alexey Milovidov](https://github.com/alexey-milovidov)). +* fixes [#46557](https://github.com/ClickHouse/ClickHouse/issues/46557). [#46611](https://github.com/ClickHouse/ClickHouse/pull/46611) ([Alexander Gololobov](https://github.com/davenger)). +* Fix endless restarts of clickhouse-server systemd unit if server cannot start within 1m30sec (Disable timeout logic for starting clickhouse-server from systemd service). [#46613](https://github.com/ClickHouse/ClickHouse/pull/46613) ([Azat Khuzhin](https://github.com/azat)). +* Allocated during asynchronous inserts memory buffers were deallocated in the global context and MemoryTracker counters for corresponding user and query were not updated correctly. That led to false positive OOM exceptions. [#46622](https://github.com/ClickHouse/ClickHouse/pull/46622) ([Dmitry Novik](https://github.com/novikd)). +* Updated to not clear on_expression from table_join as its used by future analyze runs resolves [#45185](https://github.com/ClickHouse/ClickHouse/issues/45185). [#46487](https://github.com/ClickHouse/ClickHouse/pull/46487) ([SmitaRKulkarni](https://github.com/SmitaRKulkarni)). + + ### ClickHouse release 23.1, 2023-01-26 ### ClickHouse release 23.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index b422d7d807b..cbb666b81c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,10 +391,12 @@ if (COMPILER_CLANG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstrict-vtable-pointers") - # Set new experimental pass manager, it's a performance, build time and binary size win. - # Can be removed after https://reviews.llvm.org/D66490 merged and released to at least two versions of clang. - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-new-pass-manager") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexperimental-new-pass-manager") + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) + # Set new experimental pass manager, it's a performance, build time and binary size win. + # Can be removed after https://reviews.llvm.org/D66490 merged and released to at least two versions of clang. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-new-pass-manager") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexperimental-new-pass-manager") + endif () # We cannot afford to use LTO when compiling unit tests, and it's not enough # to only supply -fno-lto at the final linking stage. So we disable it @@ -458,7 +460,7 @@ endif () set (CMAKE_POSTFIX_VARIABLE "CMAKE_${CMAKE_BUILD_TYPE_UC}_POSTFIX") set (CMAKE_POSITION_INDEPENDENT_CODE OFF) -if (OS_LINUX AND NOT ARCH_AARCH64) +if (OS_LINUX AND NOT (ARCH_AARCH64 OR ARCH_S390X)) # Slightly more efficient code can be generated # It's disabled for ARM because otherwise ClickHouse cannot run on Android. set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-pie") diff --git a/README.md b/README.md index dee60cafb33..fcbe65e8223 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ ClickHouse® is an open-source column-oriented database management system that allows generating analytical data reports in real-time. +## How To Install (Linux, macOS, FreeBSD) +``` +curl https://clickhouse.com/ | sh +``` + ## Useful Links * [Official website](https://clickhouse.com/) has a quick high-level overview of ClickHouse on the main page. @@ -9,14 +14,13 @@ ClickHouse® is an open-source column-oriented database management system that a * [Tutorial](https://clickhouse.com/docs/en/getting_started/tutorial/) shows how to set up and query a small ClickHouse cluster. * [Documentation](https://clickhouse.com/docs/en/) provides more in-depth information. * [YouTube channel](https://www.youtube.com/c/ClickHouseDB) has a lot of content about ClickHouse in video format. -* [Slack](https://clickhousedb.slack.com/) and [Telegram](https://telegram.me/clickhouse_en) allow chatting with ClickHouse users in real-time. +* [Slack](https://join.slack.com/t/clickhousedb/shared_invite/zt-1gh9ds7f4-PgDhJAaF8ad5RbWBAAjzFg) and [Telegram](https://telegram.me/clickhouse_en) allow chatting with ClickHouse users in real-time. * [Blog](https://clickhouse.com/blog/) contains various ClickHouse-related articles, as well as announcements and reports about events. * [Code Browser (Woboq)](https://clickhouse.com/codebrowser/ClickHouse/index.html) with syntax highlight and navigation. * [Code Browser (github.dev)](https://github.dev/ClickHouse/ClickHouse) with syntax highlight, powered by github.dev. * [Contacts](https://clickhouse.com/company/contact) can help to get your questions answered if there are any. ## Upcoming Events -* [**ClickHouse Workshop**](https://clickhouse.com/company/events/2023-02-15-clickhouse-workshop?utm_source=github&utm_medium=social&utm_campaign=workshop) - Feb 15 & 16 - In this 2-day (3 hrs per day) free training, topics range from introductory content to a deep dive on interacting with and understanding your data. There will be both live training and hands-on labs. * [**v23.2 Release Webinar**](https://clickhouse.com/company/events/v23-2-release-webinar?utm_source=github&utm_medium=social&utm_campaign=release-webinar-2023-02) - Feb 23 - 23.2 is rapidly approaching. Original creator, co-founder, and CTO of ClickHouse Alexey Milovidov will walk us through the highlights of the release. * [**ClickHouse Meetup in Amsterdam**](https://www.meetup.com/clickhouse-netherlands-user-group/events/291485868/) - Mar 9 - The first ClickHouse Amsterdam Meetup of 2023 is here! 🎉 Join us for short lightning talks and long discussions. Food, drinks & good times on us. * [**ClickHouse Meetup in SF Bay Area**](https://www.meetup.com/clickhouse-silicon-valley-meetup-group/events/291490121/) - Mar 14 - A night to meet with ClickHouse team in the San Francisco area! Food and drink are a given...but networking is the primary focus. diff --git a/SECURITY.md b/SECURITY.md index 0fd72971d30..7c6648c70eb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -13,9 +13,10 @@ The following versions of ClickHouse server are currently being supported with s | Version | Supported | |:-|:-| +| 23.2 | ✔️ | | 23.1 | ✔️ | | 22.12 | ✔️ | -| 22.11 | ✔️ | +| 22.11 | ❌ | | 22.10 | ❌ | | 22.9 | ❌ | | 22.8 | ✔️ | diff --git a/base/base/bit_cast.h b/base/base/bit_cast.h index 8198991e98e..5373ead36e8 100644 --- a/base/base/bit_cast.h +++ b/base/base/bit_cast.h @@ -12,21 +12,22 @@ template std::decay_t bit_cast(const From & from) { - /** - * Assume the source value is 0xAABBCCDD (i.e. sizeof(from) == 4). - * Its BE representation is 0xAABBCCDD, the LE representation is 0xDDCCBBAA. - * Further assume, sizeof(res) == 8 and that res is initially zeroed out. - * With LE, the result after bit_cast will be 0xDDCCBBAA00000000 --> input value == output value. - * With BE, the result after bit_cast will be 0x00000000AABBCCDD --> input value == output value. - */ + /** Assume the source value is 0xAABBCCDD (i.e. sizeof(from) == 4). + * Its BE representation is 0xAABBCCDD, the LE representation is 0xDDCCBBAA. + * Further assume, sizeof(res) == 8 and that res is initially zeroed out. + * With LE, the result after bit_cast will be 0xDDCCBBAA00000000 --> input value == output value. + * With BE, the result after bit_cast will be 0x00000000AABBCCDD --> input value == output value. + */ To res {}; if constexpr (std::endian::native == std::endian::little) - memcpy(static_cast(&res), &from, std::min(sizeof(res), sizeof(from))); + { + memcpy(static_cast(&res), &from, std::min(sizeof(res), sizeof(from))); + } else { - uint32_t offset_to = (sizeof(res) > sizeof(from)) ? (sizeof(res) - sizeof(from)) : 0; - uint32_t offset_from = (sizeof(from) > sizeof(res)) ? (sizeof(from) - sizeof(res)) : 0; - memcpy(reinterpret_cast(&res) + offset_to, reinterpret_cast(&from) + offset_from, std::min(sizeof(res), sizeof(from))); + uint32_t offset_to = (sizeof(res) > sizeof(from)) ? (sizeof(res) - sizeof(from)) : 0; + uint32_t offset_from = (sizeof(from) > sizeof(res)) ? (sizeof(from) - sizeof(res)) : 0; + memcpy(reinterpret_cast(&res) + offset_to, reinterpret_cast(&from) + offset_from, std::min(sizeof(res), sizeof(from))); } return res; } diff --git a/base/base/types.h b/base/base/types.h index e178653f7c6..5825c8ae7ad 100644 --- a/base/base/types.h +++ b/base/base/types.h @@ -13,11 +13,7 @@ using char8_t = unsigned char; #endif /// This is needed for more strict aliasing. https://godbolt.org/z/xpJBSb https://stackoverflow.com/a/57453713 -#if !defined(PVS_STUDIO) /// But PVS-Studio does not treat it correctly. using UInt8 = char8_t; -#else -using UInt8 = uint8_t; -#endif using UInt16 = uint16_t; using UInt32 = uint32_t; diff --git a/base/glibc-compatibility/glibc-compatibility.c b/base/glibc-compatibility/glibc-compatibility.c index bae03ad590a..7e8ea5051d7 100644 --- a/base/glibc-compatibility/glibc-compatibility.c +++ b/base/glibc-compatibility/glibc-compatibility.c @@ -195,7 +195,6 @@ long splice(int fd_in, off_t *off_in, int fd_out, off_t *off_out, size_t len, un #include #include -#if !defined(__aarch64__) struct statx { uint32_t stx_mask; uint32_t stx_blksize; @@ -226,7 +225,6 @@ int statx(int fd, const char *restrict path, int flag, { return syscall(SYS_statx, fd, path, flag, mask, statxbuf); } -#endif #include diff --git a/base/glibc-compatibility/musl/fallocate.c b/base/glibc-compatibility/musl/fallocate.c index 31e63822c94..2369f157436 100644 --- a/base/glibc-compatibility/musl/fallocate.c +++ b/base/glibc-compatibility/musl/fallocate.c @@ -8,3 +8,8 @@ int fallocate(int fd, int mode, off_t base, off_t len) { return syscall(SYS_fallocate, fd, mode, base, len); } + +int fallocate64(int fd, int mode, off_t base, off_t len) +{ + return fallocate(fd, mode, base, len); +} diff --git a/base/glibc-compatibility/musl/lgamma.c b/base/glibc-compatibility/musl/lgamma.c index 5e959504e29..fb9d105d0fa 100644 --- a/base/glibc-compatibility/musl/lgamma.c +++ b/base/glibc-compatibility/musl/lgamma.c @@ -78,9 +78,6 @@ * */ -// Disable warnings by PVS-Studio -//-V::GA - static const double pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ diff --git a/base/glibc-compatibility/musl/lgammal.c b/base/glibc-compatibility/musl/lgammal.c index 775559f13b6..b158748ce1f 100644 --- a/base/glibc-compatibility/musl/lgammal.c +++ b/base/glibc-compatibility/musl/lgammal.c @@ -85,9 +85,6 @@ * */ -// Disable warnings by PVS-Studio -//-V::GA - #include #include #include "libm.h" diff --git a/base/glibc-compatibility/musl/libm.h b/base/glibc-compatibility/musl/libm.h index e5029318693..55520c2fb03 100644 --- a/base/glibc-compatibility/musl/libm.h +++ b/base/glibc-compatibility/musl/libm.h @@ -155,7 +155,7 @@ static inline long double fp_barrierl(long double x) static inline void fp_force_evalf(float x) { volatile float y; - y = x; //-V1001 + y = x; } #endif @@ -164,7 +164,7 @@ static inline void fp_force_evalf(float x) static inline void fp_force_eval(double x) { volatile double y; - y = x; //-V1001 + y = x; } #endif @@ -173,7 +173,7 @@ static inline void fp_force_eval(double x) static inline void fp_force_evall(long double x) { volatile long double y; - y = x; //-V1001 + y = x; } #endif diff --git a/base/glibc-compatibility/musl/powf.c b/base/glibc-compatibility/musl/powf.c index 35dc3611b94..de8fab54554 100644 --- a/base/glibc-compatibility/musl/powf.c +++ b/base/glibc-compatibility/musl/powf.c @@ -3,9 +3,6 @@ * SPDX-License-Identifier: MIT */ -// Disable warnings by PVS-Studio -//-V::GA - #include #include #include "libm.h" diff --git a/base/glibc-compatibility/musl/pwritev.c b/base/glibc-compatibility/musl/pwritev.c index 4cd31fcaea9..bdfeb572423 100644 --- a/base/glibc-compatibility/musl/pwritev.c +++ b/base/glibc-compatibility/musl/pwritev.c @@ -9,3 +9,8 @@ ssize_t pwritev(int fd, const struct iovec *iov, int count, off_t ofs) /// There was cancellable syscall (syscall_cp), but I don't care. return syscall(SYS_pwritev, fd, iov, count, (long)(ofs), (long)(ofs>>32)); } + +ssize_t pwritev64(int fd, const struct iovec *iov, int count, off_t ofs) +{ + return pwritev(fd, iov, count, ofs); +} diff --git a/base/pcg-random/pcg_extras.hpp b/base/pcg-random/pcg_extras.hpp index 78ce726d48b..cc11d907006 100644 --- a/base/pcg-random/pcg_extras.hpp +++ b/base/pcg-random/pcg_extras.hpp @@ -455,7 +455,7 @@ auto bounded_rand(RngType& rng, typename RngType::result_type upper_bound) typedef typename RngType::result_type rtype; rtype threshold = (RngType::max() - RngType::min() + rtype(1) - upper_bound) % upper_bound; - for (;;) { //-V1044 + for (;;) { rtype r = rng() - RngType::min(); if (r >= threshold) return r % upper_bound; diff --git a/base/pcg-random/pcg_random.hpp b/base/pcg-random/pcg_random.hpp index db7c3d7f66c..cebceee2d33 100644 --- a/base/pcg-random/pcg_random.hpp +++ b/base/pcg-random/pcg_random.hpp @@ -930,7 +930,7 @@ struct rxs_m_xs_mixin { constexpr bitcount_t shift = bits - xtypebits; constexpr bitcount_t mask = (1 << opbits) - 1; bitcount_t rshift = - opbits ? bitcount_t(internal >> (bits - opbits)) & mask : 0; //-V547 + opbits ? bitcount_t(internal >> (bits - opbits)) & mask : 0; internal ^= internal >> (opbits + rshift); internal *= mcg_multiplier::multiplier(); xtype result = internal >> shift; @@ -952,7 +952,7 @@ struct rxs_m_xs_mixin { internal *= mcg_unmultiplier::unmultiplier(); - bitcount_t rshift = opbits ? (internal >> (bits - opbits)) & mask : 0; //-V547 + bitcount_t rshift = opbits ? (internal >> (bits - opbits)) & mask : 0; internal = unxorshift(internal, bits, opbits + rshift); return internal; @@ -977,7 +977,7 @@ struct rxs_m_mixin { : 2; constexpr bitcount_t shift = bits - xtypebits; constexpr bitcount_t mask = (1 << opbits) - 1; - bitcount_t rshift = opbits ? (internal >> (bits - opbits)) & mask : 0; //-V547 + bitcount_t rshift = opbits ? (internal >> (bits - opbits)) & mask : 0; internal ^= internal >> (opbits + rshift); internal *= mcg_multiplier::multiplier(); xtype result = internal >> shift; @@ -1368,7 +1368,7 @@ void extended::selfinit() // - any strange correlations would only be apparent if we // were to backstep the generator so that the base generator // was generating the same values again - result_type xdiff = baseclass::operator()() - baseclass::operator()(); //-V501 + result_type xdiff = baseclass::operator()() - baseclass::operator()(); for (size_t i = 0; i < table_size; ++i) { data_[i] = baseclass::operator()() ^ xdiff; } diff --git a/base/poco/Crypto/CMakeLists.txt b/base/poco/Crypto/CMakeLists.txt index d11a437fc02..67171afadfb 100644 --- a/base/poco/Crypto/CMakeLists.txt +++ b/base/poco/Crypto/CMakeLists.txt @@ -21,6 +21,7 @@ if (ENABLE_SSL) -Wno-unreachable-code-return -Wno-unused-parameter -Wno-zero-as-null-pointer-constant + -Wno-used-but-marked-unused ) target_include_directories (_poco_crypto SYSTEM PUBLIC "include") target_link_libraries (_poco_crypto PUBLIC Poco::Foundation OpenSSL::SSL OpenSSL::Crypto) diff --git a/base/poco/Crypto/include/Poco/Crypto/Cipher.h b/base/poco/Crypto/include/Poco/Crypto/Cipher.h index fbe0c30ae8c..ffd993280c1 100644 --- a/base/poco/Crypto/include/Poco/Crypto/Cipher.h +++ b/base/poco/Crypto/include/Poco/Crypto/Cipher.h @@ -18,121 +18,124 @@ #define Crypto_Cipher_INCLUDED -#include "Poco/Crypto/Crypto.h" -#include "Poco/RefCountedObject.h" -#include "Poco/AutoPtr.h" #include #include #include +#include "Poco/AutoPtr.h" +#include "Poco/Crypto/Crypto.h" +#include "Poco/RefCountedObject.h" -namespace Poco { -namespace Crypto { - - -class CryptoTransform; - - -class Crypto_API Cipher: public Poco::RefCountedObject - /// Represents the abstract base class from which all implementations of - /// symmetric/asymmetric encryption algorithms must inherit. Use the CipherFactory - /// class to obtain an instance of this class: - /// - /// CipherFactory& factory = CipherFactory::defaultFactory(); - /// // Creates a 256-bit AES cipher - /// Cipher* pCipher = factory.createCipher(CipherKey("aes-256")); - /// Cipher* pRSACipher = factory.createCipher(RSAKey(RSAKey::KL_1024, RSAKey::EXP_SMALL)); - /// - /// Check the different Key constructors on how to initialize/create - /// a key. The above example auto-generates random keys. - /// - /// Note that you won't be able to decrypt data encrypted with a random key - /// once the Cipher is destroyed unless you persist the generated key and IV. - /// An example usage for random keys is to encrypt data saved in a temporary - /// file. - /// - /// Once your key is set up, you can use the Cipher object to encrypt or - /// decrypt strings or, in conjunction with a CryptoInputStream or a - /// CryptoOutputStream, to encrypt streams of data. - /// - /// Since encrypted strings will contain arbitrary binary data that will cause - /// problems in applications that are not binary-safe (eg., when sending - /// encrypted data in e-mails), the encryptString() and decryptString() can - /// encode (or decode, respectively) encrypted data using a "transport encoding". - /// Supported encodings are Base64 and BinHex. - /// - /// The following example encrypts and decrypts a string utilizing Base64 - /// encoding: - /// - /// std::string plainText = "This is my secret information"; - /// std::string encrypted = pCipher->encryptString(plainText, Cipher::ENC_BASE64); - /// std::string decrypted = pCipher->decryptString(encrypted, Cipher::ENC_BASE64); - /// - /// In order to encrypt a stream of data (eg. to encrypt files), you can use - /// a CryptoStream: - /// - /// // Create an output stream that will encrypt all data going through it - /// // and write pass it to the underlying file stream. - /// Poco::FileOutputStream sink("encrypted.dat"); - /// CryptoOutputStream encryptor(sink, pCipher->createEncryptor()); - /// - /// Poco::FileInputStream source("source.txt"); - /// Poco::StreamCopier::copyStream(source, encryptor); - /// - /// // Always close output streams to flush all internal buffers - /// encryptor.close(); - /// sink.close(); +namespace Poco +{ +namespace Crypto { -public: - typedef Poco::AutoPtr Ptr; - typedef std::vector ByteVec; - - enum Encoding - /// Transport encoding to use for encryptString() and decryptString(). - { - ENC_NONE = 0x00, /// Plain binary output - ENC_BASE64 = 0x01, /// Base64-encoded output - ENC_BINHEX = 0x02, /// BinHex-encoded output - ENC_BASE64_NO_LF = 0x81, /// Base64-encoded output, no linefeeds - ENC_BINHEX_NO_LF = 0x82 /// BinHex-encoded output, no linefeeds - - }; - - virtual ~Cipher(); - /// Destroys the Cipher. - - virtual const std::string& name() const = 0; - /// Returns the name of the Cipher. - - virtual CryptoTransform* createEncryptor() = 0; - /// Creates an encryptor object to be used with a CryptoStream. - - virtual CryptoTransform* createDecryptor() = 0; - /// Creates a decryptor object to be used with a CryptoStream. - - virtual std::string encryptString(const std::string& str, Encoding encoding = ENC_NONE); - /// Directly encrypt a string and encode it using the given encoding. - - virtual std::string decryptString(const std::string& str, Encoding encoding = ENC_NONE); - /// Directly decrypt a string that is encoded with the given encoding. - - virtual void encrypt(std::istream& source, std::ostream& sink, Encoding encoding = ENC_NONE); - /// Directly encrypts an input stream and encodes it using the given encoding. - - virtual void decrypt(std::istream& source, std::ostream& sink, Encoding encoding = ENC_NONE); - /// Directly decrypt an input stream that is encoded with the given encoding. - -protected: - Cipher(); - /// Creates a new Cipher object. - -private: - Cipher(const Cipher&); - Cipher& operator = (const Cipher&); -}; -} } // namespace Poco::Crypto + class CryptoTransform; + + + class Crypto_API Cipher : public Poco::RefCountedObject + /// Represents the abstract base class from which all implementations of + /// symmetric/asymmetric encryption algorithms must inherit. Use the CipherFactory + /// class to obtain an instance of this class: + /// + /// CipherFactory& factory = CipherFactory::defaultFactory(); + /// // Creates a 256-bit AES cipher + /// Cipher* pCipher = factory.createCipher(CipherKey("aes-256")); + /// Cipher* pRSACipher = factory.createCipher(RSAKey(RSAKey::KL_1024, RSAKey::EXP_SMALL)); + /// + /// Check the different Key constructors on how to initialize/create + /// a key. The above example auto-generates random keys. + /// + /// Note that you won't be able to decrypt data encrypted with a random key + /// once the Cipher is destroyed unless you persist the generated key and IV. + /// An example usage for random keys is to encrypt data saved in a temporary + /// file. + /// + /// Once your key is set up, you can use the Cipher object to encrypt or + /// decrypt strings or, in conjunction with a CryptoInputStream or a + /// CryptoOutputStream, to encrypt streams of data. + /// + /// Since encrypted strings will contain arbitrary binary data that will cause + /// problems in applications that are not binary-safe (eg., when sending + /// encrypted data in e-mails), the encryptString() and decryptString() can + /// encode (or decode, respectively) encrypted data using a "transport encoding". + /// Supported encodings are Base64 and BinHex. + /// + /// The following example encrypts and decrypts a string utilizing Base64 + /// encoding: + /// + /// std::string plainText = "This is my secret information"; + /// std::string encrypted = pCipher->encryptString(plainText, Cipher::ENC_BASE64); + /// std::string decrypted = pCipher->decryptString(encrypted, Cipher::ENC_BASE64); + /// + /// In order to encrypt a stream of data (eg. to encrypt files), you can use + /// a CryptoStream: + /// + /// // Create an output stream that will encrypt all data going through it + /// // and write pass it to the underlying file stream. + /// Poco::FileOutputStream sink("encrypted.dat"); + /// CryptoOutputStream encryptor(sink, pCipher->createEncryptor()); + /// + /// Poco::FileInputStream source("source.txt"); + /// Poco::StreamCopier::copyStream(source, encryptor); + /// + /// // Always close output streams to flush all internal buffers + /// encryptor.close(); + /// sink.close(); + { + public: + typedef Poco::AutoPtr Ptr; + typedef std::vector ByteVec; + + enum Encoding + /// Transport encoding to use for encryptString() and decryptString(). + { + ENC_NONE = 0x00, /// Plain binary output + ENC_BASE64 = 0x01, /// Base64-encoded output + ENC_BINHEX = 0x02, /// BinHex-encoded output + ENC_BASE64_NO_LF = 0x81, /// Base64-encoded output, no linefeeds + ENC_BINHEX_NO_LF = 0x82 /// BinHex-encoded output, no linefeeds + + }; + + virtual ~Cipher(); + /// Destroys the Cipher. + + virtual const std::string & name() const = 0; + /// Returns the name of the Cipher. + + virtual CryptoTransform * createEncryptor() = 0; + /// Creates an encryptor object to be used with a CryptoStream. + + virtual CryptoTransform * createDecryptor() = 0; + /// Creates a decryptor object to be used with a CryptoStream. + + virtual std::string encryptString(const std::string & str, Encoding encoding = ENC_NONE); + /// Directly encrypt a string and encode it using the given encoding. + + virtual std::string decryptString(const std::string & str, Encoding encoding = ENC_NONE); + /// Directly decrypt a string that is encoded with the given encoding. + + virtual void encrypt(std::istream & source, std::ostream & sink, Encoding encoding = ENC_NONE); + /// Directly encrypts an input stream and encodes it using the given encoding. + + virtual void decrypt(std::istream & source, std::ostream & sink, Encoding encoding = ENC_NONE); + /// Directly decrypt an input stream that is encoded with the given encoding. + + protected: + Cipher(); + /// Creates a new Cipher object. + + private: + Cipher(const Cipher &); + Cipher & operator=(const Cipher &); + }; + + +} +} // namespace Poco::Crypto #endif // Crypto_Cipher_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/CipherFactory.h b/base/poco/Crypto/include/Poco/Crypto/CipherFactory.h index 36aa964a1e6..f32865e3461 100644 --- a/base/poco/Crypto/include/Poco/Crypto/CipherFactory.h +++ b/base/poco/Crypto/include/Poco/Crypto/CipherFactory.h @@ -21,55 +21,58 @@ #include "Poco/Crypto/Crypto.h" -namespace Poco { -namespace Crypto { - - -class Cipher; -class CipherKey; -class RSAKey; - - -class Crypto_API CipherFactory - /// A factory for Cipher objects. See the Cipher class for examples on how to - /// use the CipherFactory. +namespace Poco +{ +namespace Crypto { -public: - CipherFactory(); - /// Creates a new CipherFactory object. - - virtual ~CipherFactory(); - /// Destroys the CipherFactory. - - Cipher* createCipher(const CipherKey& key); - /// Creates a Cipher object for the given Cipher name. Valid cipher - /// names depend on the OpenSSL version the library is linked with; - /// see the output of - /// - /// openssl enc --help - /// - /// for a list of supported block and stream ciphers. - /// - /// Common examples are: - /// - /// * AES: "aes-128", "aes-256" - /// * DES: "des", "des3" - /// * Blowfish: "bf" - - Cipher* createCipher(const RSAKey& key, RSAPaddingMode paddingMode = RSA_PADDING_PKCS1); - /// Creates a RSACipher using the given RSA key and padding mode - /// for public key encryption/private key decryption. - - static CipherFactory& defaultFactory(); - /// Returns the default CipherFactory. - -private: - CipherFactory(const CipherFactory&); - CipherFactory& operator = (const CipherFactory&); -}; -} } // namespace Poco::Crypto + class Cipher; + class CipherKey; + class RSAKey; + + + class Crypto_API CipherFactory + /// A factory for Cipher objects. See the Cipher class for examples on how to + /// use the CipherFactory. + { + public: + CipherFactory(); + /// Creates a new CipherFactory object. + + virtual ~CipherFactory(); + /// Destroys the CipherFactory. + + Cipher * createCipher(const CipherKey & key); + /// Creates a Cipher object for the given Cipher name. Valid cipher + /// names depend on the OpenSSL version the library is linked with; + /// see the output of + /// + /// openssl enc --help + /// + /// for a list of supported block and stream ciphers. + /// + /// Common examples are: + /// + /// * AES: "aes-128", "aes-256" + /// * DES: "des", "des3" + /// * Blowfish: "bf" + + Cipher * createCipher(const RSAKey & key, RSAPaddingMode paddingMode = RSA_PADDING_PKCS1); + /// Creates a RSACipher using the given RSA key and padding mode + /// for public key encryption/private key decryption. + + static CipherFactory & defaultFactory(); + /// Returns the default CipherFactory. + + private: + CipherFactory(const CipherFactory &); + CipherFactory & operator=(const CipherFactory &); + }; + + +} +} // namespace Poco::Crypto #endif // Crypto_CipherFactory_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/CipherImpl.h b/base/poco/Crypto/include/Poco/Crypto/CipherImpl.h index d6e8e0e79b2..057e77a4cd9 100644 --- a/base/poco/Crypto/include/Poco/Crypto/CipherImpl.h +++ b/base/poco/Crypto/include/Poco/Crypto/CipherImpl.h @@ -18,52 +18,55 @@ #define Crypto_CipherImpl_INCLUDED -#include "Poco/Crypto/Crypto.h" +#include #include "Poco/Crypto/Cipher.h" #include "Poco/Crypto/CipherKey.h" +#include "Poco/Crypto/Crypto.h" #include "Poco/Crypto/OpenSSLInitializer.h" -#include -namespace Poco { -namespace Crypto { - - -class CipherImpl: public Cipher - /// An implementation of the Cipher class for OpenSSL's crypto library. +namespace Poco { -public: - CipherImpl(const CipherKey& key); - /// Creates a new CipherImpl object for the given CipherKey. - - virtual ~CipherImpl(); - /// Destroys the CipherImpl. - - const std::string& name() const; - /// Returns the name of the cipher. - - CryptoTransform* createEncryptor(); - /// Creates an encryptor object. - - CryptoTransform* createDecryptor(); - /// Creates a decryptor object. - -private: - CipherKey _key; - OpenSSLInitializer _openSSLInitializer; -}; - - -// -// Inlines -// -inline const std::string& CipherImpl::name() const +namespace Crypto { - return _key.name(); + + + class CipherImpl : public Cipher + /// An implementation of the Cipher class for OpenSSL's crypto library. + { + public: + CipherImpl(const CipherKey & key); + /// Creates a new CipherImpl object for the given CipherKey. + + virtual ~CipherImpl(); + /// Destroys the CipherImpl. + + const std::string & name() const; + /// Returns the name of the cipher. + + CryptoTransform * createEncryptor(); + /// Creates an encryptor object. + + CryptoTransform * createDecryptor(); + /// Creates a decryptor object. + + private: + CipherKey _key; + OpenSSLInitializer _openSSLInitializer; + }; + + + // + // Inlines + // + inline const std::string & CipherImpl::name() const + { + return _key.name(); + } + + } - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_CipherImpl_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/CipherKey.h b/base/poco/Crypto/include/Poco/Crypto/CipherKey.h index b102cc2310b..b39cb1a9294 100644 --- a/base/poco/Crypto/include/Poco/Crypto/CipherKey.h +++ b/base/poco/Crypto/include/Poco/Crypto/CipherKey.h @@ -18,184 +18,186 @@ #define Crypto_CipherKey_INCLUDED -#include "Poco/Crypto/Crypto.h" #include "Poco/Crypto/CipherKeyImpl.h" +#include "Poco/Crypto/Crypto.h" -namespace Poco { -namespace Crypto { - - -class Crypto_API CipherKey - /// CipherKey stores the key information for decryption/encryption of data. - /// To create a random key, using the following code: - /// - /// CipherKey key("aes-256"); - /// - /// Note that you won't be able to decrypt data encrypted with a random key - /// once the Cipher is destroyed unless you persist the generated key and IV. - /// An example usage for random keys is to encrypt data saved in a temporary - /// file. - /// - /// To create a key using a human-readable password - /// string, use the following code. We create a AES Cipher and - /// use a salt value to make the key more robust: - /// - /// std::string password = "secret"; - /// std::string salt("asdff8723lasdf(**923412"); - /// CipherKey key("aes-256", password, salt); - /// - /// You may also control the digest and the number of iterations used to generate the key - /// by specifying the specific values. Here we create a key with the same data as before, - /// except that we use 100 iterations instead of DEFAULT_ITERATION_COUNT, and sha1 instead of - /// the default md5: - /// - /// std::string password = "secret"; - /// std::string salt("asdff8723lasdf(**923412"); - /// std::string digest ("sha1"); - /// CipherKey key("aes-256", password, salt, 100, digest); - /// +namespace Poco { -public: - typedef CipherKeyImpl::Mode Mode; - typedef CipherKeyImpl::ByteVec ByteVec; - - enum - { - DEFAULT_ITERATION_COUNT = 2000 - /// Default iteration count to use with - /// generateKey(). RSA security recommends - /// an iteration count of at least 1000. - }; - - CipherKey(const std::string& name, - const std::string& passphrase, - const std::string& salt = "", - int iterationCount = DEFAULT_ITERATION_COUNT, - const std::string& digest = "md5"); - /// Creates a new CipherKeyImpl object using the given - /// cipher name, passphrase, salt value, iteration count and digest. - - CipherKey(const std::string& name, - const ByteVec& key, - const ByteVec& iv); - /// Creates a new CipherKeyImpl object using the given cipher - /// name, key and initialization vector (IV). - /// - /// The size of the IV must match the cipher's expected - /// IV size (see ivSize()), except for GCM mode, which allows - /// a custom IV size. - - CipherKey(const std::string& name); - /// Creates a new CipherKeyImpl object. Autoinitializes key and - /// initialization vector. - - ~CipherKey(); - /// Destroys the CipherKeyImpl. - - const std::string& name() const; - /// Returns the name of the Cipher. - - int keySize() const; - /// Returns the key size of the Cipher. - - int blockSize() const; - /// Returns the block size of the Cipher. - - int ivSize() const; - /// Returns the IV size of the Cipher. - - Mode mode() const; - /// Returns the Cipher's mode of operation. - - const ByteVec& getKey() const; - /// Returns the key for the Cipher. - - void setKey(const ByteVec& key); - /// Sets the key for the Cipher. - - const ByteVec& getIV() const; - /// Returns the initialization vector (IV) for the Cipher. - - void setIV(const ByteVec& iv); - /// Sets the initialization vector (IV) for the Cipher. - /// - /// The size of the vector must match the cipher's expected - /// IV size (see ivSize()), except for GCM mode, which allows - /// a custom IV size. - - CipherKeyImpl::Ptr impl(); - /// Returns the impl object - -private: - CipherKeyImpl::Ptr _pImpl; -}; - - -// -// inlines -// -inline const std::string& CipherKey::name() const +namespace Crypto { - return _pImpl->name(); + + + class Crypto_API CipherKey + /// CipherKey stores the key information for decryption/encryption of data. + /// To create a random key, using the following code: + /// + /// CipherKey key("aes-256"); + /// + /// Note that you won't be able to decrypt data encrypted with a random key + /// once the Cipher is destroyed unless you persist the generated key and IV. + /// An example usage for random keys is to encrypt data saved in a temporary + /// file. + /// + /// To create a key using a human-readable password + /// string, use the following code. We create a AES Cipher and + /// use a salt value to make the key more robust: + /// + /// std::string password = "secret"; + /// std::string salt("asdff8723lasdf(**923412"); + /// CipherKey key("aes-256", password, salt); + /// + /// You may also control the digest and the number of iterations used to generate the key + /// by specifying the specific values. Here we create a key with the same data as before, + /// except that we use 100 iterations instead of DEFAULT_ITERATION_COUNT, and sha1 instead of + /// the default md5: + /// + /// std::string password = "secret"; + /// std::string salt("asdff8723lasdf(**923412"); + /// std::string digest ("sha1"); + /// CipherKey key("aes-256", password, salt, 100, digest); + /// + { + public: + typedef CipherKeyImpl::Mode Mode; + typedef CipherKeyImpl::ByteVec ByteVec; + + enum + { + DEFAULT_ITERATION_COUNT = 2000 + /// Default iteration count to use with + /// generateKey(). RSA security recommends + /// an iteration count of at least 1000. + }; + + CipherKey( + const std::string & name, + const std::string & passphrase, + const std::string & salt = "", + int iterationCount = DEFAULT_ITERATION_COUNT, + const std::string & digest = "md5"); + /// Creates a new CipherKeyImpl object using the given + /// cipher name, passphrase, salt value, iteration count and digest. + + CipherKey(const std::string & name, const ByteVec & key, const ByteVec & iv); + /// Creates a new CipherKeyImpl object using the given cipher + /// name, key and initialization vector (IV). + /// + /// The size of the IV must match the cipher's expected + /// IV size (see ivSize()), except for GCM mode, which allows + /// a custom IV size. + + CipherKey(const std::string & name); + /// Creates a new CipherKeyImpl object. Autoinitializes key and + /// initialization vector. + + ~CipherKey(); + /// Destroys the CipherKeyImpl. + + const std::string & name() const; + /// Returns the name of the Cipher. + + int keySize() const; + /// Returns the key size of the Cipher. + + int blockSize() const; + /// Returns the block size of the Cipher. + + int ivSize() const; + /// Returns the IV size of the Cipher. + + Mode mode() const; + /// Returns the Cipher's mode of operation. + + const ByteVec & getKey() const; + /// Returns the key for the Cipher. + + void setKey(const ByteVec & key); + /// Sets the key for the Cipher. + + const ByteVec & getIV() const; + /// Returns the initialization vector (IV) for the Cipher. + + void setIV(const ByteVec & iv); + /// Sets the initialization vector (IV) for the Cipher. + /// + /// The size of the vector must match the cipher's expected + /// IV size (see ivSize()), except for GCM mode, which allows + /// a custom IV size. + + CipherKeyImpl::Ptr impl(); + /// Returns the impl object + + private: + CipherKeyImpl::Ptr _pImpl; + }; + + + // + // inlines + // + inline const std::string & CipherKey::name() const + { + return _pImpl->name(); + } + + + inline int CipherKey::keySize() const + { + return _pImpl->keySize(); + } + + + inline int CipherKey::blockSize() const + { + return _pImpl->blockSize(); + } + + + inline int CipherKey::ivSize() const + { + return _pImpl->ivSize(); + } + + + inline CipherKey::Mode CipherKey::mode() const + { + return _pImpl->mode(); + } + + + inline const CipherKey::ByteVec & CipherKey::getKey() const + { + return _pImpl->getKey(); + } + + + inline void CipherKey::setKey(const CipherKey::ByteVec & key) + { + _pImpl->setKey(key); + } + + + inline const CipherKey::ByteVec & CipherKey::getIV() const + { + return _pImpl->getIV(); + } + + + inline void CipherKey::setIV(const CipherKey::ByteVec & iv) + { + _pImpl->setIV(iv); + } + + + inline CipherKeyImpl::Ptr CipherKey::impl() + { + return _pImpl; + } + + } - - -inline int CipherKey::keySize() const -{ - return _pImpl->keySize(); -} - - -inline int CipherKey::blockSize() const -{ - return _pImpl->blockSize(); -} - - -inline int CipherKey::ivSize() const -{ - return _pImpl->ivSize(); -} - - -inline CipherKey::Mode CipherKey::mode() const -{ - return _pImpl->mode(); -} - - -inline const CipherKey::ByteVec& CipherKey::getKey() const -{ - return _pImpl->getKey(); -} - - -inline void CipherKey::setKey(const CipherKey::ByteVec& key) -{ - _pImpl->setKey(key); -} - - -inline const CipherKey::ByteVec& CipherKey::getIV() const -{ - return _pImpl->getIV(); -} - - -inline void CipherKey::setIV(const CipherKey::ByteVec& iv) -{ - _pImpl->setIV(iv); -} - - -inline CipherKeyImpl::Ptr CipherKey::impl() -{ - return _pImpl; -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_CipherKey_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/CipherKeyImpl.h b/base/poco/Crypto/include/Poco/Crypto/CipherKeyImpl.h index f7807aad9f8..700ae95c892 100644 --- a/base/poco/Crypto/include/Poco/Crypto/CipherKeyImpl.h +++ b/base/poco/Crypto/include/Poco/Crypto/CipherKeyImpl.h @@ -18,151 +18,151 @@ #define Crypto_CipherKeyImpl_INCLUDED +#include +#include "Poco/AutoPtr.h" #include "Poco/Crypto/Crypto.h" #include "Poco/Crypto/OpenSSLInitializer.h" #include "Poco/RefCountedObject.h" -#include "Poco/AutoPtr.h" -#include struct evp_cipher_st; typedef struct evp_cipher_st EVP_CIPHER; -namespace Poco { -namespace Crypto { - - -class CipherKeyImpl: public RefCountedObject - /// An implementation of the CipherKey class for OpenSSL's crypto library. +namespace Poco { -public: - typedef std::vector ByteVec; - typedef Poco::AutoPtr Ptr; - - enum Mode - /// Cipher mode of operation. This mode determines how multiple blocks - /// are connected; this is essential to improve security. - { - MODE_STREAM_CIPHER, /// Stream cipher - MODE_ECB, /// Electronic codebook (plain concatenation) - MODE_CBC, /// Cipher block chaining (default) - MODE_CFB, /// Cipher feedback - MODE_OFB, /// Output feedback - MODE_CTR, /// Counter mode - MODE_GCM, /// Galois/Counter mode - MODE_CCM /// Counter with CBC-MAC - }; - - CipherKeyImpl(const std::string& name, - const std::string& passphrase, - const std::string& salt, - int iterationCount, - const std::string& digest); - /// Creates a new CipherKeyImpl object, using - /// the given cipher name, passphrase, salt value - /// and iteration count. - - CipherKeyImpl(const std::string& name, - const ByteVec& key, - const ByteVec& iv); - /// Creates a new CipherKeyImpl object, using the - /// given cipher name, key and initialization vector. - - CipherKeyImpl(const std::string& name); - /// Creates a new CipherKeyImpl object. Autoinitializes key - /// and initialization vector. - - virtual ~CipherKeyImpl(); - /// Destroys the CipherKeyImpl. - - const std::string& name() const; - /// Returns the name of the Cipher. - - int keySize() const; - /// Returns the key size of the Cipher. - - int blockSize() const; - /// Returns the block size of the Cipher. - - int ivSize() const; - /// Returns the IV size of the Cipher. - - Mode mode() const; - /// Returns the Cipher's mode of operation. - - const ByteVec& getKey() const; - /// Returns the key for the Cipher. - - void setKey(const ByteVec& key); - /// Sets the key for the Cipher. - - const ByteVec& getIV() const; - /// Returns the initialization vector (IV) for the Cipher. - - void setIV(const ByteVec& iv); - /// Sets the initialization vector (IV) for the Cipher. - - const EVP_CIPHER* cipher(); - /// Returns the cipher object - -private: - void generateKey(const std::string& passphrase, - const std::string& salt, - int iterationCount); - /// Generates key and IV from a password and optional salt string. - - void generateKey(); - /// Generates key and IV from random data. - - void getRandomBytes(ByteVec& vec, std::size_t count); - /// Stores random bytes in vec. - -private: - const EVP_CIPHER* _pCipher; - const EVP_MD* _pDigest; - std::string _name; - ByteVec _key; - ByteVec _iv; - OpenSSLInitializer _openSSLInitializer; -}; - - -// -// Inlines -// -inline const std::string& CipherKeyImpl::name() const +namespace Crypto { - return _name; + + + class CipherKeyImpl : public RefCountedObject + /// An implementation of the CipherKey class for OpenSSL's crypto library. + { + public: + typedef std::vector ByteVec; + typedef Poco::AutoPtr Ptr; + + enum Mode + /// Cipher mode of operation. This mode determines how multiple blocks + /// are connected; this is essential to improve security. + { + MODE_STREAM_CIPHER, /// Stream cipher + MODE_ECB, /// Electronic codebook (plain concatenation) + MODE_CBC, /// Cipher block chaining (default) + MODE_CFB, /// Cipher feedback + MODE_OFB, /// Output feedback + MODE_CTR, /// Counter mode + MODE_GCM, /// Galois/Counter mode + MODE_CCM /// Counter with CBC-MAC + }; + + CipherKeyImpl( + const std::string & name, + const std::string & passphrase, + const std::string & salt, + int iterationCount, + const std::string & digest); + /// Creates a new CipherKeyImpl object, using + /// the given cipher name, passphrase, salt value + /// and iteration count. + + CipherKeyImpl(const std::string & name, const ByteVec & key, const ByteVec & iv); + /// Creates a new CipherKeyImpl object, using the + /// given cipher name, key and initialization vector. + + CipherKeyImpl(const std::string & name); + /// Creates a new CipherKeyImpl object. Autoinitializes key + /// and initialization vector. + + virtual ~CipherKeyImpl(); + /// Destroys the CipherKeyImpl. + + const std::string & name() const; + /// Returns the name of the Cipher. + + int keySize() const; + /// Returns the key size of the Cipher. + + int blockSize() const; + /// Returns the block size of the Cipher. + + int ivSize() const; + /// Returns the IV size of the Cipher. + + Mode mode() const; + /// Returns the Cipher's mode of operation. + + const ByteVec & getKey() const; + /// Returns the key for the Cipher. + + void setKey(const ByteVec & key); + /// Sets the key for the Cipher. + + const ByteVec & getIV() const; + /// Returns the initialization vector (IV) for the Cipher. + + void setIV(const ByteVec & iv); + /// Sets the initialization vector (IV) for the Cipher. + + const EVP_CIPHER * cipher(); + /// Returns the cipher object + + private: + void generateKey(const std::string & passphrase, const std::string & salt, int iterationCount); + /// Generates key and IV from a password and optional salt string. + + void generateKey(); + /// Generates key and IV from random data. + + void getRandomBytes(ByteVec & vec, std::size_t count); + /// Stores random bytes in vec. + + private: + const EVP_CIPHER * _pCipher; + const EVP_MD * _pDigest; + std::string _name; + ByteVec _key; + ByteVec _iv; + OpenSSLInitializer _openSSLInitializer; + }; + + + // + // Inlines + // + inline const std::string & CipherKeyImpl::name() const + { + return _name; + } + + + inline const CipherKeyImpl::ByteVec & CipherKeyImpl::getKey() const + { + return _key; + } + + + inline void CipherKeyImpl::setKey(const ByteVec & key) + { + poco_assert(key.size() == static_cast(keySize())); + _key = key; + } + + + inline const CipherKeyImpl::ByteVec & CipherKeyImpl::getIV() const + { + return _iv; + } + + + inline const EVP_CIPHER * CipherKeyImpl::cipher() + { + return _pCipher; + } + + } - - -inline const CipherKeyImpl::ByteVec& CipherKeyImpl::getKey() const -{ - return _key; -} - - -inline void CipherKeyImpl::setKey(const ByteVec& key) -{ - poco_assert(key.size() == static_cast(keySize())); - _key = key; -} - - -inline const CipherKeyImpl::ByteVec& CipherKeyImpl::getIV() const -{ - return _iv; -} - - -inline const EVP_CIPHER* CipherKeyImpl::cipher() -{ - return _pCipher; -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_CipherKeyImpl_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/Crypto.h b/base/poco/Crypto/include/Poco/Crypto/Crypto.h index d6b3ede65cb..42dc8cb137c 100644 --- a/base/poco/Crypto/include/Poco/Crypto/Crypto.h +++ b/base/poco/Crypto/include/Poco/Crypto/Crypto.h @@ -24,39 +24,37 @@ #define POCO_EXTERNAL_OPENSSL_SLPRO 2 -#include "Poco/Foundation.h" #include +#include "Poco/Foundation.h" #ifndef OPENSSL_VERSION_PREREQ - #if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR) - #define OPENSSL_VERSION_PREREQ(maj, min) \ - ((OPENSSL_VERSION_MAJOR << 16) + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min)) - #else - #define OPENSSL_VERSION_PREREQ(maj, min) \ - (OPENSSL_VERSION_NUMBER >= (((maj) << 28) | ((min) << 20))) - #endif +# if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR) +# define OPENSSL_VERSION_PREREQ(maj, min) ((OPENSSL_VERSION_MAJOR << 16) + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min)) +# else +# define OPENSSL_VERSION_PREREQ(maj, min) (OPENSSL_VERSION_NUMBER >= (((maj) << 28) | ((min) << 20))) +# endif #endif enum RSAPaddingMode - /// The padding mode used for RSA public key encryption. +/// The padding mode used for RSA public key encryption. { - RSA_PADDING_PKCS1, - /// PKCS #1 v1.5 padding. This currently is the most widely used mode. - - RSA_PADDING_PKCS1_OAEP, - /// EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty - /// encoding parameter. This mode is recommended for all new applications. - - RSA_PADDING_SSLV23, - /// PKCS #1 v1.5 padding with an SSL-specific modification that denotes - /// that the server is SSL3 capable. - - RSA_PADDING_NONE - /// Raw RSA encryption. This mode should only be used to implement cryptographically - /// sound padding modes in the application code. Encrypting user data directly with RSA - /// is insecure. + RSA_PADDING_PKCS1, + /// PKCS #1 v1.5 padding. This currently is the most widely used mode. + + RSA_PADDING_PKCS1_OAEP, + /// EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty + /// encoding parameter. This mode is recommended for all new applications. + + RSA_PADDING_SSLV23, + /// PKCS #1 v1.5 padding with an SSL-specific modification that denotes + /// that the server is SSL3 capable. + + RSA_PADDING_NONE + /// Raw RSA encryption. This mode should only be used to implement cryptographically + /// sound padding modes in the application code. Encrypting user data directly with RSA + /// is insecure. }; @@ -68,128 +66,51 @@ enum RSAPaddingMode // Crypto_API functions as being imported from a DLL, whereas this DLL sees symbols // defined with this macro as being exported. // -#if defined(_WIN32) - #if defined(POCO_DLL) - #if defined(Crypto_EXPORTS) - #define Crypto_API __declspec(dllexport) - #else - #define Crypto_API __declspec(dllimport) - #endif - #endif -#endif #if !defined(Crypto_API) - #if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4) - #define Crypto_API __attribute__ ((visibility ("default"))) - #else - #define Crypto_API - #endif +# if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined(__GNUC__) && (__GNUC__ >= 4) +# define Crypto_API __attribute__((visibility("default"))) +# else +# define Crypto_API +# endif #endif // // Automatically link Crypto and OpenSSL libraries. // -#if defined(_MSC_VER) - #if !defined(POCO_NO_AUTOMATIC_LIBS) - #if defined(POCO_INTERNAL_OPENSSL_MSVC_VER) - #if defined(POCO_EXTERNAL_OPENSSL) - #pragma message("External OpenSSL defined but internal headers used - possible mismatch!") - #endif // POCO_EXTERNAL_OPENSSL - #if !defined(_DEBUG) - #define POCO_DEBUG_SUFFIX "" - #if !defined (_DLL) - #define POCO_STATIC_SUFFIX "mt" - #else // _DLL - #define POCO_STATIC_SUFFIX "" - #endif - #else // _DEBUG - #define POCO_DEBUG_SUFFIX "d" - #if !defined (_DLL) - #define POCO_STATIC_SUFFIX "mt" - #else // _DLL - #define POCO_STATIC_SUFFIX "" - #endif - #endif - #pragma comment(lib, "libcrypto" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib") - #pragma comment(lib, "libssl" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib") - #if !defined(_WIN64) && !defined (_DLL) && \ - (POCO_INTERNAL_OPENSSL_MSVC_VER == 120) && \ - (POCO_MSVC_VERSION < POCO_INTERNAL_OPENSSL_MSVC_VER) - #pragma comment(lib, "libPreVS2013CRT" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib") - #endif - #if !defined (_DLL) && (POCO_MSVS_VERSION >= 2015) - #pragma comment(lib, "legacy_stdio_definitions.lib") - #pragma comment(lib, "legacy_stdio_wide_specifiers.lib") - #endif - #elif defined(POCO_EXTERNAL_OPENSSL) - #if POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_SLPRO - #if defined(POCO_DLL) - #if OPENSSL_VERSION_PREREQ(1,1) - #pragma comment(lib, "libcrypto.lib") - #pragma comment(lib, "libssl.lib") - #else - #pragma comment(lib, "libeay32.lib") - #pragma comment(lib, "ssleay32.lib") - #endif - #else - #if OPENSSL_VERSION_PREREQ(1,1) - #if defined(_WIN64) - #pragma comment(lib, "libcrypto64" POCO_LIB_SUFFIX) - #pragma comment(lib, "libssl64" POCO_LIB_SUFFIX) - #else - #pragma comment(lib, "libcrypto32" POCO_LIB_SUFFIX) - #pragma comment(lib, "libssl32" POCO_LIB_SUFFIX) - #endif - #else - #pragma comment(lib, "libeay32" POCO_LIB_SUFFIX) - #pragma comment(lib, "ssleay32" POCO_LIB_SUFFIX) - #endif - #endif - #elif POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_DEFAULT - #if OPENSSL_VERSION_PREREQ(1,1) - #pragma comment(lib, "libcrypto.lib") - #pragma comment(lib, "libssl.lib") - #else - #pragma comment(lib, "libeay32.lib") - #pragma comment(lib, "ssleay32.lib") - #endif - #endif - #endif // POCO_INTERNAL_OPENSSL_MSVC_VER - #if !defined(Crypto_EXPORTS) - #pragma comment(lib, "PocoCrypto" POCO_LIB_SUFFIX) - #endif - #endif // POCO_NO_AUTOMATIC_LIBS -#endif -namespace Poco { -namespace Crypto { +namespace Poco +{ +namespace Crypto +{ -void Crypto_API initializeCrypto(); - /// Initialize the Crypto library, as well as the underlying OpenSSL - /// libraries, by calling OpenSSLInitializer::initialize(). - /// - /// Should be called before using any class from the Crypto library. - /// The Crypto library will be initialized automatically, through - /// OpenSSLInitializer instances held by various Crypto classes - /// (Cipher, CipherKey, RSAKey, X509Certificate). - /// However, it is recommended to call initializeCrypto() - /// in any case at application startup. - /// - /// Can be called multiple times; however, for every call to - /// initializeCrypto(), a matching call to uninitializeCrypto() - /// must be performed. + void Crypto_API initializeCrypto(); + /// Initialize the Crypto library, as well as the underlying OpenSSL + /// libraries, by calling OpenSSLInitializer::initialize(). + /// + /// Should be called before using any class from the Crypto library. + /// The Crypto library will be initialized automatically, through + /// OpenSSLInitializer instances held by various Crypto classes + /// (Cipher, CipherKey, RSAKey, X509Certificate). + /// However, it is recommended to call initializeCrypto() + /// in any case at application startup. + /// + /// Can be called multiple times; however, for every call to + /// initializeCrypto(), a matching call to uninitializeCrypto() + /// must be performed. -void Crypto_API uninitializeCrypto(); - /// Uninitializes the Crypto library by calling - /// OpenSSLInitializer::uninitialize(). + void Crypto_API uninitializeCrypto(); + /// Uninitializes the Crypto library by calling + /// OpenSSLInitializer::uninitialize(). -} } // namespace Poco::Crypto +} +} // namespace Poco::Crypto #endif // Crypto_Crypto_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/CryptoException.h b/base/poco/Crypto/include/Poco/Crypto/CryptoException.h index 34c15111e6a..8a2ddd27405 100644 --- a/base/poco/Crypto/include/Poco/Crypto/CryptoException.h +++ b/base/poco/Crypto/include/Poco/Crypto/CryptoException.h @@ -23,34 +23,37 @@ #include "Poco/Exception.h" -namespace Poco { -namespace Crypto { - - -POCO_DECLARE_EXCEPTION(Crypto_API, CryptoException, Poco::Exception) - - -class Crypto_API OpenSSLException : public CryptoException +namespace Poco +{ +namespace Crypto { -public: - OpenSSLException(int code = 0); - OpenSSLException(const std::string& msg, int code = 0); - OpenSSLException(const std::string& msg, const std::string& arg, int code = 0); - OpenSSLException(const std::string& msg, const Poco::Exception& exc, int code = 0); - OpenSSLException(const OpenSSLException& exc); - ~OpenSSLException() throw(); - OpenSSLException& operator = (const OpenSSLException& exc); - const char* name() const throw(); - const char* className() const throw(); - Poco::Exception* clone() const; - void rethrow() const; - -private: - void setExtMessage(); -}; -} } // namespace Poco::Crypto + POCO_DECLARE_EXCEPTION(Crypto_API, CryptoException, Poco::Exception) + + + class Crypto_API OpenSSLException : public CryptoException + { + public: + OpenSSLException(int code = 0); + OpenSSLException(const std::string & msg, int code = 0); + OpenSSLException(const std::string & msg, const std::string & arg, int code = 0); + OpenSSLException(const std::string & msg, const Poco::Exception & exc, int code = 0); + OpenSSLException(const OpenSSLException & exc); + ~OpenSSLException() throw(); + OpenSSLException & operator=(const OpenSSLException & exc); + const char * name() const throw(); + const char * className() const throw(); + Poco::Exception * clone() const; + void rethrow() const; + + private: + void setExtMessage(); + }; + + +} +} // namespace Poco::Crypto #endif // Crypto_CryptoException_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/CryptoStream.h b/base/poco/Crypto/include/Poco/Crypto/CryptoStream.h index 25a99a4ae58..788b0ab57ce 100644 --- a/base/poco/Crypto/include/Poco/Crypto/CryptoStream.h +++ b/base/poco/Crypto/include/Poco/Crypto/CryptoStream.h @@ -19,174 +19,177 @@ #define Crypto_CryptoStream_INCLUDED -#include "Poco/Crypto/Crypto.h" -#include "Poco/BufferedStreamBuf.h" -#include "Poco/Buffer.h" #include +#include "Poco/Buffer.h" +#include "Poco/BufferedStreamBuf.h" +#include "Poco/Crypto/Crypto.h" -namespace Poco { -namespace Crypto { - - -class CryptoTransform; -class Cipher; - - -class Crypto_API CryptoStreamBuf: public Poco::BufferedStreamBuf - /// This stream buffer performs cryptographic transformation on the data - /// going through it. +namespace Poco { -public: - CryptoStreamBuf(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); - CryptoStreamBuf(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); - - virtual ~CryptoStreamBuf(); - - void close(); - /// Flushes all buffers and finishes the encryption. - -protected: - int readFromDevice(char* buffer, std::streamsize length); - int writeToDevice(const char* buffer, std::streamsize length); - -private: - CryptoTransform* _pTransform; - std::istream* _pIstr; - std::ostream* _pOstr; - bool _eof; - - Poco::Buffer _buffer; - - CryptoStreamBuf(const CryptoStreamBuf&); - CryptoStreamBuf& operator = (const CryptoStreamBuf&); -}; - - -class Crypto_API CryptoIOS: public virtual std::ios - /// The base class for CryptoInputStream and CryptoOutputStream. - /// - /// This class is needed to ensure correct initialization order of the - /// stream buffer and base classes. +namespace Crypto { -public: - CryptoIOS(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); - CryptoIOS(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); - ~CryptoIOS(); - CryptoStreamBuf* rdbuf(); - -protected: - CryptoStreamBuf _buf; -}; -class Crypto_API CryptoInputStream: public CryptoIOS, public std::istream - /// This stream transforms all data passing through it using the given - /// CryptoTransform. - /// - /// Use a CryptoTransform object provided by Cipher::createEncrytor() or - /// Cipher::createDecryptor() to create an encrypting or decrypting stream, - /// respectively. -{ -public: - CryptoInputStream(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); - /// Create a new CryptoInputStream object. The CryptoInputStream takes the - /// ownership of the given CryptoTransform object. - - CryptoInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192); - /// Create a new encrypting CryptoInputStream object using the given cipher. - - ~CryptoInputStream(); - /// Destroys the CryptoInputStream. -}; + class CryptoTransform; + class Cipher; -class Crypto_API CryptoOutputStream: public CryptoIOS, public std::ostream - /// This stream transforms all data passing through it using the given - /// CryptoTransform. - /// - /// Use a CryptoTransform object provided by Cipher::createEncrytor() or - /// Cipher::createDecryptor() to create an encrypting or decrypting stream, - /// respectively. - /// - /// After all data has been passed through the stream, close() must be called - /// to ensure completion of cryptographic transformation. -{ -public: - CryptoOutputStream(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); - /// Create a new CryptoOutputStream object. The CryptoOutputStream takes the - /// ownership of the given CryptoTransform object. + class Crypto_API CryptoStreamBuf : public Poco::BufferedStreamBuf + /// This stream buffer performs cryptographic transformation on the data + /// going through it. + { + public: + CryptoStreamBuf(std::istream & istr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192); + CryptoStreamBuf(std::ostream & ostr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192); - CryptoOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192); - /// Create a new decrypting CryptoOutputStream object using the given cipher. + virtual ~CryptoStreamBuf(); - ~CryptoOutputStream(); - /// Destroys the CryptoOutputStream. + void close(); + /// Flushes all buffers and finishes the encryption. - void close(); - /// Flushes all buffers and finishes the encryption. -}; + protected: + int readFromDevice(char * buffer, std::streamsize length); + int writeToDevice(const char * buffer, std::streamsize length); + + private: + CryptoTransform * _pTransform; + std::istream * _pIstr; + std::ostream * _pOstr; + bool _eof; + + Poco::Buffer _buffer; + + CryptoStreamBuf(const CryptoStreamBuf &); + CryptoStreamBuf & operator=(const CryptoStreamBuf &); + }; -class Crypto_API DecryptingInputStream: public CryptoIOS, public std::istream - /// This stream decrypts all data passing through it using the given - /// Cipher. -{ -public: - DecryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192); - /// Create a new DecryptingInputStream object using the given cipher. + class Crypto_API CryptoIOS : public virtual std::ios + /// The base class for CryptoInputStream and CryptoOutputStream. + /// + /// This class is needed to ensure correct initialization order of the + /// stream buffer and base classes. + { + public: + CryptoIOS(std::istream & istr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192); + CryptoIOS(std::ostream & ostr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192); + ~CryptoIOS(); + CryptoStreamBuf * rdbuf(); - ~DecryptingInputStream(); - /// Destroys the DecryptingInputStream. -}; + protected: + CryptoStreamBuf _buf; + }; -class Crypto_API DecryptingOutputStream: public CryptoIOS, public std::ostream - /// This stream decrypts all data passing through it using the given - /// Cipher. -{ -public: - DecryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192); - /// Create a new DecryptingOutputStream object using the given cipher. + class Crypto_API CryptoInputStream : public CryptoIOS, public std::istream + /// This stream transforms all data passing through it using the given + /// CryptoTransform. + /// + /// Use a CryptoTransform object provided by Cipher::createEncrytor() or + /// Cipher::createDecryptor() to create an encrypting or decrypting stream, + /// respectively. + { + public: + CryptoInputStream(std::istream & istr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192); + /// Create a new CryptoInputStream object. The CryptoInputStream takes the + /// ownership of the given CryptoTransform object. - ~DecryptingOutputStream(); - /// Destroys the DecryptingOutputStream. + CryptoInputStream(std::istream & istr, Cipher & cipher, std::streamsize bufferSize = 8192); + /// Create a new encrypting CryptoInputStream object using the given cipher. - void close(); - /// Flushes all buffers and finishes the decryption. -}; + ~CryptoInputStream(); + /// Destroys the CryptoInputStream. + }; -class Crypto_API EncryptingInputStream: public CryptoIOS, public std::istream - /// This stream encrypts all data passing through it using the given - /// Cipher. -{ -public: - EncryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192); - /// Create a new EncryptingInputStream object using the given cipher. + class Crypto_API CryptoOutputStream : public CryptoIOS, public std::ostream + /// This stream transforms all data passing through it using the given + /// CryptoTransform. + /// + /// Use a CryptoTransform object provided by Cipher::createEncrytor() or + /// Cipher::createDecryptor() to create an encrypting or decrypting stream, + /// respectively. + /// + /// After all data has been passed through the stream, close() must be called + /// to ensure completion of cryptographic transformation. + { + public: + CryptoOutputStream(std::ostream & ostr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192); + /// Create a new CryptoOutputStream object. The CryptoOutputStream takes the + /// ownership of the given CryptoTransform object. - ~EncryptingInputStream(); - /// Destroys the EncryptingInputStream. -}; + CryptoOutputStream(std::ostream & ostr, Cipher & cipher, std::streamsize bufferSize = 8192); + /// Create a new decrypting CryptoOutputStream object using the given cipher. + + ~CryptoOutputStream(); + /// Destroys the CryptoOutputStream. + + void close(); + /// Flushes all buffers and finishes the encryption. + }; -class Crypto_API EncryptingOutputStream: public CryptoIOS, public std::ostream - /// This stream encrypts all data passing through it using the given - /// Cipher. -{ -public: - EncryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192); - /// Create a new EncryptingOutputStream object using the given cipher. + class Crypto_API DecryptingInputStream : public CryptoIOS, public std::istream + /// This stream decrypts all data passing through it using the given + /// Cipher. + { + public: + DecryptingInputStream(std::istream & istr, Cipher & cipher, std::streamsize bufferSize = 8192); + /// Create a new DecryptingInputStream object using the given cipher. - ~EncryptingOutputStream(); - /// Destroys the EncryptingOutputStream. - - void close(); - /// Flushes all buffers and finishes the encryption. -}; + ~DecryptingInputStream(); + /// Destroys the DecryptingInputStream. + }; -} } // namespace Poco::Crypto + class Crypto_API DecryptingOutputStream : public CryptoIOS, public std::ostream + /// This stream decrypts all data passing through it using the given + /// Cipher. + { + public: + DecryptingOutputStream(std::ostream & ostr, Cipher & cipher, std::streamsize bufferSize = 8192); + /// Create a new DecryptingOutputStream object using the given cipher. + + ~DecryptingOutputStream(); + /// Destroys the DecryptingOutputStream. + + void close(); + /// Flushes all buffers and finishes the decryption. + }; + + + class Crypto_API EncryptingInputStream : public CryptoIOS, public std::istream + /// This stream encrypts all data passing through it using the given + /// Cipher. + { + public: + EncryptingInputStream(std::istream & istr, Cipher & cipher, std::streamsize bufferSize = 8192); + /// Create a new EncryptingInputStream object using the given cipher. + + ~EncryptingInputStream(); + /// Destroys the EncryptingInputStream. + }; + + + class Crypto_API EncryptingOutputStream : public CryptoIOS, public std::ostream + /// This stream encrypts all data passing through it using the given + /// Cipher. + { + public: + EncryptingOutputStream(std::ostream & ostr, Cipher & cipher, std::streamsize bufferSize = 8192); + /// Create a new EncryptingOutputStream object using the given cipher. + + ~EncryptingOutputStream(); + /// Destroys the EncryptingOutputStream. + + void close(); + /// Flushes all buffers and finishes the encryption. + }; + + +} +} // namespace Poco::Crypto #endif // Crypto_CryptoStream_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/CryptoTransform.h b/base/poco/Crypto/include/Poco/Crypto/CryptoTransform.h index 9fa3806c653..7fbcff2b5c3 100644 --- a/base/poco/Crypto/include/Poco/Crypto/CryptoTransform.h +++ b/base/poco/Crypto/include/Poco/Crypto/CryptoTransform.h @@ -18,70 +18,71 @@ #define Crypto_CryptoTransform_INCLUDED -#include "Poco/Crypto/Crypto.h" #include +#include "Poco/Crypto/Crypto.h" -namespace Poco { -namespace Crypto { - - -class Crypto_API CryptoTransform - /// This interface represents the basic operations for cryptographic - /// transformations to be used with a CryptoInputStream or a - /// CryptoOutputStream. - /// - /// Implementations of this class are returned by the Cipher class to - /// perform encryption or decryption of data. +namespace Poco +{ +namespace Crypto { -public: - CryptoTransform(); - /// Creates a new CryptoTransform object. - - virtual ~CryptoTransform(); - /// Destroys the CryptoTransform. - - virtual std::size_t blockSize() const = 0; - /// Returns the block size for this CryptoTransform. - - virtual int setPadding(int padding); - /// Enables or disables padding. By default encryption operations are padded using standard block - /// padding and the padding is checked and removed when decrypting. If the padding parameter is zero then - /// no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of - /// the block size or an error will occur. - - virtual std::string getTag(std::size_t tagSize = 16) = 0; - /// Returns the GCM tag after encrypting using GCM mode. - /// - /// Must be called after finalize(). - - virtual void setTag(const std::string& tag) = 0; - /// Sets the GCM tag for authenticated decryption using GCM mode. - /// - /// Must be set before finalize() is called, otherwise - /// decryption will fail. - - virtual std::streamsize transform( - const unsigned char* input, - std::streamsize inputLength, - unsigned char* output, - std::streamsize outputLength) = 0; - /// Transforms a chunk of data. The inputLength is arbitrary and does not - /// need to be a multiple of the block size. The output buffer has a maximum - /// capacity of the given outputLength that must be at least - /// inputLength + blockSize() - 1 - /// Returns the number of bytes written to the output buffer. - - virtual std::streamsize finalize(unsigned char* output, std::streamsize length) = 0; - /// Finalizes the transformation. The output buffer must contain enough - /// space for at least two blocks, ie. - /// length >= 2*blockSize() - /// must be true. Returns the number of bytes written to the output - /// buffer. -}; -} } // namespace Poco::Crypto + class Crypto_API CryptoTransform + /// This interface represents the basic operations for cryptographic + /// transformations to be used with a CryptoInputStream or a + /// CryptoOutputStream. + /// + /// Implementations of this class are returned by the Cipher class to + /// perform encryption or decryption of data. + { + public: + CryptoTransform(); + /// Creates a new CryptoTransform object. + + virtual ~CryptoTransform(); + /// Destroys the CryptoTransform. + + virtual std::size_t blockSize() const = 0; + /// Returns the block size for this CryptoTransform. + + virtual int setPadding(int padding); + /// Enables or disables padding. By default encryption operations are padded using standard block + /// padding and the padding is checked and removed when decrypting. If the padding parameter is zero then + /// no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of + /// the block size or an error will occur. + + virtual std::string getTag(std::size_t tagSize = 16) = 0; + /// Returns the GCM tag after encrypting using GCM mode. + /// + /// Must be called after finalize(). + + virtual void setTag(const std::string & tag) = 0; + /// Sets the GCM tag for authenticated decryption using GCM mode. + /// + /// Must be set before finalize() is called, otherwise + /// decryption will fail. + + virtual std::streamsize + transform(const unsigned char * input, std::streamsize inputLength, unsigned char * output, std::streamsize outputLength) + = 0; + /// Transforms a chunk of data. The inputLength is arbitrary and does not + /// need to be a multiple of the block size. The output buffer has a maximum + /// capacity of the given outputLength that must be at least + /// inputLength + blockSize() - 1 + /// Returns the number of bytes written to the output buffer. + + virtual std::streamsize finalize(unsigned char * output, std::streamsize length) = 0; + /// Finalizes the transformation. The output buffer must contain enough + /// space for at least two blocks, ie. + /// length >= 2*blockSize() + /// must be true. Returns the number of bytes written to the output + /// buffer. + }; + + +} +} // namespace Poco::Crypto #endif // Crypto_CryptoTransform_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/DigestEngine.h b/base/poco/Crypto/include/Poco/Crypto/DigestEngine.h index 1c30e769d5f..77a1349f8e2 100644 --- a/base/poco/Crypto/include/Poco/Crypto/DigestEngine.h +++ b/base/poco/Crypto/include/Poco/Crypto/DigestEngine.h @@ -18,63 +18,66 @@ #define Crypto_DigestEngine_INCLUDED +#include #include "Poco/Crypto/Crypto.h" #include "Poco/Crypto/OpenSSLInitializer.h" #include "Poco/DigestEngine.h" -#include -namespace Poco { -namespace Crypto { - - -class Crypto_API DigestEngine: public Poco::DigestEngine - /// This class implements a Poco::DigestEngine for all - /// digest algorithms supported by OpenSSL. +namespace Poco { -public: - DigestEngine(const std::string& name); - /// Creates a DigestEngine using the digest with the given name - /// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.). - /// See the OpenSSL documentation for a list of supported digest algorithms. - /// - /// Throws a Poco::NotFoundException if no algorithm with the given name exists. - - ~DigestEngine(); - /// Destroys the DigestEngine. - - const std::string& algorithm() const; - /// Returns the name of the digest algorithm. - - int nid() const; - /// Returns the NID (OpenSSL object identifier) of the digest algorithm. - - // DigestEngine - std::size_t digestLength() const; - void reset(); - const Poco::DigestEngine::Digest& digest(); - -protected: - void updateImpl(const void* data, std::size_t length); - -private: - std::string _name; - EVP_MD_CTX* _pContext; - Poco::DigestEngine::Digest _digest; - OpenSSLInitializer _openSSLInitializer; -}; - - -// -// inlines -// -inline const std::string& DigestEngine::algorithm() const +namespace Crypto { - return _name; + + + class Crypto_API DigestEngine : public Poco::DigestEngine + /// This class implements a Poco::DigestEngine for all + /// digest algorithms supported by OpenSSL. + { + public: + DigestEngine(const std::string & name); + /// Creates a DigestEngine using the digest with the given name + /// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.). + /// See the OpenSSL documentation for a list of supported digest algorithms. + /// + /// Throws a Poco::NotFoundException if no algorithm with the given name exists. + + ~DigestEngine(); + /// Destroys the DigestEngine. + + const std::string & algorithm() const; + /// Returns the name of the digest algorithm. + + int nid() const; + /// Returns the NID (OpenSSL object identifier) of the digest algorithm. + + // DigestEngine + std::size_t digestLength() const; + void reset(); + const Poco::DigestEngine::Digest & digest(); + + protected: + void updateImpl(const void * data, std::size_t length); + + private: + std::string _name; + EVP_MD_CTX * _pContext; + Poco::DigestEngine::Digest _digest; + OpenSSLInitializer _openSSLInitializer; + }; + + + // + // inlines + // + inline const std::string & DigestEngine::algorithm() const + { + return _name; + } + + } - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_DigestEngine_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/ECDSADigestEngine.h b/base/poco/Crypto/include/Poco/Crypto/ECDSADigestEngine.h index ed6fab442f6..2d0c31ba09c 100644 --- a/base/poco/Crypto/include/Poco/Crypto/ECDSADigestEngine.h +++ b/base/poco/Crypto/include/Poco/Crypto/ECDSADigestEngine.h @@ -19,83 +19,85 @@ #define Crypto_ECDSADigestEngine_INCLUDED -#include "Poco/Crypto/Crypto.h" -#include "Poco/Crypto/ECKey.h" -#include "Poco/DigestEngine.h" -#include "Poco/Crypto/DigestEngine.h" #include #include +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/DigestEngine.h" +#include "Poco/Crypto/ECKey.h" +#include "Poco/DigestEngine.h" -namespace Poco { -namespace Crypto { - - -class Crypto_API ECDSADigestEngine: public Poco::DigestEngine - /// This class implements a Poco::DigestEngine that can be - /// used to compute a secure digital signature. - /// - /// First another Poco::Crypto::DigestEngine is created and - /// used to compute a cryptographic hash of the data to be - /// signed. Then, the hash value is encrypted, using - /// the ECDSA private key. - /// - /// To verify a signature, pass it to the verify() - /// member function. It will decrypt the signature - /// using the ECDSA public key and compare the resulting - /// hash with the actual hash of the data. +namespace Poco +{ +namespace Crypto { -public: - - ECDSADigestEngine(const ECKey& key, const std::string &name); - /// Creates the ECDSADigestEngine with the given ECDSA key, - /// using the hash algorithm with the given name - /// (e.g., "SHA1", "SHA256", "SHA512", etc.). - /// See the OpenSSL documentation for a list of supported digest algorithms. - /// - /// Throws a Poco::NotFoundException if no algorithm with the given name exists. - - ~ECDSADigestEngine(); - /// Destroys the ECDSADigestEngine. - - std::size_t digestLength() const; - /// Returns the length of the digest in bytes. - - void reset(); - /// Resets the engine so that a new - /// digest can be computed. - - const DigestEngine::Digest& digest(); - /// Finishes the computation of the digest - /// (the first time it's called) and - /// returns the message digest. - /// - /// Can be called multiple times. - - const DigestEngine::Digest& signature(); - /// Signs the digest using the ECDSADSA algorithm - /// and the private key (the first time it's - /// called) and returns the result. - /// - /// Can be called multiple times. - - bool verify(const DigestEngine::Digest& signature); - /// Verifies the data against the signature. - /// - /// Returns true if the signature can be verified, false otherwise. - -protected: - void updateImpl(const void* data, std::size_t length); - -private: - ECKey _key; - Poco::Crypto::DigestEngine _engine; - Poco::DigestEngine::Digest _digest; - Poco::DigestEngine::Digest _signature; -}; -} } // namespace Poco::Crypto + class Crypto_API ECDSADigestEngine : public Poco::DigestEngine + /// This class implements a Poco::DigestEngine that can be + /// used to compute a secure digital signature. + /// + /// First another Poco::Crypto::DigestEngine is created and + /// used to compute a cryptographic hash of the data to be + /// signed. Then, the hash value is encrypted, using + /// the ECDSA private key. + /// + /// To verify a signature, pass it to the verify() + /// member function. It will decrypt the signature + /// using the ECDSA public key and compare the resulting + /// hash with the actual hash of the data. + { + public: + ECDSADigestEngine(const ECKey & key, const std::string & name); + /// Creates the ECDSADigestEngine with the given ECDSA key, + /// using the hash algorithm with the given name + /// (e.g., "SHA1", "SHA256", "SHA512", etc.). + /// See the OpenSSL documentation for a list of supported digest algorithms. + /// + /// Throws a Poco::NotFoundException if no algorithm with the given name exists. + + ~ECDSADigestEngine(); + /// Destroys the ECDSADigestEngine. + + std::size_t digestLength() const; + /// Returns the length of the digest in bytes. + + void reset(); + /// Resets the engine so that a new + /// digest can be computed. + + const DigestEngine::Digest & digest(); + /// Finishes the computation of the digest + /// (the first time it's called) and + /// returns the message digest. + /// + /// Can be called multiple times. + + const DigestEngine::Digest & signature(); + /// Signs the digest using the ECDSADSA algorithm + /// and the private key (the first time it's + /// called) and returns the result. + /// + /// Can be called multiple times. + + bool verify(const DigestEngine::Digest & signature); + /// Verifies the data against the signature. + /// + /// Returns true if the signature can be verified, false otherwise. + + protected: + void updateImpl(const void * data, std::size_t length); + + private: + ECKey _key; + Poco::Crypto::DigestEngine _engine; + Poco::DigestEngine::Digest _digest; + Poco::DigestEngine::Digest _signature; + }; + + +} +} // namespace Poco::Crypto #endif // Crypto_ECDSADigestEngine_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/ECKey.h b/base/poco/Crypto/include/Poco/Crypto/ECKey.h index 15d5401cbcd..babcd814ec9 100644 --- a/base/poco/Crypto/include/Poco/Crypto/ECKey.h +++ b/base/poco/Crypto/include/Poco/Crypto/ECKey.h @@ -20,116 +20,119 @@ #include "Poco/Crypto/Crypto.h" -#include "Poco/Crypto/KeyPair.h" #include "Poco/Crypto/ECKeyImpl.h" +#include "Poco/Crypto/KeyPair.h" -namespace Poco { -namespace Crypto { - - -class X509Certificate; -class PKCS12Container; - - -class Crypto_API ECKey : public KeyPair - /// This class stores an EC key pair, consisting - /// of private and public key. Storage of the private - /// key is optional. - /// - /// If a private key is available, the ECKey can be - /// used for decrypting data (encrypted with the public key) - /// or computing secure digital signatures. +namespace Poco { -public: - ECKey(const EVPPKey& key); - /// Constructs ECKeyImpl by extracting the EC key. - - ECKey(const X509Certificate& cert); - /// Extracts the EC public key from the given certificate. - - ECKey(const PKCS12Container& cert); - /// Extracts the EC private key from the given certificate. - - ECKey(const std::string& eccGroup); - /// Creates the ECKey. Creates a new public/private key pair using the given parameters. - /// Can be used to sign data and verify signatures. - - ECKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase = ""); - /// Creates the ECKey, by reading public and private key from the given files and - /// using the given passphrase for the private key. - /// - /// Cannot be used for signing or decryption unless a private key is available. - /// - /// If a private key is specified, you don't need to specify a public key file. - /// OpenSSL will auto-create the public key from the private key. - - ECKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream = 0, const std::string& privateKeyPassphrase = ""); - /// Creates the ECKey, by reading public and private key from the given streams and - /// using the given passphrase for the private key. - /// - /// Cannot be used for signing or decryption unless a private key is available. - /// - /// If a private key is specified, you don't need to specify a public key file. - /// OpenSSL will auto-create the public key from the private key. - - ~ECKey(); - /// Destroys the ECKey. - - ECKeyImpl::Ptr impl() const; - /// Returns the impl object. - - static std::string getCurveName(int nid = -1); - /// Returns elliptical curve name corresponding to - /// the given nid; if nid is not found, returns - /// empty string. - /// - /// If nid is -1, returns first curve name. - /// - /// If no curves are found, returns empty string; - - static int getCurveNID(std::string& name); - /// Returns the NID of the specified curve. - /// - /// If name is empty, returns the first curve NID - /// and updates the name accordingly. - - static bool hasCurve(const std::string& name); - /// Returns true if the named curve is found, - /// false otherwise. - -private: - ECKeyImpl::Ptr _pImpl; -}; - - -// -// inlines -// -inline ECKeyImpl::Ptr ECKey::impl() const +namespace Crypto { - return _pImpl; + + + class X509Certificate; + class PKCS12Container; + + + class Crypto_API ECKey : public KeyPair + /// This class stores an EC key pair, consisting + /// of private and public key. Storage of the private + /// key is optional. + /// + /// If a private key is available, the ECKey can be + /// used for decrypting data (encrypted with the public key) + /// or computing secure digital signatures. + { + public: + ECKey(const EVPPKey & key); + /// Constructs ECKeyImpl by extracting the EC key. + + ECKey(const X509Certificate & cert); + /// Extracts the EC public key from the given certificate. + + ECKey(const PKCS12Container & cert); + /// Extracts the EC private key from the given certificate. + + ECKey(const std::string & eccGroup); + /// Creates the ECKey. Creates a new public/private key pair using the given parameters. + /// Can be used to sign data and verify signatures. + + ECKey(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase = ""); + /// Creates the ECKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. + /// + /// Cannot be used for signing or decryption unless a private key is available. + /// + /// If a private key is specified, you don't need to specify a public key file. + /// OpenSSL will auto-create the public key from the private key. + + ECKey(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = ""); + /// Creates the ECKey, by reading public and private key from the given streams and + /// using the given passphrase for the private key. + /// + /// Cannot be used for signing or decryption unless a private key is available. + /// + /// If a private key is specified, you don't need to specify a public key file. + /// OpenSSL will auto-create the public key from the private key. + + ~ECKey(); + /// Destroys the ECKey. + + ECKeyImpl::Ptr impl() const; + /// Returns the impl object. + + static std::string getCurveName(int nid = -1); + /// Returns elliptical curve name corresponding to + /// the given nid; if nid is not found, returns + /// empty string. + /// + /// If nid is -1, returns first curve name. + /// + /// If no curves are found, returns empty string; + + static int getCurveNID(std::string & name); + /// Returns the NID of the specified curve. + /// + /// If name is empty, returns the first curve NID + /// and updates the name accordingly. + + static bool hasCurve(const std::string & name); + /// Returns true if the named curve is found, + /// false otherwise. + + private: + ECKeyImpl::Ptr _pImpl; + }; + + + // + // inlines + // + inline ECKeyImpl::Ptr ECKey::impl() const + { + return _pImpl; + } + + + inline std::string ECKey::getCurveName(int nid) + { + return ECKeyImpl::getCurveName(nid); + } + + + inline int ECKey::getCurveNID(std::string & name) + { + return ECKeyImpl::getCurveNID(name); + } + + + inline bool ECKey::hasCurve(const std::string & name) + { + return ECKeyImpl::hasCurve(name); + } + + } - - -inline std::string ECKey::getCurveName(int nid) -{ - return ECKeyImpl::getCurveName(nid); -} - - -inline int ECKey::getCurveNID(std::string& name) -{ - return ECKeyImpl::getCurveNID(name); -} - - -inline bool ECKey::hasCurve(const std::string& name) -{ - return ECKeyImpl::hasCurve(name); -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_ECKey_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/ECKeyImpl.h b/base/poco/Crypto/include/Poco/Crypto/ECKeyImpl.h index 840764304d1..2a72861a84e 100644 --- a/base/poco/Crypto/include/Poco/Crypto/ECKeyImpl.h +++ b/base/poco/Crypto/include/Poco/Crypto/ECKeyImpl.h @@ -19,156 +19,155 @@ #define Crypto_ECKeyImplImpl_INCLUDED +#include +#include +#include +#include +#include +#include "Poco/AutoPtr.h" #include "Poco/Crypto/Crypto.h" #include "Poco/Crypto/EVPPKey.h" #include "Poco/Crypto/KeyPairImpl.h" #include "Poco/Crypto/OpenSSLInitializer.h" #include "Poco/RefCountedObject.h" -#include "Poco/AutoPtr.h" -#include -#include -#include -#include -#include -namespace Poco { -namespace Crypto { - - -class X509Certificate; -class PKCS12Container; - - -class ECKeyImpl: public KeyPairImpl - /// Elliptic Curve key clas implementation. +namespace Poco { -public: - typedef Poco::AutoPtr Ptr; - typedef std::vector ByteVec; - - ECKeyImpl(const EVPPKey& key); - /// Constructs ECKeyImpl by extracting the EC key. - - ECKeyImpl(const X509Certificate& cert); - /// Constructs ECKeyImpl by extracting the EC public key from the given certificate. - - ECKeyImpl(const PKCS12Container& cert); - /// Constructs ECKeyImpl by extracting the EC private key from the given certificate. - - ECKeyImpl(int eccGroup); - /// Creates the ECKey of the specified group. Creates a new public/private keypair using the given parameters. - /// Can be used to sign data and verify signatures. - - ECKeyImpl(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase); - /// Creates the ECKey, by reading public and private key from the given files and - /// using the given passphrase for the private key. Can only by used for signing if - /// a private key is available. - - ECKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase); - /// Creates the ECKey. Can only by used for signing if pPrivKey - /// is not null. If a private key file is specified, you don't need to - /// specify a public key file. OpenSSL will auto-create it from the private key. - - ~ECKeyImpl(); - /// Destroys the ECKeyImpl. - - EC_KEY* getECKey(); - /// Returns the OpenSSL EC key. - - const EC_KEY* getECKey() const; - /// Returns the OpenSSL EC key. - - int size() const; - /// Returns the EC key length in bits. - - int groupId() const; - /// Returns the EC key group integer Id. - - std::string groupName() const; - /// Returns the EC key group name. - - void save(const std::string& publicKeyFile, - const std::string& privateKeyFile = "", - const std::string& privateKeyPassphrase = "") const; - /// Exports the public and private keys to the given files. - /// - /// If an empty filename is specified, the corresponding key - /// is not exported. - - void save(std::ostream* pPublicKeyStream, - std::ostream* pPrivateKeyStream = 0, - const std::string& privateKeyPassphrase = "") const; - /// Exports the public and private key to the given streams. - /// - /// If a null pointer is passed for a stream, the corresponding - /// key is not exported. - - static std::string getCurveName(int nid = -1); - /// Returns elliptical curve name corresponding to - /// the given nid; if nid is not found, returns - /// empty string. - /// - /// If nid is -1, returns first curve name. - /// - /// If no curves are found, returns empty string; - - static int getCurveNID(std::string& name); - /// Returns the NID of the specified curve. - /// - /// If name is empty, returns the first curve NID - /// and updates the name accordingly. - - static bool hasCurve(const std::string& name); - /// Returns true if the named curve is found, - /// false otherwise. - -private: - void checkEC(const std::string& method, const std::string& func) const; - void freeEC(); - - EC_KEY* _pEC; -}; - - -// -// inlines -// -inline EC_KEY* ECKeyImpl::getECKey() +namespace Crypto { - return _pEC; + + + class X509Certificate; + class PKCS12Container; + + + class ECKeyImpl : public KeyPairImpl + /// Elliptic Curve key clas implementation. + { + public: + typedef Poco::AutoPtr Ptr; + typedef std::vector ByteVec; + + ECKeyImpl(const EVPPKey & key); + /// Constructs ECKeyImpl by extracting the EC key. + + ECKeyImpl(const X509Certificate & cert); + /// Constructs ECKeyImpl by extracting the EC public key from the given certificate. + + ECKeyImpl(const PKCS12Container & cert); + /// Constructs ECKeyImpl by extracting the EC private key from the given certificate. + + ECKeyImpl(int eccGroup); + /// Creates the ECKey of the specified group. Creates a new public/private keypair using the given parameters. + /// Can be used to sign data and verify signatures. + + ECKeyImpl(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase); + /// Creates the ECKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. Can only by used for signing if + /// a private key is available. + + ECKeyImpl(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream, const std::string & privateKeyPassphrase); + /// Creates the ECKey. Can only by used for signing if pPrivKey + /// is not null. If a private key file is specified, you don't need to + /// specify a public key file. OpenSSL will auto-create it from the private key. + + ~ECKeyImpl(); + /// Destroys the ECKeyImpl. + + EC_KEY * getECKey(); + /// Returns the OpenSSL EC key. + + const EC_KEY * getECKey() const; + /// Returns the OpenSSL EC key. + + int size() const; + /// Returns the EC key length in bits. + + int groupId() const; + /// Returns the EC key group integer Id. + + std::string groupName() const; + /// Returns the EC key group name. + + void save(const std::string & publicKeyFile, const std::string & privateKeyFile = "", const std::string & privateKeyPassphrase = "") + const; + /// Exports the public and private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. + + void + save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "") const; + /// Exports the public and private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. + + static std::string getCurveName(int nid = -1); + /// Returns elliptical curve name corresponding to + /// the given nid; if nid is not found, returns + /// empty string. + /// + /// If nid is -1, returns first curve name. + /// + /// If no curves are found, returns empty string; + + static int getCurveNID(std::string & name); + /// Returns the NID of the specified curve. + /// + /// If name is empty, returns the first curve NID + /// and updates the name accordingly. + + static bool hasCurve(const std::string & name); + /// Returns true if the named curve is found, + /// false otherwise. + + private: + void checkEC(const std::string & method, const std::string & func) const; + void freeEC(); + + EC_KEY * _pEC; + }; + + + // + // inlines + // + inline EC_KEY * ECKeyImpl::getECKey() + { + return _pEC; + } + + + inline const EC_KEY * ECKeyImpl::getECKey() const + { + return _pEC; + } + + + inline std::string ECKeyImpl::groupName() const + { + return OBJ_nid2sn(groupId()); + } + + + inline void + ECKeyImpl::save(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase) const + { + EVPPKey(_pEC).save(publicKeyFile, privateKeyFile, privateKeyPassphrase); + } + + + inline void + ECKeyImpl::save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream, const std::string & privateKeyPassphrase) const + { + EVPPKey(_pEC).save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase); + } + + } - - -inline const EC_KEY* ECKeyImpl::getECKey() const -{ - return _pEC; -} - - -inline std::string ECKeyImpl::groupName() const -{ - return OBJ_nid2sn(groupId()); -} - - -inline void ECKeyImpl::save(const std::string& publicKeyFile, - const std::string& privateKeyFile, - const std::string& privateKeyPassphrase) const -{ - EVPPKey(_pEC).save(publicKeyFile, privateKeyFile, privateKeyPassphrase); -} - - -inline void ECKeyImpl::save(std::ostream* pPublicKeyStream, - std::ostream* pPrivateKeyStream, - const std::string& privateKeyPassphrase) const -{ - EVPPKey(_pEC).save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase); -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_ECKeyImplImpl_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/EVPPKey.h b/base/poco/Crypto/include/Poco/Crypto/EVPPKey.h index 2b0062a3e13..acc79ec92b2 100644 --- a/base/poco/Crypto/include/Poco/Crypto/EVPPKey.h +++ b/base/poco/Crypto/include/Poco/Crypto/EVPPKey.h @@ -19,336 +19,351 @@ #define Crypto_EVPPKeyImpl_INCLUDED +#include +#include +#include +#include +#include +#include #include "Poco/Crypto/Crypto.h" #include "Poco/Crypto/CryptoException.h" #include "Poco/StreamCopier.h" -#include -#include -#include -#include -#include -#include -namespace Poco { -namespace Crypto { - - -class ECKey; -class RSAKey; - - -class Crypto_API EVPPKey - /// Utility class for conversion of native keys to EVP. - /// Currently, only RSA and EC keys are supported. +namespace Poco +{ +namespace Crypto { -public: - explicit EVPPKey(const std::string& ecCurveName); - /// Constructs EVPPKey from ECC curve name. - /// - /// Only EC keys can be wrapped by an EVPPKey - /// created using this constructor. - explicit EVPPKey(const char* ecCurveName); - /// Constructs EVPPKey from ECC curve name. - /// - /// Only EC keys can be wrapped by an EVPPKey - /// created using this constructor. - explicit EVPPKey(EVP_PKEY* pEVPPKey); - /// Constructs EVPPKey from EVP_PKEY pointer. - /// The content behind the supplied pointer is internally duplicated. + class ECKey; + class RSAKey; - template - explicit EVPPKey(K* pKey): _pEVPPKey(EVP_PKEY_new()) - /// Constructs EVPPKey from a "native" OpenSSL (RSA or EC_KEY), - /// or a Poco wrapper (RSAKey, ECKey) key pointer. - { - if (!_pEVPPKey) throw OpenSSLException(); - setKey(pKey); - } - EVPPKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase = ""); - /// Creates the EVPPKey, by reading public and private key from the given files and - /// using the given passphrase for the private key. Can only by used for signing if - /// a private key is available. + class Crypto_API EVPPKey + /// Utility class for conversion of native keys to EVP. + /// Currently, only RSA and EC keys are supported. + { + public: + explicit EVPPKey(const std::string & ecCurveName); + /// Constructs EVPPKey from ECC curve name. + /// + /// Only EC keys can be wrapped by an EVPPKey + /// created using this constructor. - EVPPKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase = ""); - /// Creates the EVPPKey. Can only by used for signing if pPrivKey - /// is not null. If a private key file is specified, you don't need to - /// specify a public key file. OpenSSL will auto-create it from the private key. + explicit EVPPKey(const char * ecCurveName); + /// Constructs EVPPKey from ECC curve name. + /// + /// Only EC keys can be wrapped by an EVPPKey + /// created using this constructor. - EVPPKey(const EVPPKey& other); - /// Copy constructor. + explicit EVPPKey(EVP_PKEY * pEVPPKey); + /// Constructs EVPPKey from EVP_PKEY pointer. + /// The content behind the supplied pointer is internally duplicated. - EVPPKey& operator=(const EVPPKey& other); - /// Assignment operator. + template + explicit EVPPKey(K * pKey) : _pEVPPKey(EVP_PKEY_new()) + /// Constructs EVPPKey from a "native" OpenSSL (RSA or EC_KEY), + /// or a Poco wrapper (RSAKey, ECKey) key pointer. + { + if (!_pEVPPKey) + throw OpenSSLException(); + setKey(pKey); + } + + EVPPKey(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase = ""); + /// Creates the EVPPKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. Can only by used for signing if + /// a private key is available. + + EVPPKey(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream, const std::string & privateKeyPassphrase = ""); + /// Creates the EVPPKey. Can only by used for signing if pPrivKey + /// is not null. If a private key file is specified, you don't need to + /// specify a public key file. OpenSSL will auto-create it from the private key. + + EVPPKey(const EVPPKey & other); + /// Copy constructor. + + EVPPKey & operator=(const EVPPKey & other); + /// Assignment operator. #ifdef POCO_ENABLE_CPP11 - EVPPKey(EVPPKey&& other); - /// Move constructor. + EVPPKey(EVPPKey && other); + /// Move constructor. - EVPPKey& operator=(EVPPKey&& other); - /// Assignment move operator. + EVPPKey & operator=(EVPPKey && other); + /// Assignment move operator. #endif // POCO_ENABLE_CPP11 - ~EVPPKey(); - /// Destroys the EVPPKey. + ~EVPPKey(); + /// Destroys the EVPPKey. - bool operator == (const EVPPKey& other) const; - /// Comparison operator. - /// Returns true if public key components and parameters - /// of the other key are equal to this key. - /// - /// Works as expected when one key contains only public key, - /// while the other one contains private (thus also public) key. + bool operator==(const EVPPKey & other) const; + /// Comparison operator. + /// Returns true if public key components and parameters + /// of the other key are equal to this key. + /// + /// Works as expected when one key contains only public key, + /// while the other one contains private (thus also public) key. - bool operator != (const EVPPKey& other) const; - /// Comparison operator. - /// Returns true if public key components and parameters - /// of the other key are different from this key. - /// - /// Works as expected when one key contains only public key, - /// while the other one contains private (thus also public) key. + bool operator!=(const EVPPKey & other) const; + /// Comparison operator. + /// Returns true if public key components and parameters + /// of the other key are different from this key. + /// + /// Works as expected when one key contains only public key, + /// while the other one contains private (thus also public) key. - void save(const std::string& publicKeyFile, const std::string& privateKeyFile = "", const std::string& privateKeyPassphrase = "") const; - /// Exports the public and/or private keys to the given files. - /// - /// If an empty filename is specified, the corresponding key - /// is not exported. + void save(const std::string & publicKeyFile, const std::string & privateKeyFile = "", const std::string & privateKeyPassphrase = "") + const; + /// Exports the public and/or private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. - void save(std::ostream* pPublicKeyStream, std::ostream* pPrivateKeyStream = 0, const std::string& privateKeyPassphrase = "") const; - /// Exports the public and/or private key to the given streams. - /// - /// If a null pointer is passed for a stream, the corresponding - /// key is not exported. + void + save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "") const; + /// Exports the public and/or private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. - int type() const; - /// Returns the EVPPKey type NID. + int type() const; + /// Returns the EVPPKey type NID. - bool isSupported(int type) const; - /// Returns true if OpenSSL type is supported + bool isSupported(int type) const; + /// Returns true if OpenSSL type is supported - operator const EVP_PKEY*() const; - /// Returns const pointer to the OpenSSL EVP_PKEY structure. + operator const EVP_PKEY *() const; + /// Returns const pointer to the OpenSSL EVP_PKEY structure. - operator EVP_PKEY*(); - /// Returns pointer to the OpenSSL EVP_PKEY structure. + operator EVP_PKEY *(); + /// Returns pointer to the OpenSSL EVP_PKEY structure. - static EVP_PKEY* duplicate(const EVP_PKEY* pFromKey, EVP_PKEY** pToKey); - /// Duplicates pFromKey into *pToKey and returns - // the pointer to duplicated EVP_PKEY. + static EVP_PKEY * duplicate(const EVP_PKEY * pFromKey, EVP_PKEY ** pToKey); + /// Duplicates pFromKey into *pToKey and returns + // the pointer to duplicated EVP_PKEY. -private: - EVPPKey(); + private: + EVPPKey(); - static int type(const EVP_PKEY* pEVPPKey); - void newECKey(const char* group); - void duplicate(EVP_PKEY* pEVPPKey); + static int type(const EVP_PKEY * pEVPPKey); + void newECKey(const char * group); + void duplicate(EVP_PKEY * pEVPPKey); - void setKey(ECKey* pKey); - void setKey(RSAKey* pKey); - void setKey(EC_KEY* pKey); - void setKey(RSA* pKey); - static int passCB(char* buf, int size, int, void* pass); + void setKey(ECKey * pKey); + void setKey(RSAKey * pKey); + void setKey(EC_KEY * pKey); + void setKey(RSA * pKey); + static int passCB(char * buf, int size, int, void * pass); - typedef EVP_PKEY* (*PEM_read_FILE_Key_fn)(FILE*, EVP_PKEY**, pem_password_cb*, void*); - typedef EVP_PKEY* (*PEM_read_BIO_Key_fn)(BIO*, EVP_PKEY**, pem_password_cb*, void*); - typedef void* (*EVP_PKEY_get_Key_fn)(EVP_PKEY*); + typedef EVP_PKEY * (*PEM_read_FILE_Key_fn)(FILE *, EVP_PKEY **, pem_password_cb *, void *); + typedef EVP_PKEY * (*PEM_read_BIO_Key_fn)(BIO *, EVP_PKEY **, pem_password_cb *, void *); + typedef void * (*EVP_PKEY_get_Key_fn)(EVP_PKEY *); - // The following load*() functions are used by both native and EVP_PKEY type key - // loading from BIO/FILE. - // When used for EVP key loading, getFunc is null (ie. native key is not extracted - // from the loaded EVP_PKEY). - template - static bool loadKey(K** ppKey, - PEM_read_FILE_Key_fn readFunc, - F getFunc, - const std::string& keyFile, - const std::string& pass = "") - { - poco_assert_dbg (((typeid(K*) == typeid(RSA*) || typeid(K*) == typeid(EC_KEY*)) && getFunc) || - ((typeid(K*) == typeid(EVP_PKEY*)) && !getFunc)); - poco_check_ptr (ppKey); - poco_assert_dbg (!*ppKey); + // The following load*() functions are used by both native and EVP_PKEY type key + // loading from BIO/FILE. + // When used for EVP key loading, getFunc is null (ie. native key is not extracted + // from the loaded EVP_PKEY). + template + static bool + loadKey(K ** ppKey, PEM_read_FILE_Key_fn readFunc, F getFunc, const std::string & keyFile, const std::string & pass = "") + { + poco_assert_dbg( + ((typeid(K *) == typeid(RSA *) || typeid(K *) == typeid(EC_KEY *)) && getFunc) + || ((typeid(K *) == typeid(EVP_PKEY *)) && !getFunc)); + poco_check_ptr(ppKey); + poco_assert_dbg(!*ppKey); - FILE* pFile = 0; - if (!keyFile.empty()) - { - if (!getFunc) *ppKey = (K*)EVP_PKEY_new(); - EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey; - if (pKey) - { - pFile = fopen(keyFile.c_str(), "r"); - if (pFile) - { - pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)0 : &passCB; - void* pPassword = pass.empty() ? (void*)0 : (void*)pass.c_str(); - if (readFunc(pFile, &pKey, pCB, pPassword)) - { - fclose(pFile); pFile = 0; - if(getFunc) - { - *ppKey = (K*)getFunc(pKey); - EVP_PKEY_free(pKey); - } - else - { - poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*)); - *ppKey = (K*)pKey; - } - if(!*ppKey) goto error; - return true; - } - goto error; - } - else - { - if (getFunc) EVP_PKEY_free(pKey); - throw IOException("ECKeyImpl, cannot open file", keyFile); - } - } - else goto error; - } - return false; + FILE * pFile = 0; + if (!keyFile.empty()) + { + if (!getFunc) + *ppKey = (K *)EVP_PKEY_new(); + EVP_PKEY * pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY *)*ppKey; + if (pKey) + { + pFile = fopen(keyFile.c_str(), "r"); + if (pFile) + { + pem_password_cb * pCB = pass.empty() ? (pem_password_cb *)0 : &passCB; + void * pPassword = pass.empty() ? (void *)0 : (void *)pass.c_str(); + if (readFunc(pFile, &pKey, pCB, pPassword)) + { + fclose(pFile); + pFile = 0; + if (getFunc) + { + *ppKey = (K *)getFunc(pKey); + EVP_PKEY_free(pKey); + } + else + { + poco_assert_dbg(typeid(K *) == typeid(EVP_PKEY *)); + *ppKey = (K *)pKey; + } + if (!*ppKey) + goto error; + return true; + } + goto error; + } + else + { + if (getFunc) + EVP_PKEY_free(pKey); + throw IOException("ECKeyImpl, cannot open file", keyFile); + } + } + else + goto error; + } + return false; - error: - if (pFile) fclose(pFile); - throw OpenSSLException("EVPKey::loadKey(string)"); - } + error: + if (pFile) + fclose(pFile); + throw OpenSSLException("EVPKey::loadKey(string)"); + } - template - static bool loadKey(K** ppKey, - PEM_read_BIO_Key_fn readFunc, - F getFunc, - std::istream* pIstr, - const std::string& pass = "") - { - poco_assert_dbg (((typeid(K*) == typeid(RSA*) || typeid(K*) == typeid(EC_KEY*)) && getFunc) || - ((typeid(K*) == typeid(EVP_PKEY*)) && !getFunc)); - poco_check_ptr(ppKey); - poco_assert_dbg(!*ppKey); + template + static bool loadKey(K ** ppKey, PEM_read_BIO_Key_fn readFunc, F getFunc, std::istream * pIstr, const std::string & pass = "") + { + poco_assert_dbg( + ((typeid(K *) == typeid(RSA *) || typeid(K *) == typeid(EC_KEY *)) && getFunc) + || ((typeid(K *) == typeid(EVP_PKEY *)) && !getFunc)); + poco_check_ptr(ppKey); + poco_assert_dbg(!*ppKey); - BIO* pBIO = 0; - if (pIstr) - { - std::ostringstream ostr; - Poco::StreamCopier::copyStream(*pIstr, ostr); - std::string key = ostr.str(); - pBIO = BIO_new_mem_buf(const_cast(key.data()), static_cast(key.size())); - if (pBIO) - { - if (!getFunc) *ppKey = (K*)EVP_PKEY_new(); - EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey; - if (pKey) - { - pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)0 : &passCB; - void* pPassword = pass.empty() ? (void*)0 : (void*)pass.c_str(); - if (readFunc(pBIO, &pKey, pCB, pPassword)) - { - BIO_free(pBIO); pBIO = 0; - if (getFunc) - { - *ppKey = (K*)getFunc(pKey); - EVP_PKEY_free(pKey); - } - else - { - poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*)); - *ppKey = (K*)pKey; - } - if (!*ppKey) goto error; - return true; - } - if (getFunc) EVP_PKEY_free(pKey); - goto error; - } - else goto error; - } - else goto error; - } - return false; + BIO * pBIO = 0; + if (pIstr) + { + std::ostringstream ostr; + Poco::StreamCopier::copyStream(*pIstr, ostr); + std::string key = ostr.str(); + pBIO = BIO_new_mem_buf(const_cast(key.data()), static_cast(key.size())); + if (pBIO) + { + if (!getFunc) + *ppKey = (K *)EVP_PKEY_new(); + EVP_PKEY * pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY *)*ppKey; + if (pKey) + { + pem_password_cb * pCB = pass.empty() ? (pem_password_cb *)0 : &passCB; + void * pPassword = pass.empty() ? (void *)0 : (void *)pass.c_str(); + if (readFunc(pBIO, &pKey, pCB, pPassword)) + { + BIO_free(pBIO); + pBIO = 0; + if (getFunc) + { + *ppKey = (K *)getFunc(pKey); + EVP_PKEY_free(pKey); + } + else + { + poco_assert_dbg(typeid(K *) == typeid(EVP_PKEY *)); + *ppKey = (K *)pKey; + } + if (!*ppKey) + goto error; + return true; + } + if (getFunc) + EVP_PKEY_free(pKey); + goto error; + } + else + goto error; + } + else + goto error; + } + return false; - error: - if (pBIO) BIO_free(pBIO); - throw OpenSSLException("EVPKey::loadKey(stream)"); - } + error: + if (pBIO) + BIO_free(pBIO); + throw OpenSSLException("EVPKey::loadKey(stream)"); + } - EVP_PKEY* _pEVPPKey; + EVP_PKEY * _pEVPPKey; - friend class ECKeyImpl; - friend class RSAKeyImpl; -}; + friend class ECKeyImpl; + friend class RSAKeyImpl; + }; -// -// inlines -// + // + // inlines + // + + + inline bool EVPPKey::operator==(const EVPPKey & other) const + { + poco_check_ptr(other._pEVPPKey); + poco_check_ptr(_pEVPPKey); + return (1 == EVP_PKEY_cmp(_pEVPPKey, other._pEVPPKey)); + } + + + inline bool EVPPKey::operator!=(const EVPPKey & other) const + { + return !(other == *this); + } + + + inline int EVPPKey::type(const EVP_PKEY * pEVPPKey) + { + if (!pEVPPKey) + return NID_undef; + + return EVP_PKEY_type(EVP_PKEY_id(pEVPPKey)); + } + + + inline int EVPPKey::type() const + { + return type(_pEVPPKey); + } + + + inline bool EVPPKey::isSupported(int type) const + { + return type == EVP_PKEY_EC || type == EVP_PKEY_RSA; + } + + + inline EVPPKey::operator const EVP_PKEY *() const + { + return _pEVPPKey; + } + + + inline EVPPKey::operator EVP_PKEY *() + { + return _pEVPPKey; + } + + + inline void EVPPKey::setKey(EC_KEY * pKey) + { + if (!EVP_PKEY_set1_EC_KEY(_pEVPPKey, pKey)) + throw OpenSSLException(); + } + + + inline void EVPPKey::setKey(RSA * pKey) + { + if (!EVP_PKEY_set1_RSA(_pEVPPKey, pKey)) + throw OpenSSLException(); + } -inline bool EVPPKey::operator == (const EVPPKey& other) const -{ - poco_check_ptr (other._pEVPPKey); - poco_check_ptr (_pEVPPKey); - return (1 == EVP_PKEY_cmp(_pEVPPKey, other._pEVPPKey)); } - - -inline bool EVPPKey::operator != (const EVPPKey& other) const -{ - return !(other == *this); -} - - -inline int EVPPKey::type(const EVP_PKEY* pEVPPKey) -{ - if (!pEVPPKey) return NID_undef; - - return EVP_PKEY_type(EVP_PKEY_id(pEVPPKey)); -} - - -inline int EVPPKey::type() const -{ - return type(_pEVPPKey); -} - - -inline bool EVPPKey::isSupported(int type) const -{ - return type == EVP_PKEY_EC || type == EVP_PKEY_RSA; -} - - -inline EVPPKey::operator const EVP_PKEY*() const -{ - return _pEVPPKey; -} - - -inline EVPPKey::operator EVP_PKEY*() -{ - return _pEVPPKey; -} - - -inline void EVPPKey::setKey(EC_KEY* pKey) -{ - if (!EVP_PKEY_set1_EC_KEY(_pEVPPKey, pKey)) - throw OpenSSLException(); -} - - -inline void EVPPKey::setKey(RSA* pKey) -{ - if (!EVP_PKEY_set1_RSA(_pEVPPKey, pKey)) - throw OpenSSLException(); -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_EVPPKeyImpl_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/KeyPair.h b/base/poco/Crypto/include/Poco/Crypto/KeyPair.h index b9a705f8f1b..36adbec6a4d 100644 --- a/base/poco/Crypto/include/Poco/Crypto/KeyPair.h +++ b/base/poco/Crypto/include/Poco/Crypto/KeyPair.h @@ -23,111 +23,114 @@ #include "Poco/Crypto/KeyPairImpl.h" -namespace Poco { -namespace Crypto { - - -class X509Certificate; - - -class Crypto_API KeyPair - /// This is a parent class for classes storing a key pair, consisting - /// of private and public key. Storage of the private key is optional. - /// - /// If a private key is available, the KeyPair can be - /// used for decrypting data (encrypted with the public key) - /// or computing secure digital signatures. +namespace Poco { -public: - enum Type - { - KT_RSA = KeyPairImpl::KT_RSA_IMPL, - KT_EC = KeyPairImpl::KT_EC_IMPL - }; - - explicit KeyPair(KeyPairImpl::Ptr pKeyPairImpl = 0); - /// Extracts the RSA public key from the given certificate. - - virtual ~KeyPair(); - /// Destroys the KeyPair. - - virtual int size() const; - /// Returns the RSA modulus size. - - virtual void save(const std::string& publicKeyPairFile, - const std::string& privateKeyPairFile = "", - const std::string& privateKeyPairPassphrase = "") const; - /// Exports the public and private keys to the given files. - /// - /// If an empty filename is specified, the corresponding key - /// is not exported. - - virtual void save(std::ostream* pPublicKeyPairStream, - std::ostream* pPrivateKeyPairStream = 0, - const std::string& privateKeyPairPassphrase = "") const; - /// Exports the public and private key to the given streams. - /// - /// If a null pointer is passed for a stream, the corresponding - /// key is not exported. - - KeyPairImpl::Ptr impl() const; - /// Returns the impl object. - - const std::string& name() const; - /// Returns key pair name - - Type type() const; - /// Returns key pair type - -private: - KeyPairImpl::Ptr _pImpl; -}; - - -// -// inlines -// - -inline int KeyPair::size() const +namespace Crypto { - return _pImpl->size(); + + + class X509Certificate; + + + class Crypto_API KeyPair + /// This is a parent class for classes storing a key pair, consisting + /// of private and public key. Storage of the private key is optional. + /// + /// If a private key is available, the KeyPair can be + /// used for decrypting data (encrypted with the public key) + /// or computing secure digital signatures. + { + public: + enum Type + { + KT_RSA = KeyPairImpl::KT_RSA_IMPL, + KT_EC = KeyPairImpl::KT_EC_IMPL + }; + + explicit KeyPair(KeyPairImpl::Ptr pKeyPairImpl = 0); + /// Extracts the RSA public key from the given certificate. + + virtual ~KeyPair(); + /// Destroys the KeyPair. + + virtual int size() const; + /// Returns the RSA modulus size. + + virtual void save( + const std::string & publicKeyPairFile, + const std::string & privateKeyPairFile = "", + const std::string & privateKeyPairPassphrase = "") const; + /// Exports the public and private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. + + virtual void save( + std::ostream * pPublicKeyPairStream, + std::ostream * pPrivateKeyPairStream = 0, + const std::string & privateKeyPairPassphrase = "") const; + /// Exports the public and private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. + + KeyPairImpl::Ptr impl() const; + /// Returns the impl object. + + const std::string & name() const; + /// Returns key pair name + + Type type() const; + /// Returns key pair type + + private: + KeyPairImpl::Ptr _pImpl; + }; + + + // + // inlines + // + + inline int KeyPair::size() const + { + return _pImpl->size(); + } + + + inline void + KeyPair::save(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase) const + { + _pImpl->save(publicKeyFile, privateKeyFile, privateKeyPassphrase); + } + + + inline void + KeyPair::save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream, const std::string & privateKeyPassphrase) const + { + _pImpl->save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase); + } + + + inline const std::string & KeyPair::name() const + { + return _pImpl->name(); + } + + inline KeyPairImpl::Ptr KeyPair::impl() const + { + return _pImpl; + } + + + inline KeyPair::Type KeyPair::type() const + { + return (KeyPair::Type)impl()->type(); + } + + } - - -inline void KeyPair::save(const std::string& publicKeyFile, - const std::string& privateKeyFile, - const std::string& privateKeyPassphrase) const -{ - _pImpl->save(publicKeyFile, privateKeyFile, privateKeyPassphrase); -} - - -inline void KeyPair::save(std::ostream* pPublicKeyStream, - std::ostream* pPrivateKeyStream, - const std::string& privateKeyPassphrase) const -{ - _pImpl->save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase); -} - - -inline const std::string& KeyPair::name() const -{ - return _pImpl->name(); -} - -inline KeyPairImpl::Ptr KeyPair::impl() const -{ - return _pImpl; -} - - -inline KeyPair::Type KeyPair::type() const -{ - return (KeyPair::Type)impl()->type(); -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_KeyPair_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/KeyPairImpl.h b/base/poco/Crypto/include/Poco/Crypto/KeyPairImpl.h index e6320df044b..155efd20b9c 100644 --- a/base/poco/Crypto/include/Poco/Crypto/KeyPairImpl.h +++ b/base/poco/Crypto/include/Poco/Crypto/KeyPairImpl.h @@ -19,89 +19,92 @@ #define Crypto_KeyPairImplImpl_INCLUDED +#include +#include +#include "Poco/AutoPtr.h" #include "Poco/Crypto/Crypto.h" #include "Poco/Crypto/OpenSSLInitializer.h" #include "Poco/RefCountedObject.h" -#include "Poco/AutoPtr.h" -#include -#include -namespace Poco { -namespace Crypto { - - -class KeyPairImpl: public Poco::RefCountedObject - /// Class KeyPairImpl +namespace Poco { -public: - enum Type - { - KT_RSA_IMPL = 0, - KT_EC_IMPL - }; - - typedef Poco::AutoPtr Ptr; - typedef std::vector ByteVec; - - KeyPairImpl(const std::string& name, Type type); - /// Create KeyPairImpl with specified type and name. - - virtual ~KeyPairImpl(); - /// Destroys the KeyPairImpl. - - virtual int size() const = 0; - /// Returns the key size. - - virtual void save(const std::string& publicKeyFile, - const std::string& privateKeyFile = "", - const std::string& privateKeyPassphrase = "") const = 0; - /// Exports the public and private keys to the given files. - /// - /// If an empty filename is specified, the corresponding key - /// is not exported. - - virtual void save(std::ostream* pPublicKeyStream, - std::ostream* pPrivateKeyStream = 0, - const std::string& privateKeyPassphrase = "") const = 0; - /// Exports the public and private key to the given streams. - /// - /// If a null pointer is passed for a stream, the corresponding - /// key is not exported. - - const std::string& name() const; - /// Returns key pair name - - Type type() const; - /// Returns key pair type - -private: - KeyPairImpl(); - - std::string _name; - Type _type; - OpenSSLInitializer _openSSLInitializer; -}; - - -// -// inlines -// - - -inline const std::string& KeyPairImpl::name() const +namespace Crypto { - return _name; + + + class KeyPairImpl : public Poco::RefCountedObject + /// Class KeyPairImpl + { + public: + enum Type + { + KT_RSA_IMPL = 0, + KT_EC_IMPL + }; + + typedef Poco::AutoPtr Ptr; + typedef std::vector ByteVec; + + KeyPairImpl(const std::string & name, Type type); + /// Create KeyPairImpl with specified type and name. + + virtual ~KeyPairImpl(); + /// Destroys the KeyPairImpl. + + virtual int size() const = 0; + /// Returns the key size. + + virtual void save( + const std::string & publicKeyFile, + const std::string & privateKeyFile = "", + const std::string & privateKeyPassphrase = "") const = 0; + /// Exports the public and private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. + + virtual void save( + std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "") const = 0; + /// Exports the public and private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. + + const std::string & name() const; + /// Returns key pair name + + Type type() const; + /// Returns key pair type + + private: + KeyPairImpl(); + + std::string _name; + Type _type; + OpenSSLInitializer _openSSLInitializer; + }; + + + // + // inlines + // + + + inline const std::string & KeyPairImpl::name() const + { + return _name; + } + + + inline KeyPairImpl::Type KeyPairImpl::type() const + { + return _type; + } + + } - - -inline KeyPairImpl::Type KeyPairImpl::type() const -{ - return _type; -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_KeyPairImplImpl_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/OpenSSLInitializer.h b/base/poco/Crypto/include/Poco/Crypto/OpenSSLInitializer.h index ce822a69710..147cfaeefca 100644 --- a/base/poco/Crypto/include/Poco/Crypto/OpenSSLInitializer.h +++ b/base/poco/Crypto/include/Poco/Crypto/OpenSSLInitializer.h @@ -18,98 +18,100 @@ #define Crypto_OpenSSLInitializer_INCLUDED +#include +#include "Poco/AtomicCounter.h" #include "Poco/Crypto/Crypto.h" #include "Poco/Mutex.h" -#include "Poco/AtomicCounter.h" -#include #if defined(OPENSSL_FIPS) && OPENSSL_VERSION_NUMBER < 0x010001000L -#include +# include #endif -extern "C" +extern "C" { +struct CRYPTO_dynlock_value { - struct CRYPTO_dynlock_value - { - Poco::FastMutex _mutex; - }; -} - - -namespace Poco { -namespace Crypto { - - -class Crypto_API OpenSSLInitializer - /// Initializes the OpenSSL library. - /// - /// The class ensures the earliest initialization and the - /// latest shutdown of the OpenSSL library. -{ -public: - OpenSSLInitializer(); - /// Automatically initialize OpenSSL on startup. - - ~OpenSSLInitializer(); - /// Automatically shut down OpenSSL on exit. - - static void initialize(); - /// Initializes the OpenSSL machinery. - - static void uninitialize(); - /// Shuts down the OpenSSL machinery. - - static bool isFIPSEnabled(); - // Returns true if FIPS mode is enabled, false otherwise. - - static void enableFIPSMode(bool enabled); - // Enable or disable FIPS mode. If FIPS is not available, this method doesn't do anything. - -protected: - enum - { - SEEDSIZE = 256 - }; - - // OpenSSL multithreading support - static void lock(int mode, int n, const char* file, int line); - static unsigned long id(); - static struct CRYPTO_dynlock_value* dynlockCreate(const char* file, int line); - static void dynlock(int mode, struct CRYPTO_dynlock_value* lock, const char* file, int line); - static void dynlockDestroy(struct CRYPTO_dynlock_value* lock, const char* file, int line); - -private: - static Poco::FastMutex* _mutexes; - static Poco::AtomicCounter _rc; + Poco::FastMutex _mutex; }; +} -// -// inlines -// -inline bool OpenSSLInitializer::isFIPSEnabled() +namespace Poco { +namespace Crypto +{ + + + class Crypto_API OpenSSLInitializer + /// Initializes the OpenSSL library. + /// + /// The class ensures the earliest initialization and the + /// latest shutdown of the OpenSSL library. + { + public: + OpenSSLInitializer(); + /// Automatically initialize OpenSSL on startup. + + ~OpenSSLInitializer(); + /// Automatically shut down OpenSSL on exit. + + static void initialize(); + /// Initializes the OpenSSL machinery. + + static void uninitialize(); + /// Shuts down the OpenSSL machinery. + + static bool isFIPSEnabled(); + // Returns true if FIPS mode is enabled, false otherwise. + + static void enableFIPSMode(bool enabled); + // Enable or disable FIPS mode. If FIPS is not available, this method doesn't do anything. + + protected: + enum + { + SEEDSIZE = 256 + }; + + // OpenSSL multithreading support + static void lock(int mode, int n, const char * file, int line); + static unsigned long id(); + static struct CRYPTO_dynlock_value * dynlockCreate(const char * file, int line); + static void dynlock(int mode, struct CRYPTO_dynlock_value * lock, const char * file, int line); + static void dynlockDestroy(struct CRYPTO_dynlock_value * lock, const char * file, int line); + + private: + static Poco::FastMutex * _mutexes; + static Poco::AtomicCounter _rc; + }; + + + // + // inlines + // + inline bool OpenSSLInitializer::isFIPSEnabled() + { #ifdef OPENSSL_FIPS - return FIPS_mode() ? true : false; + return FIPS_mode() ? true : false; #else - return false; + return false; #endif -} + } #ifdef OPENSSL_FIPS -inline void OpenSSLInitializer::enableFIPSMode(bool enabled) -{ - FIPS_mode_set(enabled); -} + inline void OpenSSLInitializer::enableFIPSMode(bool enabled) + { + FIPS_mode_set(enabled); + } #else -inline void OpenSSLInitializer::enableFIPSMode(bool /*enabled*/) -{ -} + inline void OpenSSLInitializer::enableFIPSMode(bool /*enabled*/) + { + } #endif -} } // namespace Poco::Crypto +} +} // namespace Poco::Crypto #endif // Crypto_OpenSSLInitializer_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/PKCS12Container.h b/base/poco/Crypto/include/Poco/Crypto/PKCS12Container.h index 63cc224d8cc..40baa496827 100644 --- a/base/poco/Crypto/include/Poco/Crypto/PKCS12Container.h +++ b/base/poco/Crypto/include/Poco/Crypto/PKCS12Container.h @@ -18,142 +18,145 @@ #define Crypto_PKCS12Container_INCLUDED +#include +#include +#include #include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/EVPPKey.h" #include "Poco/Crypto/OpenSSLInitializer.h" #include "Poco/Crypto/X509Certificate.h" -#include "Poco/Crypto/EVPPKey.h" #include "Poco/Path.h" -#include -#include -#include -namespace Poco { -namespace Crypto { - - -class Crypto_API PKCS12Container - /// This class implements PKCS#12 container functionality. +namespace Poco +{ +namespace Crypto { -public: - typedef X509Certificate::List CAList; - typedef std::vector CANameList; - explicit PKCS12Container(std::istream& istr, const std::string& password = ""); - /// Creates the PKCS12Container object from a stream. - explicit PKCS12Container(const std::string& path, const std::string& password = ""); - /// Creates the PKCS12Container object from a file. + class Crypto_API PKCS12Container + /// This class implements PKCS#12 container functionality. + { + public: + typedef X509Certificate::List CAList; + typedef std::vector CANameList; - PKCS12Container(const PKCS12Container& cont); - /// Copy constructor. + explicit PKCS12Container(std::istream & istr, const std::string & password = ""); + /// Creates the PKCS12Container object from a stream. - PKCS12Container& operator = (const PKCS12Container& cont); - /// Assignment operator. + explicit PKCS12Container(const std::string & path, const std::string & password = ""); + /// Creates the PKCS12Container object from a file. + + PKCS12Container(const PKCS12Container & cont); + /// Copy constructor. + + PKCS12Container & operator=(const PKCS12Container & cont); + /// Assignment operator. #ifdef POCO_ENABLE_CPP11 - PKCS12Container(PKCS12Container&& cont); - /// Move constructor. + PKCS12Container(PKCS12Container && cont); + /// Move constructor. - PKCS12Container& operator = (PKCS12Container&& cont); - /// Move assignment operator. + PKCS12Container & operator=(PKCS12Container && cont); + /// Move assignment operator. #endif // POCO_ENABLE_CPP11 - ~PKCS12Container(); - /// Destroys the PKCS12Container. + ~PKCS12Container(); + /// Destroys the PKCS12Container. - bool hasKey() const; - /// Returns true if container contains the key. + bool hasKey() const; + /// Returns true if container contains the key. - EVPPKey getKey() const; - /// Return key as openssl EVP_PKEY wrapper object. + EVPPKey getKey() const; + /// Return key as openssl EVP_PKEY wrapper object. - bool hasX509Certificate() const; - /// Returns true if container has X509 certificate. + bool hasX509Certificate() const; + /// Returns true if container has X509 certificate. - const X509Certificate& getX509Certificate() const; - /// Returns the X509 certificate. - /// Throws NotFoundException if there is no certificate. + const X509Certificate & getX509Certificate() const; + /// Returns the X509 certificate. + /// Throws NotFoundException if there is no certificate. - const CAList& getCACerts() const; - /// Returns the list of CA certificates in this container. + const CAList & getCACerts() const; + /// Returns the list of CA certificates in this container. - const std::string& getFriendlyName() const; - /// Returns the friendly name of the certificate bag. + const std::string & getFriendlyName() const; + /// Returns the friendly name of the certificate bag. - const CANameList& getFriendlyNamesCA() const; - /// Returns a list of CA certificates friendly names. + const CANameList & getFriendlyNamesCA() const; + /// Returns a list of CA certificates friendly names. -private: - void load(PKCS12* pPKCS12, const std::string& password = ""); - std::string extractFriendlyName(X509* pCert); + private: + void load(PKCS12 * pPKCS12, const std::string & password = ""); + std::string extractFriendlyName(X509 * pCert); #ifdef POCO_ENABLE_CPP11 - typedef std::unique_ptr CertPtr; + typedef std::unique_ptr CertPtr; #else - typedef std::auto_ptr CertPtr; + typedef std::auto_ptr CertPtr; #endif // #ifdef POCO_ENABLE_CPP11 - OpenSSLInitializer _openSSLInitializer; - EVP_PKEY* _pKey; - CertPtr _pX509Cert; - CAList _caCertList; - CANameList _caCertNames; - std::string _pkcsFriendlyName; -}; + OpenSSLInitializer _openSSLInitializer; + EVP_PKEY * _pKey; + CertPtr _pX509Cert; + CAList _caCertList; + CANameList _caCertNames; + std::string _pkcsFriendlyName; + }; -// -// inlines -// + // + // inlines + // + + inline bool PKCS12Container::hasX509Certificate() const + { + return _pX509Cert.get() != 0; + } + + + inline const X509Certificate & PKCS12Container::getX509Certificate() const + { + if (!hasX509Certificate()) + throw NotFoundException("PKCS12Container X509 certificate"); + return *_pX509Cert; + } + + + inline const std::string & PKCS12Container::getFriendlyName() const + { + return _pkcsFriendlyName; + } + + + inline const PKCS12Container::CAList & PKCS12Container::getCACerts() const + { + return _caCertList; + } + + + inline const PKCS12Container::CANameList & PKCS12Container::getFriendlyNamesCA() const + { + return _caCertNames; + } + + + inline bool PKCS12Container::hasKey() const + { + return _pKey != 0; + } + + + inline EVPPKey PKCS12Container::getKey() const + { + return EVPPKey(_pKey); + } + -inline bool PKCS12Container::hasX509Certificate() const -{ - return _pX509Cert.get() != 0; } - - -inline const X509Certificate& PKCS12Container::getX509Certificate() const -{ - if (!hasX509Certificate()) - throw NotFoundException("PKCS12Container X509 certificate"); - return *_pX509Cert; -} - - -inline const std::string& PKCS12Container::getFriendlyName() const -{ - return _pkcsFriendlyName; -} - - -inline const PKCS12Container::CAList& PKCS12Container::getCACerts() const -{ - return _caCertList; -} - - -inline const PKCS12Container::CANameList& PKCS12Container::getFriendlyNamesCA() const -{ - return _caCertNames; -} - - -inline bool PKCS12Container::hasKey() const -{ - return _pKey != 0; -} - - -inline EVPPKey PKCS12Container::getKey() const -{ - return EVPPKey(_pKey); -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_PKCS12Container_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/RSACipherImpl.h b/base/poco/Crypto/include/Poco/Crypto/RSACipherImpl.h index 2ebc38e3b55..c0920b4099a 100644 --- a/base/poco/Crypto/include/Poco/Crypto/RSACipherImpl.h +++ b/base/poco/Crypto/include/Poco/Crypto/RSACipherImpl.h @@ -18,60 +18,63 @@ #define Crypto_RSACipherImpl_INCLUDED -#include "Poco/Crypto/Crypto.h" -#include "Poco/Crypto/Cipher.h" -#include "Poco/Crypto/RSAKey.h" -#include "Poco/Crypto/OpenSSLInitializer.h" #include +#include "Poco/Crypto/Cipher.h" +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include "Poco/Crypto/RSAKey.h" -namespace Poco { -namespace Crypto { - - -class RSACipherImpl: public Cipher - /// An implementation of the Cipher class for - /// asymmetric (public-private key) encryption - /// based on the the RSA algorithm in OpenSSL's - /// crypto library. - /// - /// Encryption is using the public key, decryption - /// requires the private key. +namespace Poco { -public: - RSACipherImpl(const RSAKey& key, RSAPaddingMode paddingMode); - /// Creates a new RSACipherImpl object for the given RSAKey - /// and using the given padding mode. - - virtual ~RSACipherImpl(); - /// Destroys the RSACipherImpl. - - const std::string& name() const; - /// Returns the name of the Cipher. - - CryptoTransform* createEncryptor(); - /// Creates an encryptor object. - - CryptoTransform* createDecryptor(); - /// Creates a decryptor object. - -private: - RSAKey _key; - RSAPaddingMode _paddingMode; - OpenSSLInitializer _openSSLInitializer; -}; - - -// -// Inlines -// -inline const std::string& RSACipherImpl::name() const +namespace Crypto { - return _key.name(); + + + class RSACipherImpl : public Cipher + /// An implementation of the Cipher class for + /// asymmetric (public-private key) encryption + /// based on the the RSA algorithm in OpenSSL's + /// crypto library. + /// + /// Encryption is using the public key, decryption + /// requires the private key. + { + public: + RSACipherImpl(const RSAKey & key, RSAPaddingMode paddingMode); + /// Creates a new RSACipherImpl object for the given RSAKey + /// and using the given padding mode. + + virtual ~RSACipherImpl(); + /// Destroys the RSACipherImpl. + + const std::string & name() const; + /// Returns the name of the Cipher. + + CryptoTransform * createEncryptor(); + /// Creates an encryptor object. + + CryptoTransform * createDecryptor(); + /// Creates a decryptor object. + + private: + RSAKey _key; + RSAPaddingMode _paddingMode; + OpenSSLInitializer _openSSLInitializer; + }; + + + // + // Inlines + // + inline const std::string & RSACipherImpl::name() const + { + return _key.name(); + } + + } - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_RSACipherImpl_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/RSADigestEngine.h b/base/poco/Crypto/include/Poco/Crypto/RSADigestEngine.h index 7c4d3860508..980fae1f0f0 100644 --- a/base/poco/Crypto/include/Poco/Crypto/RSADigestEngine.h +++ b/base/poco/Crypto/include/Poco/Crypto/RSADigestEngine.h @@ -18,94 +18,97 @@ #define Crypto_RSADigestEngine_INCLUDED -#include "Poco/Crypto/Crypto.h" -#include "Poco/Crypto/RSAKey.h" -#include "Poco/DigestEngine.h" -#include "Poco/Crypto/DigestEngine.h" #include #include +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/DigestEngine.h" +#include "Poco/Crypto/RSAKey.h" +#include "Poco/DigestEngine.h" -namespace Poco { -namespace Crypto { - - -class Crypto_API RSADigestEngine: public Poco::DigestEngine - /// This class implements a Poco::DigestEngine that can be - /// used to compute a secure digital signature. - /// - /// First another Poco::Crypto::DigestEngine is created and - /// used to compute a cryptographic hash of the data to be - /// signed. Then, the hash value is encrypted, using - /// the RSA private key. - /// - /// To verify a signature, pass it to the verify() - /// member function. It will decrypt the signature - /// using the RSA public key and compare the resulting - /// hash with the actual hash of the data. +namespace Poco +{ +namespace Crypto { -public: - enum DigestType - { - DIGEST_MD5, - DIGEST_SHA1 - }; - - //@ deprecated - RSADigestEngine(const RSAKey& key, DigestType digestType = DIGEST_SHA1); - /// Creates the RSADigestEngine with the given RSA key, - /// using the MD5 or SHA-1 hash algorithm. - /// Kept for backward compatibility - - RSADigestEngine(const RSAKey& key, const std::string &name); - /// Creates the RSADigestEngine with the given RSA key, - /// using the hash algorithm with the given name - /// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.). - /// See the OpenSSL documentation for a list of supported digest algorithms. - /// - /// Throws a Poco::NotFoundException if no algorithm with the given name exists. - - ~RSADigestEngine(); - /// Destroys the RSADigestEngine. - - std::size_t digestLength() const; - /// Returns the length of the digest in bytes. - - void reset(); - /// Resets the engine so that a new - /// digest can be computed. - - const DigestEngine::Digest& digest(); - /// Finishes the computation of the digest - /// (the first time it's called) and - /// returns the message digest. - /// - /// Can be called multiple times. - - const DigestEngine::Digest& signature(); - /// Signs the digest using the RSA algorithm - /// and the private key (the first time it's - /// called) and returns the result. - /// - /// Can be called multiple times. - - bool verify(const DigestEngine::Digest& signature); - /// Verifies the data against the signature. - /// - /// Returns true if the signature can be verified, false otherwise. - -protected: - void updateImpl(const void* data, std::size_t length); - -private: - RSAKey _key; - Poco::Crypto::DigestEngine _engine; - Poco::DigestEngine::Digest _digest; - Poco::DigestEngine::Digest _signature; -}; -} } // namespace Poco::Crypto + class Crypto_API RSADigestEngine : public Poco::DigestEngine + /// This class implements a Poco::DigestEngine that can be + /// used to compute a secure digital signature. + /// + /// First another Poco::Crypto::DigestEngine is created and + /// used to compute a cryptographic hash of the data to be + /// signed. Then, the hash value is encrypted, using + /// the RSA private key. + /// + /// To verify a signature, pass it to the verify() + /// member function. It will decrypt the signature + /// using the RSA public key and compare the resulting + /// hash with the actual hash of the data. + { + public: + enum DigestType + { + DIGEST_MD5, + DIGEST_SHA1 + }; + + //@ deprecated + RSADigestEngine(const RSAKey & key, DigestType digestType = DIGEST_SHA1); + /// Creates the RSADigestEngine with the given RSA key, + /// using the MD5 or SHA-1 hash algorithm. + /// Kept for backward compatibility + + RSADigestEngine(const RSAKey & key, const std::string & name); + /// Creates the RSADigestEngine with the given RSA key, + /// using the hash algorithm with the given name + /// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.). + /// See the OpenSSL documentation for a list of supported digest algorithms. + /// + /// Throws a Poco::NotFoundException if no algorithm with the given name exists. + + ~RSADigestEngine(); + /// Destroys the RSADigestEngine. + + std::size_t digestLength() const; + /// Returns the length of the digest in bytes. + + void reset(); + /// Resets the engine so that a new + /// digest can be computed. + + const DigestEngine::Digest & digest(); + /// Finishes the computation of the digest + /// (the first time it's called) and + /// returns the message digest. + /// + /// Can be called multiple times. + + const DigestEngine::Digest & signature(); + /// Signs the digest using the RSA algorithm + /// and the private key (the first time it's + /// called) and returns the result. + /// + /// Can be called multiple times. + + bool verify(const DigestEngine::Digest & signature); + /// Verifies the data against the signature. + /// + /// Returns true if the signature can be verified, false otherwise. + + protected: + void updateImpl(const void * data, std::size_t length); + + private: + RSAKey _key; + Poco::Crypto::DigestEngine _engine; + Poco::DigestEngine::Digest _digest; + Poco::DigestEngine::Digest _signature; + }; + + +} +} // namespace Poco::Crypto #endif // Crypto_RSADigestEngine_INCLUDED diff --git a/base/poco/Crypto/include/Poco/Crypto/RSAKey.h b/base/poco/Crypto/include/Poco/Crypto/RSAKey.h index ad9163ed42f..47a01e15746 100644 --- a/base/poco/Crypto/include/Poco/Crypto/RSAKey.h +++ b/base/poco/Crypto/include/Poco/Crypto/RSAKey.h @@ -23,103 +23,102 @@ #include "Poco/Crypto/RSAKeyImpl.h" -namespace Poco { -namespace Crypto { - - -class X509Certificate; -class PKCS12Container; - - -class Crypto_API RSAKey : public KeyPair - /// This class stores an RSA key pair, consisting - /// of private and public key. Storage of the private - /// key is optional. - /// - /// If a private key is available, the RSAKey can be - /// used for decrypting data (encrypted with the public key) - /// or computing secure digital signatures. +namespace Poco { -public: - enum KeyLength - { - KL_512 = 512, - KL_1024 = 1024, - KL_2048 = 2048, - KL_4096 = 4096 - }; - - enum Exponent - { - EXP_SMALL = 0, - EXP_LARGE - }; - - RSAKey(const EVPPKey& key); - /// Constructs ECKeyImpl by extracting the EC key. - - RSAKey(const X509Certificate& cert); - /// Extracts the RSA public key from the given certificate. - - RSAKey(const PKCS12Container& cert); - /// Extracts the RSA private key from the given certificate. - - RSAKey(KeyLength keyLength, Exponent exp); - /// Creates the RSAKey. Creates a new public/private keypair using the given parameters. - /// Can be used to sign data and verify signatures. - - RSAKey(const std::string& publicKeyFile, - const std::string& privateKeyFile = "", - const std::string& privateKeyPassphrase = ""); - /// Creates the RSAKey, by reading public and private key from the given files and - /// using the given passphrase for the private key. - /// - /// Cannot be used for signing or decryption unless a private key is available. - /// - /// If a private key is specified, you don't need to specify a public key file. - /// OpenSSL will auto-create the public key from the private key. - - RSAKey(std::istream* pPublicKeyStream, - std::istream* pPrivateKeyStream = 0, - const std::string& privateKeyPassphrase = ""); - /// Creates the RSAKey, by reading public and private key from the given streams and - /// using the given passphrase for the private key. - /// - /// Cannot be used for signing or decryption unless a private key is available. - /// - /// If a private key is specified, you don't need to specify a public key file. - /// OpenSSL will auto-create the public key from the private key. - - ~RSAKey(); - /// Destroys the RSAKey. - - RSAKeyImpl::ByteVec modulus() const; - /// Returns the RSA modulus. - - RSAKeyImpl::ByteVec encryptionExponent() const; - /// Returns the RSA encryption exponent. - - RSAKeyImpl::ByteVec decryptionExponent() const; - /// Returns the RSA decryption exponent. - - RSAKeyImpl::Ptr impl() const; - /// Returns the impl object. - -private: - RSAKeyImpl::Ptr _pImpl; -}; - - -// -// inlines -// -inline RSAKeyImpl::Ptr RSAKey::impl() const +namespace Crypto { - return _pImpl; + + + class X509Certificate; + class PKCS12Container; + + + class Crypto_API RSAKey : public KeyPair + /// This class stores an RSA key pair, consisting + /// of private and public key. Storage of the private + /// key is optional. + /// + /// If a private key is available, the RSAKey can be + /// used for decrypting data (encrypted with the public key) + /// or computing secure digital signatures. + { + public: + enum KeyLength + { + KL_512 = 512, + KL_1024 = 1024, + KL_2048 = 2048, + KL_4096 = 4096 + }; + + enum Exponent + { + EXP_SMALL = 0, + EXP_LARGE + }; + + RSAKey(const EVPPKey & key); + /// Constructs ECKeyImpl by extracting the EC key. + + RSAKey(const X509Certificate & cert); + /// Extracts the RSA public key from the given certificate. + + RSAKey(const PKCS12Container & cert); + /// Extracts the RSA private key from the given certificate. + + RSAKey(KeyLength keyLength, Exponent exp); + /// Creates the RSAKey. Creates a new public/private keypair using the given parameters. + /// Can be used to sign data and verify signatures. + + RSAKey(const std::string & publicKeyFile, const std::string & privateKeyFile = "", const std::string & privateKeyPassphrase = ""); + /// Creates the RSAKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. + /// + /// Cannot be used for signing or decryption unless a private key is available. + /// + /// If a private key is specified, you don't need to specify a public key file. + /// OpenSSL will auto-create the public key from the private key. + + RSAKey(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = ""); + /// Creates the RSAKey, by reading public and private key from the given streams and + /// using the given passphrase for the private key. + /// + /// Cannot be used for signing or decryption unless a private key is available. + /// + /// If a private key is specified, you don't need to specify a public key file. + /// OpenSSL will auto-create the public key from the private key. + + ~RSAKey(); + /// Destroys the RSAKey. + + RSAKeyImpl::ByteVec modulus() const; + /// Returns the RSA modulus. + + RSAKeyImpl::ByteVec encryptionExponent() const; + /// Returns the RSA encryption exponent. + + RSAKeyImpl::ByteVec decryptionExponent() const; + /// Returns the RSA decryption exponent. + + RSAKeyImpl::Ptr impl() const; + /// Returns the impl object. + + private: + RSAKeyImpl::Ptr _pImpl; + }; + + + // + // inlines + // + inline RSAKeyImpl::Ptr RSAKey::impl() const + { + return _pImpl; + } + + } - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_RSAKey_INCLUDED \ No newline at end of file diff --git a/base/poco/Crypto/include/Poco/Crypto/RSAKeyImpl.h b/base/poco/Crypto/include/Poco/Crypto/RSAKeyImpl.h index 035881636b2..4ccbb324c06 100644 --- a/base/poco/Crypto/include/Poco/Crypto/RSAKeyImpl.h +++ b/base/poco/Crypto/include/Poco/Crypto/RSAKeyImpl.h @@ -18,15 +18,15 @@ #define Crypto_RSAKeyImplImpl_INCLUDED +#include +#include +#include +#include "Poco/AutoPtr.h" #include "Poco/Crypto/Crypto.h" #include "Poco/Crypto/EVPPKey.h" #include "Poco/Crypto/KeyPairImpl.h" #include "Poco/Crypto/OpenSSLInitializer.h" #include "Poco/RefCountedObject.h" -#include "Poco/AutoPtr.h" -#include -#include -#include struct bignum_st; @@ -35,107 +35,108 @@ typedef struct bignum_st BIGNUM; typedef struct rsa_st RSA; -namespace Poco { -namespace Crypto { - - -class X509Certificate; -class PKCS12Container; - - -class RSAKeyImpl: public KeyPairImpl - /// class RSAKeyImpl +namespace Poco { -public: - typedef Poco::AutoPtr Ptr; - typedef std::vector ByteVec; - - RSAKeyImpl(const EVPPKey& key); - /// Constructs ECKeyImpl by extracting the EC key. - - RSAKeyImpl(const X509Certificate& cert); - /// Extracts the RSA public key from the given certificate. - - RSAKeyImpl(const PKCS12Container& cert); - /// Extracts the EC private key from the given certificate. - - RSAKeyImpl(int keyLength, unsigned long exponent); - /// Creates the RSAKey. Creates a new public/private keypair using the given parameters. - /// Can be used to sign data and verify signatures. - - RSAKeyImpl(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase); - /// Creates the RSAKey, by reading public and private key from the given files and - /// using the given passphrase for the private key. Can only by used for signing if - /// a private key is available. - - RSAKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase); - /// Creates the RSAKey. Can only by used for signing if pPrivKey - /// is not null. If a private key file is specified, you don't need to - /// specify a public key file. OpenSSL will auto-create it from the private key. - - ~RSAKeyImpl(); - /// Destroys the RSAKeyImpl. - - RSA* getRSA(); - /// Returns the OpenSSL RSA object. - - const RSA* getRSA() const; - /// Returns the OpenSSL RSA object. - - int size() const; - /// Returns the RSA modulus size. - - ByteVec modulus() const; - /// Returns the RSA modulus. - - ByteVec encryptionExponent() const; - /// Returns the RSA encryption exponent. - - ByteVec decryptionExponent() const; - /// Returns the RSA decryption exponent. - - void save(const std::string& publicKeyFile, - const std::string& privateKeyFile = "", - const std::string& privateKeyPassphrase = "") const; - /// Exports the public and private keys to the given files. - /// - /// If an empty filename is specified, the corresponding key - /// is not exported. - - void save(std::ostream* pPublicKeyStream, - std::ostream* pPrivateKeyStream = 0, - const std::string& privateKeyPassphrase = "") const; - /// Exports the public and private key to the given streams. - /// - /// If a null pointer is passed for a stream, the corresponding - /// key is not exported. - -private: - RSAKeyImpl(); - - void freeRSA(); - static ByteVec convertToByteVec(const BIGNUM* bn); - - RSA* _pRSA; -}; - - -// -// inlines -// -inline RSA* RSAKeyImpl::getRSA() +namespace Crypto { - return _pRSA; + + + class X509Certificate; + class PKCS12Container; + + + class RSAKeyImpl : public KeyPairImpl + /// class RSAKeyImpl + { + public: + typedef Poco::AutoPtr Ptr; + typedef std::vector ByteVec; + + RSAKeyImpl(const EVPPKey & key); + /// Constructs ECKeyImpl by extracting the EC key. + + RSAKeyImpl(const X509Certificate & cert); + /// Extracts the RSA public key from the given certificate. + + RSAKeyImpl(const PKCS12Container & cert); + /// Extracts the EC private key from the given certificate. + + RSAKeyImpl(int keyLength, unsigned long exponent); + /// Creates the RSAKey. Creates a new public/private keypair using the given parameters. + /// Can be used to sign data and verify signatures. + + RSAKeyImpl(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase); + /// Creates the RSAKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. Can only by used for signing if + /// a private key is available. + + RSAKeyImpl(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream, const std::string & privateKeyPassphrase); + /// Creates the RSAKey. Can only by used for signing if pPrivKey + /// is not null. If a private key file is specified, you don't need to + /// specify a public key file. OpenSSL will auto-create it from the private key. + + ~RSAKeyImpl(); + /// Destroys the RSAKeyImpl. + + RSA * getRSA(); + /// Returns the OpenSSL RSA object. + + const RSA * getRSA() const; + /// Returns the OpenSSL RSA object. + + int size() const; + /// Returns the RSA modulus size. + + ByteVec modulus() const; + /// Returns the RSA modulus. + + ByteVec encryptionExponent() const; + /// Returns the RSA encryption exponent. + + ByteVec decryptionExponent() const; + /// Returns the RSA decryption exponent. + + void save(const std::string & publicKeyFile, const std::string & privateKeyFile = "", const std::string & privateKeyPassphrase = "") + const; + /// Exports the public and private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. + + void + save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "") const; + /// Exports the public and private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. + + private: + RSAKeyImpl(); + + void freeRSA(); + static ByteVec convertToByteVec(const BIGNUM * bn); + + RSA * _pRSA; + }; + + + // + // inlines + // + inline RSA * RSAKeyImpl::getRSA() + { + return _pRSA; + } + + + inline const RSA * RSAKeyImpl::getRSA() const + { + return _pRSA; + } + + } - - -inline const RSA* RSAKeyImpl::getRSA() const -{ - return _pRSA; -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_RSAKeyImplImpl_INCLUDED \ No newline at end of file diff --git a/base/poco/Crypto/include/Poco/Crypto/X509Certificate.h b/base/poco/Crypto/include/Poco/Crypto/X509Certificate.h index ccdab1ce37e..30147623035 100644 --- a/base/poco/Crypto/include/Poco/Crypto/X509Certificate.h +++ b/base/poco/Crypto/include/Poco/Crypto/X509Certificate.h @@ -18,228 +18,231 @@ #define Crypto_X509Certificate_INCLUDED +#include +#include +#include +#include #include "Poco/Crypto/Crypto.h" #include "Poco/Crypto/OpenSSLInitializer.h" #include "Poco/DateTime.h" #include "Poco/SharedPtr.h" -#include -#include -#include -#include -namespace Poco { -namespace Crypto { - - -class Crypto_API X509Certificate - /// This class represents a X509 Certificate. +namespace Poco { -public: - typedef std::vector List; - - enum NID - /// Name identifier for extracting information from - /// a certificate subject's or issuer's distinguished name. - { - NID_COMMON_NAME = 13, - NID_COUNTRY = 14, - NID_LOCALITY_NAME = 15, - NID_STATE_OR_PROVINCE = 16, - NID_ORGANIZATION_NAME = 17, - NID_ORGANIZATION_UNIT_NAME = 18, - NID_PKCS9_EMAIL_ADDRESS = 48, - NID_SERIAL_NUMBER = 105 - }; - - explicit X509Certificate(std::istream& istr); - /// Creates the X509Certificate object by reading - /// a certificate in PEM format from a stream. - - explicit X509Certificate(const std::string& path); - /// Creates the X509Certificate object by reading - /// a certificate in PEM format from a file. - - explicit X509Certificate(X509* pCert); - /// Creates the X509Certificate from an existing - /// OpenSSL certificate. Ownership is taken of - /// the certificate. - - X509Certificate(X509* pCert, bool shared); - /// Creates the X509Certificate from an existing - /// OpenSSL certificate. Ownership is taken of - /// the certificate. If shared is true, the - /// certificate's reference count is incremented. - - X509Certificate(const X509Certificate& cert); - /// Creates the certificate by copying another one. - - X509Certificate& operator = (const X509Certificate& cert); - /// Assigns a certificate. - - void swap(X509Certificate& cert); - /// Exchanges the certificate with another one. - - ~X509Certificate(); - /// Destroys the X509Certificate. - - long version() const; - /// Returns the version of the certificate. - - const std::string& serialNumber() const; - /// Returns the certificate serial number as a - /// string in decimal encoding. - - const std::string& issuerName() const; - /// Returns the certificate issuer's distinguished name. - - std::string issuerName(NID nid) const; - /// Extracts the information specified by the given - /// NID (name identifier) from the certificate issuer's - /// distinguished name. - - const std::string& subjectName() const; - /// Returns the certificate subject's distinguished name. - - std::string subjectName(NID nid) const; - /// Extracts the information specified by the given - /// NID (name identifier) from the certificate subject's - /// distinguished name. - - std::string commonName() const; - /// Returns the common name stored in the certificate - /// subject's distinguished name. - - void extractNames(std::string& commonName, std::set& domainNames) const; - /// Extracts the common name and the alias domain names from the - /// certificate. - - Poco::DateTime validFrom() const; - /// Returns the date and time the certificate is valid from. - - Poco::DateTime expiresOn() const; - /// Returns the date and time the certificate expires. - - void save(std::ostream& stream) const; - /// Writes the certificate to the given stream. - /// The certificate is written in PEM format. - - void save(const std::string& path) const; - /// Writes the certificate to the file given by path. - /// The certificate is written in PEM format. - - bool issuedBy(const X509Certificate& issuerCertificate) const; - /// Checks whether the certificate has been issued by - /// the issuer given by issuerCertificate. This can be - /// used to validate a certificate chain. - /// - /// Verifies if the certificate has been signed with the - /// issuer's private key, using the public key from the issuer - /// certificate. - /// - /// Returns true if verification against the issuer certificate - /// was successful, false otherwise. - - bool equals(const X509Certificate& otherCertificate) const; - /// Checks whether the certificate is equal to - /// the other certificate, by comparing the hashes - /// of both certificates. - /// - /// Returns true if both certificates are identical, - /// otherwise false. - - const X509* certificate() const; - /// Returns the underlying OpenSSL certificate. - - X509* dup() const; - /// Duplicates and returns the underlying OpenSSL certificate. Note that - /// the caller assumes responsibility for the lifecycle of the created - /// certificate. - - std::string signatureAlgorithm() const; - /// Returns the certificate signature algorithm long name. - - void print(std::ostream& out) const; - /// Prints the certificate information to ostream. - - static List readPEM(const std::string& pemFileName); - /// Reads and returns a list of certificates from - /// the specified PEM file. - - static void writePEM(const std::string& pemFileName, const List& list); - /// Writes the list of certificates to the specified PEM file. - -protected: - void load(std::istream& stream); - /// Loads the certificate from the given stream. The - /// certificate must be in PEM format. - - void load(const std::string& path); - /// Loads the certificate from the given file. The - /// certificate must be in PEM format. - - void init(); - /// Extracts issuer and subject name from the certificate. - -private: - enum - { - NAME_BUFFER_SIZE = 256 - }; - - std::string _issuerName; - std::string _subjectName; - std::string _serialNumber; - X509* _pCert; - OpenSSLInitializer _openSSLInitializer; -}; - - -// -// inlines -// - - -inline long X509Certificate::version() const +namespace Crypto { - // This is defined by standards (X.509 et al) to be - // one less than the certificate version. - // So, eg. a version 3 certificate will return 2. - return X509_get_version(_pCert) + 1; + + + class Crypto_API X509Certificate + /// This class represents a X509 Certificate. + { + public: + typedef std::vector List; + + enum NID + /// Name identifier for extracting information from + /// a certificate subject's or issuer's distinguished name. + { + NID_COMMON_NAME = 13, + NID_COUNTRY = 14, + NID_LOCALITY_NAME = 15, + NID_STATE_OR_PROVINCE = 16, + NID_ORGANIZATION_NAME = 17, + NID_ORGANIZATION_UNIT_NAME = 18, + NID_PKCS9_EMAIL_ADDRESS = 48, + NID_SERIAL_NUMBER = 105 + }; + + explicit X509Certificate(std::istream & istr); + /// Creates the X509Certificate object by reading + /// a certificate in PEM format from a stream. + + explicit X509Certificate(const std::string & path); + /// Creates the X509Certificate object by reading + /// a certificate in PEM format from a file. + + explicit X509Certificate(X509 * pCert); + /// Creates the X509Certificate from an existing + /// OpenSSL certificate. Ownership is taken of + /// the certificate. + + X509Certificate(X509 * pCert, bool shared); + /// Creates the X509Certificate from an existing + /// OpenSSL certificate. Ownership is taken of + /// the certificate. If shared is true, the + /// certificate's reference count is incremented. + + X509Certificate(const X509Certificate & cert); + /// Creates the certificate by copying another one. + + X509Certificate & operator=(const X509Certificate & cert); + /// Assigns a certificate. + + void swap(X509Certificate & cert); + /// Exchanges the certificate with another one. + + ~X509Certificate(); + /// Destroys the X509Certificate. + + long version() const; + /// Returns the version of the certificate. + + const std::string & serialNumber() const; + /// Returns the certificate serial number as a + /// string in decimal encoding. + + const std::string & issuerName() const; + /// Returns the certificate issuer's distinguished name. + + std::string issuerName(NID nid) const; + /// Extracts the information specified by the given + /// NID (name identifier) from the certificate issuer's + /// distinguished name. + + const std::string & subjectName() const; + /// Returns the certificate subject's distinguished name. + + std::string subjectName(NID nid) const; + /// Extracts the information specified by the given + /// NID (name identifier) from the certificate subject's + /// distinguished name. + + std::string commonName() const; + /// Returns the common name stored in the certificate + /// subject's distinguished name. + + void extractNames(std::string & commonName, std::set & domainNames) const; + /// Extracts the common name and the alias domain names from the + /// certificate. + + Poco::DateTime validFrom() const; + /// Returns the date and time the certificate is valid from. + + Poco::DateTime expiresOn() const; + /// Returns the date and time the certificate expires. + + void save(std::ostream & stream) const; + /// Writes the certificate to the given stream. + /// The certificate is written in PEM format. + + void save(const std::string & path) const; + /// Writes the certificate to the file given by path. + /// The certificate is written in PEM format. + + bool issuedBy(const X509Certificate & issuerCertificate) const; + /// Checks whether the certificate has been issued by + /// the issuer given by issuerCertificate. This can be + /// used to validate a certificate chain. + /// + /// Verifies if the certificate has been signed with the + /// issuer's private key, using the public key from the issuer + /// certificate. + /// + /// Returns true if verification against the issuer certificate + /// was successful, false otherwise. + + bool equals(const X509Certificate & otherCertificate) const; + /// Checks whether the certificate is equal to + /// the other certificate, by comparing the hashes + /// of both certificates. + /// + /// Returns true if both certificates are identical, + /// otherwise false. + + const X509 * certificate() const; + /// Returns the underlying OpenSSL certificate. + + X509 * dup() const; + /// Duplicates and returns the underlying OpenSSL certificate. Note that + /// the caller assumes responsibility for the lifecycle of the created + /// certificate. + + std::string signatureAlgorithm() const; + /// Returns the certificate signature algorithm long name. + + void print(std::ostream & out) const; + /// Prints the certificate information to ostream. + + static List readPEM(const std::string & pemFileName); + /// Reads and returns a list of certificates from + /// the specified PEM file. + + static void writePEM(const std::string & pemFileName, const List & list); + /// Writes the list of certificates to the specified PEM file. + + protected: + void load(std::istream & stream); + /// Loads the certificate from the given stream. The + /// certificate must be in PEM format. + + void load(const std::string & path); + /// Loads the certificate from the given file. The + /// certificate must be in PEM format. + + void init(); + /// Extracts issuer and subject name from the certificate. + + private: + enum + { + NAME_BUFFER_SIZE = 256 + }; + + std::string _issuerName; + std::string _subjectName; + std::string _serialNumber; + X509 * _pCert; + OpenSSLInitializer _openSSLInitializer; + }; + + + // + // inlines + // + + + inline long X509Certificate::version() const + { + // This is defined by standards (X.509 et al) to be + // one less than the certificate version. + // So, eg. a version 3 certificate will return 2. + return X509_get_version(_pCert) + 1; + } + + + inline const std::string & X509Certificate::serialNumber() const + { + return _serialNumber; + } + + + inline const std::string & X509Certificate::issuerName() const + { + return _issuerName; + } + + + inline const std::string & X509Certificate::subjectName() const + { + return _subjectName; + } + + + inline const X509 * X509Certificate::certificate() const + { + return _pCert; + } + + + inline X509 * X509Certificate::dup() const + { + return X509_dup(_pCert); + } + + } - - -inline const std::string& X509Certificate::serialNumber() const -{ - return _serialNumber; -} - - -inline const std::string& X509Certificate::issuerName() const -{ - return _issuerName; -} - - -inline const std::string& X509Certificate::subjectName() const -{ - return _subjectName; -} - - -inline const X509* X509Certificate::certificate() const -{ - return _pCert; -} - - -inline X509* X509Certificate::dup() const -{ - return X509_dup(_pCert); -} - - -} } // namespace Poco::Crypto +} // namespace Poco::Crypto #endif // Crypto_X509Certificate_INCLUDED diff --git a/base/poco/Crypto/src/OpenSSLInitializer.cpp b/base/poco/Crypto/src/OpenSSLInitializer.cpp index a3bc1d01431..31798e8dd7e 100644 --- a/base/poco/Crypto/src/OpenSSLInitializer.cpp +++ b/base/poco/Crypto/src/OpenSSLInitializer.cpp @@ -22,36 +22,12 @@ #if OPENSSL_VERSION_NUMBER >= 0x0907000L #include #endif -#if defined(POCO_OS_FAMILY_WINDOWS) - #define POCO_STR_HELPER(x) #x - #define POCO_STR(x) POCO_STR_HELPER(x) - #if defined POCO_INTERNAL_OPENSSL_MSVC_VER - #define POCO_INTERNAL_OPENSSL_BUILD \ - " (POCO internal build, MSVC version " \ - POCO_STR(POCO_INTERNAL_OPENSSL_MSVC_VER) ")" - #else - #define POCO_INTERNAL_OPENSSL_BUILD "" - #endif - #pragma message (OPENSSL_VERSION_TEXT POCO_INTERNAL_OPENSSL_BUILD) -#endif using Poco::RandomInputStream; using Poco::Thread; -#if defined(_MSC_VER) && !defined(_DLL) && defined(POCO_INTERNAL_OPENSSL_MSVC_VER) - - #if (POCO_MSVS_VERSION >= 2015) - FILE _iob[] = { *stdin, *stdout, *stderr }; - extern "C" FILE * __cdecl __iob_func(void) { return _iob; } - #endif // (POCO_MSVS_VERSION >= 2015) - - #if (POCO_MSVS_VERSION < 2012) - extern "C" __declspec(noreturn) void __cdecl __report_rangecheckfailure(void) { ::ExitProcess(1); } - #endif // (POCO_MSVS_VERSION < 2012) - -#endif // _MSC_VER && _MT && !POCO_EXTERNAL_OPENSSL && (POCO_MSVS_VERSION < 2013) namespace Poco { @@ -100,7 +76,6 @@ void OpenSSLInitializer::initialize() int nMutexes = CRYPTO_num_locks(); _mutexes = new Poco::FastMutex[nMutexes]; CRYPTO_set_locking_callback(&OpenSSLInitializer::lock); -#ifndef POCO_OS_FAMILY_WINDOWS // Not needed on Windows (see SF #110: random unhandled exceptions when linking with ssl). // https://sourceforge.net/p/poco/bugs/110/ // @@ -109,7 +84,6 @@ void OpenSSLInitializer::initialize() // then a default implementation is used - on Windows and BeOS this uses the system's // default thread identifying APIs" CRYPTO_set_id_callback(&OpenSSLInitializer::id); -#endif CRYPTO_set_dynlock_create_callback(&OpenSSLInitializer::dynlockCreate); CRYPTO_set_dynlock_lock_callback(&OpenSSLInitializer::dynlock); CRYPTO_set_dynlock_destroy_callback(&OpenSSLInitializer::dynlockDestroy); @@ -124,9 +98,7 @@ void OpenSSLInitializer::uninitialize() EVP_cleanup(); ERR_free_strings(); CRYPTO_set_locking_callback(0); -#ifndef POCO_OS_FAMILY_WINDOWS CRYPTO_set_id_callback(0); -#endif delete [] _mutexes; CONF_modules_free(); diff --git a/base/poco/Crypto/src/RSAKeyImpl.cpp b/base/poco/Crypto/src/RSAKeyImpl.cpp index 86089b828b1..eb6e758343a 100644 --- a/base/poco/Crypto/src/RSAKeyImpl.cpp +++ b/base/poco/Crypto/src/RSAKeyImpl.cpp @@ -102,7 +102,7 @@ RSAKeyImpl::RSAKeyImpl(const std::string& publicKeyFile, { BIO* bio = BIO_new(BIO_s_file()); if (!bio) throw Poco::IOException("Cannot create BIO for reading public key", publicKeyFile); - int rc = BIO_read_filename(bio, publicKeyFile.c_str()); + int rc = BIO_read_filename(bio, const_cast(publicKeyFile.c_str())); if (rc) { RSA* pubKey = PEM_read_bio_RSAPublicKey(bio, &_pRSA, 0, 0); @@ -132,7 +132,7 @@ RSAKeyImpl::RSAKeyImpl(const std::string& publicKeyFile, { BIO* bio = BIO_new(BIO_s_file()); if (!bio) throw Poco::IOException("Cannot create BIO for reading private key", privateKeyFile); - int rc = BIO_read_filename(bio, privateKeyFile.c_str()); + int rc = BIO_read_filename(bio, const_cast(privateKeyFile.c_str())); if (rc) { RSA* privKey = 0; diff --git a/base/poco/Crypto/src/X509Certificate.cpp b/base/poco/Crypto/src/X509Certificate.cpp index 542066665df..16458d0477b 100644 --- a/base/poco/Crypto/src/X509Certificate.cpp +++ b/base/poco/Crypto/src/X509Certificate.cpp @@ -20,10 +20,6 @@ #include "Poco/Format.h" #include #include -#ifdef _WIN32 -// fix for WIN32 header conflict -#undef X509_NAME -#endif #include #include #include @@ -133,7 +129,7 @@ void X509Certificate::load(const std::string& path) BIO *pBIO = BIO_new(BIO_s_file()); if (!pBIO) throw Poco::IOException("Cannot create BIO for reading certificate file", path); - if (!BIO_read_filename(pBIO, path.c_str())) + if (!BIO_read_filename(pBIO, const_cast(path.c_str()))) { BIO_free(pBIO); throw Poco::OpenFileException("Cannot open certificate file for reading", path); diff --git a/base/poco/Data/ODBC/include/Poco/Data/ODBC/Binder.h b/base/poco/Data/ODBC/include/Poco/Data/ODBC/Binder.h index 5203f65679f..3169563879c 100644 --- a/base/poco/Data/ODBC/include/Poco/Data/ODBC/Binder.h +++ b/base/poco/Data/ODBC/include/Poco/Data/ODBC/Binder.h @@ -18,1499 +18,1517 @@ #define Data_ODBC_Binder_INCLUDED -#include "Poco/Data/ODBC/ODBC.h" -#include "Poco/Data/AbstractBinder.h" -#include "Poco/Data/LOB.h" -#include "Poco/Data/ODBC/Handle.h" -#include "Poco/Data/ODBC/Parameter.h" -#include "Poco/Data/ODBC/ODBCMetaColumn.h" -#include "Poco/Data/ODBC/Utility.h" -#include "Poco/Data/ODBC/TypeInfo.h" -#include "Poco/Exception.h" -#include #include #include #include -#ifdef POCO_OS_FAMILY_WINDOWS -#include -#endif +#include +#include "Poco/Data/AbstractBinder.h" +#include "Poco/Data/LOB.h" +#include "Poco/Data/ODBC/Handle.h" +#include "Poco/Data/ODBC/ODBC.h" +#include "Poco/Data/ODBC/ODBCMetaColumn.h" +#include "Poco/Data/ODBC/Parameter.h" +#include "Poco/Data/ODBC/TypeInfo.h" +#include "Poco/Data/ODBC/Utility.h" +#include "Poco/Exception.h" #include -namespace Poco { +namespace Poco +{ class DateTime; -namespace Data { - - -class Date; -class Time; - - -namespace ODBC { - - -class ODBC_API Binder: public Poco::Data::AbstractBinder - /// Binds placeholders in the sql query to the provided values. Performs data types mapping. +namespace Data { -public: - typedef AbstractBinder::Direction Direction; - typedef std::map ParamMap; - static const size_t DEFAULT_PARAM_SIZE = 1024; - enum ParameterBinding - { - PB_IMMEDIATE, - PB_AT_EXEC - }; + class Date; + class Time; - Binder(const StatementHandle& rStmt, - std::size_t maxFieldSize, - ParameterBinding dataBinding = PB_IMMEDIATE, - TypeInfo* pDataTypes = 0); - /// Creates the Binder. - ~Binder(); - /// Destroys the Binder. + namespace ODBC + { - void bind(std::size_t pos, const Poco::Int8& val, Direction dir); - /// Binds an Int8. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds an Int8 vector. + class ODBC_API Binder : public Poco::Data::AbstractBinder + /// Binds placeholders in the sql query to the provided values. Performs data types mapping. + { + public: + typedef AbstractBinder::Direction Direction; + typedef std::map ParamMap; - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds an Int8 deque. + static const size_t DEFAULT_PARAM_SIZE = 1024; - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds an Int8 list. + enum ParameterBinding + { + PB_IMMEDIATE, + PB_AT_EXEC + }; - void bind(std::size_t pos, const Poco::UInt8& val, Direction dir); - /// Binds an UInt8. + Binder( + const StatementHandle & rStmt, + std::size_t maxFieldSize, + ParameterBinding dataBinding = PB_IMMEDIATE, + TypeInfo * pDataTypes = 0); + /// Creates the Binder. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds an UInt8 vector. + ~Binder(); + /// Destroys the Binder. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds an UInt8 deque. + void bind(std::size_t pos, const Poco::Int8 & val, Direction dir); + /// Binds an Int8. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds an UInt8 list. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds an Int8 vector. - void bind(std::size_t pos, const Poco::Int16& val, Direction dir); - /// Binds an Int16. - - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds an Int16 vector. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds an Int8 deque. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds an Int16 deque. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds an Int8 list. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds an Int16 list. + void bind(std::size_t pos, const Poco::UInt8 & val, Direction dir); + /// Binds an UInt8. - void bind(std::size_t pos, const Poco::UInt16& val, Direction dir); - /// Binds an UInt16. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds an UInt8 vector. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds an UInt16 vector. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds an UInt8 deque. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds an UInt16 deque. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds an UInt8 list. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds an UInt16 list. + void bind(std::size_t pos, const Poco::Int16 & val, Direction dir); + /// Binds an Int16. - void bind(std::size_t pos, const Poco::Int32& val, Direction dir); - /// Binds an Int32. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds an Int16 vector. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds an Int32 vector. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds an Int16 deque. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds an Int32 deque. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds an Int16 list. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds an Int32 list. + void bind(std::size_t pos, const Poco::UInt16 & val, Direction dir); + /// Binds an UInt16. - void bind(std::size_t pos, const Poco::UInt32& val, Direction dir); - /// Binds an UInt32. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds an UInt16 vector. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds an UInt32 vector. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds an UInt16 deque. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds an UInt32 deque. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds an UInt16 list. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds an UInt32 list. + void bind(std::size_t pos, const Poco::Int32 & val, Direction dir); + /// Binds an Int32. - void bind(std::size_t pos, const Poco::Int64& val, Direction dir); - /// Binds an Int64. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds an Int32 vector. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds an Int64 vector. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds an Int32 deque. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds an Int64 deque. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds an Int32 list. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds an Int64 list. + void bind(std::size_t pos, const Poco::UInt32 & val, Direction dir); + /// Binds an UInt32. - void bind(std::size_t pos, const Poco::UInt64& val, Direction dir); - /// Binds an UInt64. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds an UInt32 vector. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds an UInt64 vector. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds an UInt32 deque. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds an UInt64 deque. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds an UInt32 list. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds an UInt64 list. + void bind(std::size_t pos, const Poco::Int64 & val, Direction dir); + /// Binds an Int64. + + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds an Int64 vector. + + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds an Int64 deque. + + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds an Int64 list. + + void bind(std::size_t pos, const Poco::UInt64 & val, Direction dir); + /// Binds an UInt64. + + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds an UInt64 vector. + + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds an UInt64 deque. + + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds an UInt64 list. #ifndef POCO_LONG_IS_64_BIT - void bind(std::size_t pos, const long& val, Direction dir); - /// Binds a long. + void bind(std::size_t pos, const long & val, Direction dir); + /// Binds a long. - void bind(std::size_t pos, const unsigned long& val, Direction dir); - /// Binds an unsigned long. + void bind(std::size_t pos, const unsigned long & val, Direction dir); + /// Binds an unsigned long. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a long vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a long vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a long deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a long deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a long list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a long list. #endif - void bind(std::size_t pos, const bool& val, Direction dir); - /// Binds a boolean. + void bind(std::size_t pos, const bool & val, Direction dir); + /// Binds a boolean. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a boolean vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a boolean vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a boolean deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a boolean deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a boolean list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a boolean list. - void bind(std::size_t pos, const float& val, Direction dir); - /// Binds a float. + void bind(std::size_t pos, const float & val, Direction dir); + /// Binds a float. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a float vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a float vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a float deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a float deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a float list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a float list. - void bind(std::size_t pos, const double& val, Direction dir); - /// Binds a double. + void bind(std::size_t pos, const double & val, Direction dir); + /// Binds a double. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a double vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a double vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a double deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a double deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a double list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a double list. - void bind(std::size_t pos, const char& val, Direction dir); - /// Binds a single character. + void bind(std::size_t pos, const char & val, Direction dir); + /// Binds a single character. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a character vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a character vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a character deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a character deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a character list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a character list. - void bind(std::size_t pos, const std::string& val, Direction dir); - /// Binds a string. + void bind(std::size_t pos, const std::string & val, Direction dir); + /// Binds a string. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a string vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a string vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a string deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a string deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a string list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a string list. - void bind(std::size_t pos, const UTF16String& val, Direction dir); - /// Binds a string. + void bind(std::size_t pos, const UTF16String & val, Direction dir); + /// Binds a string. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a string vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a string vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a string deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a string deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a string list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a string list. - void bind(std::size_t pos, const BLOB& val, Direction dir); - /// Binds a BLOB. In-bound only. + void bind(std::size_t pos, const BLOB & val, Direction dir); + /// Binds a BLOB. In-bound only. - void bind(std::size_t pos, const CLOB& val, Direction dir); - /// Binds a CLOB. In-bound only. + void bind(std::size_t pos, const CLOB & val, Direction dir); + /// Binds a CLOB. In-bound only. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a BLOB vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a BLOB vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a BLOB deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a BLOB deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a BLOB list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a BLOB list. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a CLOB vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a CLOB vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a CLOB deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a CLOB deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a CLOB list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a CLOB list. - void bind(std::size_t pos, const Date& val, Direction dir); - /// Binds a Date. + void bind(std::size_t pos, const Date & val, Direction dir); + /// Binds a Date. - void bind(std::size_t pos, const std::vector& val, Direction dir); - /// Binds a Date vector. + void bind(std::size_t pos, const std::vector & val, Direction dir); + /// Binds a Date vector. - void bind(std::size_t pos, const std::deque& val, Direction dir); - /// Binds a Date deque. + void bind(std::size_t pos, const std::deque & val, Direction dir); + /// Binds a Date deque. - void bind(std::size_t pos, const std::list& val, Direction dir); - /// Binds a Date list. + void bind(std::size_t pos, const std::list & val, Direction dir); + /// Binds a Date list. - void bind(std::size_t pos, const Time& val, Direction dir); - /// Binds a Time. + void bind(std::size_t pos, const Time & val, Direction dir); + /// Binds a Time. - void bind(std::size_t pos, const std::vector