diff --git a/CHANGELOG.md b/CHANGELOG.md index e65cc30aecd7e..5df33dc6e3ace 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Add events correlation engine plugin ([#6854](https://github.com/opensearch-project/OpenSearch/issues/6854)) - Introduce new dynamic cluster setting to control slice computation for concurrent segment search ([#9107](https://github.com/opensearch-project/OpenSearch/pull/9107)) - Implement on behalf of token passing for extensions ([#8679](https://github.com/opensearch-project/OpenSearch/pull/8679)) +- Added encryption-sdk lib to provide encryption and decryption capabilities ([#8466](https://github.com/opensearch-project/OpenSearch/pull/8466)) ### Dependencies - Bump `log4j-core` from 2.18.0 to 2.19.0 @@ -40,6 +41,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Bump `org.bouncycastle:bcprov-jdk15on` to `org.bouncycastle:bcprov-jdk15to18` version 1.75 ([#8247](https://github.com/opensearch-project/OpenSearch/pull/8247)) - Bump `org.bouncycastle:bcmail-jdk15on` to `org.bouncycastle:bcmail-jdk15to18` version 1.75 ([#8247](https://github.com/opensearch-project/OpenSearch/pull/8247)) - Bump `org.bouncycastle:bcpkix-jdk15on` to `org.bouncycastle:bcpkix-jdk15to18` version 1.75 ([#8247](https://github.com/opensearch-project/OpenSearch/pull/8247)) +- Add Encryption SDK dependencies ([#8466](https://github.com/opensearch-project/OpenSearch/pull/8466)) ### Changed - [CCR] Add getHistoryOperationsFromTranslog method to fetch the history snapshot from translogs ([#3948](https://github.com/opensearch-project/OpenSearch/pull/3948)) diff --git a/buildSrc/version.properties b/buildSrc/version.properties index 0d84ddebb905c..500727e909494 100644 --- a/buildSrc/version.properties +++ b/buildSrc/version.properties @@ -39,7 +39,7 @@ httpcore = 4.4.16 httpasyncclient = 4.1.5 commonslogging = 1.2 commonscodec = 1.15 - +commonslang = 3.13.0 # plugin dependencies aws = 2.20.55 reactivestreams = 1.0.4 diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/CryptoHandler.java b/libs/common/src/main/java/org/opensearch/common/crypto/CryptoHandler.java new file mode 100644 index 0000000000000..bdcaa295f1cc4 --- /dev/null +++ b/libs/common/src/main/java/org/opensearch/common/crypto/CryptoHandler.java @@ -0,0 +1,114 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.common.crypto; + +import org.opensearch.common.io.InputStreamContainer; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Crypto provider abstractions for encryption and decryption of data. Allows registering multiple providers + * for defining different ways of encrypting or decrypting data. + * + * T - Encryption Metadata / CryptoContext + * U - Parsed Encryption Metadata / CryptoContext + */ +public interface CryptoHandler { + + /** + * To initialise or create a new crypto metadata to be used in encryption. This is needed to set the context before + * beginning encryption. + * + * @return crypto metadata instance + */ + T initEncryptionMetadata(); + + /** + * To load crypto metadata to be used in encryption from content header. + * Note that underlying information in the loaded metadata object is same as present in the object created during + * encryption but object type may differ. + * + * @return crypto metadata instance used in decryption. + */ + U loadEncryptionMetadata(EncryptedHeaderContentSupplier encryptedHeaderContentSupplier) throws IOException; + + /** + * Few encryption algorithms have certain conditions on the unit of content to be encrypted. This requires the + * content size to be re adjusted in order to fulfil these conditions for partial writes. If write requests for + * encryption of a part of content do not fulfil these conditions then encryption fails or can result in corrupted + * content depending on the algorithm used. This method exposes a means to re-adjust sizes of such writes. + * + * @param cryptoContext crypto metadata instance + * @param contentSize Size of the raw content + * @return Adjusted size of the content. + */ + long adjustContentSizeForPartialEncryption(T cryptoContext, long contentSize); + + /** + * Estimate length of the encrypted content. It should only be used to determine length of entire content after + * encryption. + * + * @param cryptoContext crypto metadata instance consisting of encryption metadata used in encryption. + * @param contentLength Size of the raw content + * @return Calculated size of the encrypted content. + */ + long estimateEncryptedLengthOfEntireContent(T cryptoContext, long contentLength); + + /** + * For given encrypted content length, estimate the length of the decrypted content. + * @param cryptoContext crypto metadata instance consisting of encryption metadata used in encryption. + * @param contentLength Size of the encrypted content + * @return Calculated size of the decrypted content. + */ + long estimateDecryptedLength(U cryptoContext, long contentLength); + + /** + * Wraps a raw InputStream with encrypting stream + * + * @param encryptionMetadata created earlier to set the crypto metadata. + * @param stream Raw InputStream to encrypt + * @return encrypting stream wrapped around raw InputStream. + */ + InputStreamContainer createEncryptingStream(T encryptionMetadata, InputStreamContainer stream); + + /** + * Provides encrypted stream for a raw stream emitted for a part of content. + * + * @param cryptoContext crypto metadata instance. + * @param stream raw stream for which encrypted stream has to be created. + * @param totalStreams Number of streams being used for the entire content. + * @param streamIdx Index of the current stream. + * @return Encrypted stream for the provided raw stream. + */ + InputStreamContainer createEncryptingStreamOfPart(T cryptoContext, InputStreamContainer stream, int totalStreams, int streamIdx); + + /** + * This method accepts an encrypted stream and provides a decrypting wrapper. + * @param encryptingStream to be decrypted. + * @return Decrypting wrapper stream + */ + InputStream createDecryptingStream(InputStream encryptingStream); + + /** + * This method creates a {@link DecryptedRangedStreamProvider} which provides a wrapped stream to decrypt the + * underlying stream. This also provides adjusted range against the actual range which should be used for fetching + * and supplying the encrypted content for decryption. Extra content outside the range is trimmed down and returned + * by the decrypted stream. + * For partial reads of encrypted content, few algorithms require the range of content to be adjusted for + * successful decryption. Adjusted range may or may not be same as the provided range. If range is adjusted then + * starting offset of resultant range can be lesser than the starting offset of provided range and end + * offset can be greater than the ending offset of the provided range. + * + * @param cryptoContext crypto metadata instance. + * @param startPosOfRawContent starting position in the raw/decrypted content + * @param endPosOfRawContent ending position in the raw/decrypted content + */ + DecryptedRangedStreamProvider createDecryptingStreamOfRange(U cryptoContext, long startPosOfRawContent, long endPosOfRawContent); +} diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/DataKeyPair.java b/libs/common/src/main/java/org/opensearch/common/crypto/DataKeyPair.java new file mode 100644 index 0000000000000..3d487f9028d71 --- /dev/null +++ b/libs/common/src/main/java/org/opensearch/common/crypto/DataKeyPair.java @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.common.crypto; + +/** + * Key pair generated by {@link MasterKeyProvider} + */ +public class DataKeyPair { + private final byte[] rawKey; + private final byte[] encryptedKey; + + /** + * Constructor to initialize key-pair values + * @param rawKey Unencrypted data key used for encryption and decryption + * @param encryptedKey Encrypted version of rawKey + */ + public DataKeyPair(byte[] rawKey, byte[] encryptedKey) { + this.rawKey = rawKey; + this.encryptedKey = encryptedKey; + } + + /** + * Returns raw key + * @return raw/decrypted key + */ + public byte[] getRawKey() { + return rawKey; + } + + /** + * Returns encrypted key + * @return encrypted key + */ + public byte[] getEncryptedKey() { + return encryptedKey; + } +} diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/DecryptedRangedStreamProvider.java b/libs/common/src/main/java/org/opensearch/common/crypto/DecryptedRangedStreamProvider.java new file mode 100644 index 0000000000000..06b18027a0726 --- /dev/null +++ b/libs/common/src/main/java/org/opensearch/common/crypto/DecryptedRangedStreamProvider.java @@ -0,0 +1,49 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.common.crypto; + +import java.io.InputStream; +import java.util.function.UnaryOperator; + +/** + * Contains adjusted range of partial encrypted content which needs to be used for decryption. + */ +public class DecryptedRangedStreamProvider { + + private final long[] adjustedRange; + private final UnaryOperator decryptedStreamProvider; + + /** + * To construct adjusted encrypted range. + * @param adjustedRange range of partial encrypted content which needs to be used for decryption. + * @param decryptedStreamProvider stream provider for decryption and range re-adjustment. + */ + public DecryptedRangedStreamProvider(long[] adjustedRange, UnaryOperator decryptedStreamProvider) { + this.adjustedRange = adjustedRange; + this.decryptedStreamProvider = decryptedStreamProvider; + } + + /** + * Adjusted range of partial encrypted content which needs to be used for decryption. + * @return adjusted range + */ + public long[] getAdjustedRange() { + return adjustedRange; + } + + /** + * A utility stream provider which supplies the stream responsible for decrypting the content and reading the + * desired range of decrypted content by skipping extra content which got decrypted as a result of range adjustment. + * @return stream provider for decryption and supplying the desired range of content. + */ + public UnaryOperator getDecryptedStreamProvider() { + return decryptedStreamProvider; + } + +} diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/EncryptedHeaderContentSupplier.java b/libs/common/src/main/java/org/opensearch/common/crypto/EncryptedHeaderContentSupplier.java new file mode 100644 index 0000000000000..49a037f05f185 --- /dev/null +++ b/libs/common/src/main/java/org/opensearch/common/crypto/EncryptedHeaderContentSupplier.java @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.common.crypto; + +import java.io.IOException; + +/** + * This is used in partial decryption. Header information is required for decryption of actual encrypted content. + * Implementation of this supplier only requires first few bytes of encrypted content to be supplied. + */ +public interface EncryptedHeaderContentSupplier { + + /** + * @param start Start position of the encrypted content (Generally supplied as 0 during usage) + * @param end End position of the header. + * @return Encrypted header content (May contain additional content which is later discarded) + * @throws IOException In case content fetch fails. + */ + byte[] supply(long start, long end) throws IOException; +} diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/MasterKeyProvider.java b/libs/common/src/main/java/org/opensearch/common/crypto/MasterKeyProvider.java new file mode 100644 index 0000000000000..b5feeb6d37ec6 --- /dev/null +++ b/libs/common/src/main/java/org/opensearch/common/crypto/MasterKeyProvider.java @@ -0,0 +1,41 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.common.crypto; + +import java.io.Closeable; +import java.util.Map; + +/** + * Master key provider responsible for management of master keys. + */ +public interface MasterKeyProvider extends Closeable { + + /** + * Returns data key pair + * @return data key pair generated by master key. + */ + DataKeyPair generateDataPair(); + + /** + * Returns decrpted key against the encrypted key. + * @param encryptedKey Key to decrypt + * @return Decrypted version of key. + */ + byte[] decryptKey(byte[] encryptedKey); + + /** + * Returns key id. + * @return key id + */ + String getKeyId(); + + /** + * @return encryption context associated with this master key. + */ + Map getEncryptionContext(); +} diff --git a/libs/common/src/main/java/org/opensearch/common/crypto/package-info.java b/libs/common/src/main/java/org/opensearch/common/crypto/package-info.java new file mode 100644 index 0000000000000..c744689ebf532 --- /dev/null +++ b/libs/common/src/main/java/org/opensearch/common/crypto/package-info.java @@ -0,0 +1,10 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/** Common crypto utilities used across opensearch. */ +package org.opensearch.common.crypto; diff --git a/libs/encryption-sdk/build.gradle b/libs/encryption-sdk/build.gradle new file mode 100644 index 0000000000000..d229d4edf0a83 --- /dev/null +++ b/libs/encryption-sdk/build.gradle @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +apply plugin: 'opensearch.build' +apply plugin: 'opensearch.publish' + +forbiddenApis.ignoreFailures = false + +thirdPartyAudit.enabled = false +forbiddenApisTest.ignoreFailures = true +testingConventions.enabled = false + +dependencies { + // Common crypto classes + api project(':libs:opensearch-common') + + // Logger + implementation "org.slf4j:slf4j-api:${versions.slf4j}" + implementation 'commons-logging:commons-logging:1.2' + + // Encryption + implementation "com.amazonaws:aws-encryption-sdk-java:2.4.0" + implementation "org.bouncycastle:bcprov-jdk15to18:${versions.bouncycastle}" + implementation "org.apache.commons:commons-lang3:${versions.commonslang}" + + //Tests + testImplementation "junit:junit:${versions.junit}" + testImplementation "org.hamcrest:hamcrest:${versions.hamcrest}" + testImplementation(project(":test:framework")) { + exclude group: 'org.opensearch', module: 'opensearch-encryption-sdk' + } + + compileOnly 'com.google.code.findbugs:annotations:3.0.1' +} + +tasks.named('forbiddenApisMain').configure { + // Only enable limited check because AD code has too many violations. + replaceSignatureFiles 'jdk-signatures' + signaturesFiles += files('src/forbidden/crypto-signatures.txt') +} + +// Encryption SDK files have missing java docs so disabling for the lib. +tasks.named('missingJavadoc').configure { + enabled = false +} + +forbiddenApisTest.setSignaturesFiles(files('src/forbidden/crypto-test-signatures.txt')) diff --git a/libs/encryption-sdk/licenses/aws-encryption-sdk-java-2.4.0.jar.sha1 b/libs/encryption-sdk/licenses/aws-encryption-sdk-java-2.4.0.jar.sha1 new file mode 100644 index 0000000000000..504b4a423a975 --- /dev/null +++ b/libs/encryption-sdk/licenses/aws-encryption-sdk-java-2.4.0.jar.sha1 @@ -0,0 +1 @@ +98943eda1dc05bb01f4f5405e115b08dc541afbf \ No newline at end of file diff --git a/libs/encryption-sdk/licenses/aws-encryption-sdk-java-LICENSE.txt b/libs/encryption-sdk/licenses/aws-encryption-sdk-java-LICENSE.txt new file mode 100644 index 0000000000000..8dada3edaf50d --- /dev/null +++ b/libs/encryption-sdk/licenses/aws-encryption-sdk-java-LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/libs/encryption-sdk/licenses/aws-encryption-sdk-java-NOTICE.txt b/libs/encryption-sdk/licenses/aws-encryption-sdk-java-NOTICE.txt new file mode 100644 index 0000000000000..e32695955374a --- /dev/null +++ b/libs/encryption-sdk/licenses/aws-encryption-sdk-java-NOTICE.txt @@ -0,0 +1,11 @@ +AWS Encryption SDK +Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +THIRD PARTY COMPONENTS +********************** +This software includes third party software subject to the following copyrights: + +-Cryptographic functions from Bouncy Castle Crypto APIs for Java - Copyright +2000-2013 The Legion of the Bouncy Castle + +The licenses for these third party components are included in LICENSE.txt diff --git a/libs/encryption-sdk/licenses/bcprov-jdk15to18-1.75.jar.sha1 b/libs/encryption-sdk/licenses/bcprov-jdk15to18-1.75.jar.sha1 new file mode 100644 index 0000000000000..9911bb75f9209 --- /dev/null +++ b/libs/encryption-sdk/licenses/bcprov-jdk15to18-1.75.jar.sha1 @@ -0,0 +1 @@ +df22e1b6a9f6b218913f5b68dd16641344397fe0 \ No newline at end of file diff --git a/libs/encryption-sdk/licenses/bcprov-jdk15to18-LICENSE.txt b/libs/encryption-sdk/licenses/bcprov-jdk15to18-LICENSE.txt new file mode 100644 index 0000000000000..9f27bafe96885 --- /dev/null +++ b/libs/encryption-sdk/licenses/bcprov-jdk15to18-LICENSE.txt @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2000 - 2013 The Legion of the Bouncy Castle Inc. + (http://www.bouncycastle.org) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/libs/encryption-sdk/licenses/bcprov-jdk15to18-NOTICE.txt b/libs/encryption-sdk/licenses/bcprov-jdk15to18-NOTICE.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/libs/encryption-sdk/licenses/commons-lang3-3.13.0.jar.sha1 b/libs/encryption-sdk/licenses/commons-lang3-3.13.0.jar.sha1 new file mode 100644 index 0000000000000..d0c2f2486ee1f --- /dev/null +++ b/libs/encryption-sdk/licenses/commons-lang3-3.13.0.jar.sha1 @@ -0,0 +1 @@ +b7263237aa89c1f99b327197c41d0669707a462e \ No newline at end of file diff --git a/libs/encryption-sdk/licenses/commons-lang3-LICENSE.txt b/libs/encryption-sdk/licenses/commons-lang3-LICENSE.txt new file mode 100644 index 0000000000000..d645695673349 --- /dev/null +++ b/libs/encryption-sdk/licenses/commons-lang3-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/libs/encryption-sdk/licenses/commons-lang3-NOTICE.txt b/libs/encryption-sdk/licenses/commons-lang3-NOTICE.txt new file mode 100644 index 0000000000000..13a3140897472 --- /dev/null +++ b/libs/encryption-sdk/licenses/commons-lang3-NOTICE.txt @@ -0,0 +1,5 @@ +Apache Commons Lang +Copyright 2001-2019 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/libs/encryption-sdk/licenses/commons-logging-1.2.jar.sha1 b/libs/encryption-sdk/licenses/commons-logging-1.2.jar.sha1 new file mode 100644 index 0000000000000..f40f0242448e8 --- /dev/null +++ b/libs/encryption-sdk/licenses/commons-logging-1.2.jar.sha1 @@ -0,0 +1 @@ +4bfc12adfe4842bf07b657f0369c4cb522955686 \ No newline at end of file diff --git a/libs/encryption-sdk/licenses/commons-logging-LICENSE.txt b/libs/encryption-sdk/licenses/commons-logging-LICENSE.txt new file mode 100644 index 0000000000000..d645695673349 --- /dev/null +++ b/libs/encryption-sdk/licenses/commons-logging-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/libs/encryption-sdk/licenses/commons-logging-NOTICE.txt b/libs/encryption-sdk/licenses/commons-logging-NOTICE.txt new file mode 100644 index 0000000000000..1a45218353e87 --- /dev/null +++ b/libs/encryption-sdk/licenses/commons-logging-NOTICE.txt @@ -0,0 +1,5 @@ +Apache Commons Logging +Copyright 2003-2016 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/libs/encryption-sdk/licenses/slf4j-api-1.7.36.jar.sha1 b/libs/encryption-sdk/licenses/slf4j-api-1.7.36.jar.sha1 new file mode 100644 index 0000000000000..77b9917528382 --- /dev/null +++ b/libs/encryption-sdk/licenses/slf4j-api-1.7.36.jar.sha1 @@ -0,0 +1 @@ +6c62681a2f655b49963a5983b8b0950a6120ae14 \ No newline at end of file diff --git a/libs/encryption-sdk/licenses/slf4j-api-LICENSE.txt b/libs/encryption-sdk/licenses/slf4j-api-LICENSE.txt new file mode 100644 index 0000000000000..8fda22f4d72f6 --- /dev/null +++ b/libs/encryption-sdk/licenses/slf4j-api-LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) 2004-2014 QOS.ch +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/libs/encryption-sdk/licenses/slf4j-api-NOTICE.txt b/libs/encryption-sdk/licenses/slf4j-api-NOTICE.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/libs/encryption-sdk/src/forbidden/crypto-signatures.txt b/libs/encryption-sdk/src/forbidden/crypto-signatures.txt new file mode 100644 index 0000000000000..3699186679924 --- /dev/null +++ b/libs/encryption-sdk/src/forbidden/crypto-signatures.txt @@ -0,0 +1,13 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +@defaultMessage use format with Locale +java.lang.String#format(java.lang.String,java.lang.Object[]) \ No newline at end of file diff --git a/libs/encryption-sdk/src/forbidden/crypto-test-signatures.txt b/libs/encryption-sdk/src/forbidden/crypto-test-signatures.txt new file mode 100644 index 0000000000000..3699186679924 --- /dev/null +++ b/libs/encryption-sdk/src/forbidden/crypto-test-signatures.txt @@ -0,0 +1,13 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +@defaultMessage use format with Locale +java.lang.String#format(java.lang.String,java.lang.Object[]) \ No newline at end of file diff --git a/libs/encryption-sdk/src/main/java/org/opensearch/encryption/CryptoManager.java b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/CryptoManager.java new file mode 100644 index 0000000000000..8e1fc8570d552 --- /dev/null +++ b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/CryptoManager.java @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.encryption; + +import org.opensearch.common.crypto.CryptoHandler; +import org.opensearch.common.util.concurrent.RefCounted; + +/** + * Crypto plugin interface used for encryption and decryption. + */ +public interface CryptoManager extends RefCounted { + + /** + * @return key provider type + */ + String type(); + + /** + * @return key provider name + */ + String name(); + + /** + * @return Crypto provider for encrypting or decrypting raw content. + */ + CryptoHandler getCryptoProvider(); +} diff --git a/libs/encryption-sdk/src/main/java/org/opensearch/encryption/CryptoManagerFactory.java b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/CryptoManagerFactory.java new file mode 100644 index 0000000000000..e1dc9291ed1a6 --- /dev/null +++ b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/CryptoManagerFactory.java @@ -0,0 +1,127 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.encryption; + +import org.opensearch.common.crypto.CryptoHandler; +import org.opensearch.common.crypto.MasterKeyProvider; +import org.opensearch.common.unit.TimeValue; +import org.opensearch.common.util.concurrent.AbstractRefCounted; +import org.opensearch.encryption.keyprovider.CryptoMasterKey; + +import java.security.SecureRandom; +import java.util.concurrent.TimeUnit; + +import com.amazonaws.encryptionsdk.CryptoAlgorithm; +import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManager; +import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCache; + +public class CryptoManagerFactory { + + private final int dataKeyCacheSize; + private final String algorithm; + + // - Cache TTL and Jitter is used to decide the Crypto Cache TTL. + // - Random number between: (TTL Jitter, TTL - Jitter) + private final long dataKeyCacheTTL; + private static final long dataKeyCacheJitter = TimeUnit.MINUTES.toMillis(30); // - 30 minutes + + public CryptoManagerFactory(String algorithm, TimeValue keyRefreshInterval, int keyCacheSize) { + this.dataKeyCacheSize = keyCacheSize; + validateAndGetAlgorithmId(algorithm); + this.algorithm = algorithm; + dataKeyCacheTTL = keyRefreshInterval.getMillis(); + } + + private String validateAndGetAlgorithmId(String algorithm) { + // Supporting only 256 bit algorithm + switch (algorithm) { + case "ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY": + return CryptoAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY.getDataKeyAlgo(); + case "ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384": + return CryptoAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384.getDataKeyAlgo(); + default: + throw new IllegalArgumentException("Unsupported algorithm: " + algorithm); + } + } + + public CryptoManager getOrCreateCryptoManager( + MasterKeyProvider keyProvider, + String keyProviderName, + String keyProviderType, + Runnable onClose + ) { + CachingCryptoMaterialsManager materialsManager = createMaterialsManager( + keyProvider, + keyProviderName, + validateAndGetAlgorithmId(algorithm) + ); + CryptoHandler cryptoHandler = createCryptoProvider(algorithm, materialsManager, keyProvider); + return createCryptoManager(cryptoHandler, keyProviderType, keyProviderName, onClose); + } + + // package private for tests + CryptoHandler createCryptoProvider( + String algorithm, + CachingCryptoMaterialsManager materialsManager, + MasterKeyProvider masterKeyProvider + ) { + return new NoOpCryptoHandler(); + } + + // Package private for tests + CachingCryptoMaterialsManager createMaterialsManager(MasterKeyProvider masterKeyProvider, String keyProviderName, String algorithm) { + SecureRandom r = new SecureRandom(); + long low = dataKeyCacheTTL - dataKeyCacheJitter; + long high = dataKeyCacheTTL + dataKeyCacheJitter; + long masterKeyCacheTTL = r.nextInt((int) (high - low)) + low; + + CryptoMasterKey cryptoMasterKey = new CryptoMasterKey(masterKeyProvider, keyProviderName, algorithm); + return CachingCryptoMaterialsManager.newBuilder() + .withMasterKeyProvider(cryptoMasterKey) + .withCache(new LocalCryptoMaterialsCache(dataKeyCacheSize)) + .withMaxAge(masterKeyCacheTTL, TimeUnit.MILLISECONDS) + .build(); + } + + // package private for tests + CryptoManager createCryptoManager( + CryptoHandler cryptoHandler, + String keyProviderType, + String keyProviderName, + Runnable onClose + ) { + return new CryptoManagerImpl(keyProviderName, keyProviderType) { + @Override + protected void closeInternal() { + onClose.run(); + } + + @Override + public String type() { + return keyProviderType; + } + + @Override + public String name() { + return keyProviderName; + } + + @Override + public CryptoHandler getCryptoProvider() { + return cryptoHandler; + } + }; + } + + private static abstract class CryptoManagerImpl extends AbstractRefCounted implements CryptoManager { + public CryptoManagerImpl(String keyProviderName, String keyProviderType) { + super(keyProviderName + "-" + keyProviderType); + } + } +} diff --git a/libs/encryption-sdk/src/main/java/org/opensearch/encryption/NoOpCryptoHandler.java b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/NoOpCryptoHandler.java new file mode 100644 index 0000000000000..d6b23ed08c6b0 --- /dev/null +++ b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/NoOpCryptoHandler.java @@ -0,0 +1,128 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.encryption; + +import org.opensearch.common.crypto.CryptoHandler; +import org.opensearch.common.crypto.DecryptedRangedStreamProvider; +import org.opensearch.common.crypto.EncryptedHeaderContentSupplier; +import org.opensearch.common.io.InputStreamContainer; + +import java.io.IOException; +import java.io.InputStream; + +public class NoOpCryptoHandler implements CryptoHandler { + + /** + * No op - Initialises metadata store used in encryption. + * @return crypto metadata object constructed with encryption metadata like data key pair, encryption algorithm, etc. + */ + public Object initEncryptionMetadata() { + return new Object(); + } + + /** + * No op content size adjustment of length of a partial content used in partial encryption. + * + * @param cryptoContextObj stateful object for a request consisting of materials required in encryption. + * @param streamSize Size of the stream to be adjusted. + * @return Adjusted size of the stream. + */ + public long adjustContentSizeForPartialEncryption(Object cryptoContextObj, long streamSize) { + return streamSize; + } + + /** + * No op - Estimate length of the encrypted stream. + * + * @param cryptoMetadataObj crypto metadata instance + * @param contentLength Size of the raw content + * @return Calculated size of the encrypted stream for the provided raw stream. + */ + public long estimateEncryptedLengthOfEntireContent(Object cryptoMetadataObj, long contentLength) { + return contentLength; + } + + /** + * No op length estimation for a given content length. + * + * @param cryptoMetadataObj crypto metadata instance + * @param contentLength Size of the encrypted content + * @return Calculated size of the encrypted stream for the provided raw stream. + */ + public long estimateDecryptedLength(Object cryptoMetadataObj, long contentLength) { + return contentLength; + } + + /** + * No op encrypting stream wrapper. + * + * @param cryptoContextObj consists encryption metadata. + * @param stream Raw InputStream to encrypt + * @return encrypting stream wrapped around raw InputStream. + */ + public InputStreamContainer createEncryptingStream(Object cryptoContextObj, InputStreamContainer stream) { + return stream; + } + + /** + * No op encrypting stream provider for a part of content. + * + * @param cryptoContextObj stateful object for a request consisting of materials required in encryption. + * @param stream raw stream for which encrypted stream has to be created. + * @param totalStreams Number of streams being used for the entire content. + * @param streamIdx Index of the current stream. + * @return Encrypted stream for the provided raw stream. + */ + public InputStreamContainer createEncryptingStreamOfPart( + Object cryptoContextObj, + InputStreamContainer stream, + int totalStreams, + int streamIdx + ) { + return stream; + } + + /** + * + * @param encryptedHeaderContentSupplier Supplier used to fetch bytes from source for header creation + * @return parsed encryption metadata object + * @throws IOException if content fetch for header creation fails + */ + public Object loadEncryptionMetadata(EncryptedHeaderContentSupplier encryptedHeaderContentSupplier) throws IOException { + return new Object(); + } + + /** + * No op decrypting stream provider. + * + * @param encryptedStream to be decrypted. + * @return Decrypting wrapper stream + */ + public InputStream createDecryptingStream(InputStream encryptedStream) { + return encryptedStream; + } + + /** + * No Op decrypted stream range provider + * + * @param cryptoContext crypto metadata instance consisting of encryption metadata used in encryption. + * @param startPosOfRawContent starting position in the raw/decrypted content + * @param endPosOfRawContent ending position in the raw/decrypted content + * @return stream provider for decrypted stream for the specified range of content including adjusted range + */ + public DecryptedRangedStreamProvider createDecryptingStreamOfRange( + Object cryptoContext, + long startPosOfRawContent, + long endPosOfRawContent + ) { + long[] range = { startPosOfRawContent, endPosOfRawContent }; + return new DecryptedRangedStreamProvider(range, (encryptedStream) -> encryptedStream); + } + +} diff --git a/libs/encryption-sdk/src/main/java/org/opensearch/encryption/TrimmingStream.java b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/TrimmingStream.java new file mode 100644 index 0000000000000..d6640bbe5e79e --- /dev/null +++ b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/TrimmingStream.java @@ -0,0 +1,119 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.encryption; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Trims content from a given source range to a target range. + */ +public class TrimmingStream extends InputStream { + + private final long sourceStart; + private final long sourceEnd; + private final long targetStart; + private final long targetEnd; + private final InputStream in; + + private long offsetFromStart = 0; + + public TrimmingStream(long sourceStart, long sourceEnd, long targetStart, long targetEnd, InputStream in) { + if (sourceStart < 0 + || targetStart < 0 + || targetEnd < 0 + || targetStart > targetEnd + || sourceStart > targetStart + || sourceEnd < targetEnd) { + throw new IllegalArgumentException("Invalid arguments to the bounded stream"); + } + + this.sourceStart = sourceStart; + this.sourceEnd = sourceEnd; + this.targetStart = targetStart; + this.targetEnd = targetEnd; + this.in = in; + } + + private void skipBytesOutsideBounds() throws IOException { + long relativeOffset = offsetFromStart + sourceStart; + + if (relativeOffset < targetStart) { + skipBytes(relativeOffset, targetStart); + } + + if (relativeOffset > targetEnd) { + skipBytes(relativeOffset, sourceEnd + 1); + } + } + + private void skipBytes(long offset, long end) throws IOException { + long bytesToSkip = end - offset; + while (bytesToSkip > 0) { + long skipped = skip(bytesToSkip); + if (skipped <= 0) { + // End of stream or unable to skip further + break; + } + bytesToSkip -= skipped; + } + } + + @Override + public int read() throws IOException { + skipBytesOutsideBounds(); + if (offsetFromStart + sourceStart > targetEnd) { + return -1; + } + int b = in.read(); + if (b != -1) { + offsetFromStart++; + } + // This call is made again to ensure that source stream is fully consumed when it reaches end of target range. + skipBytesOutsideBounds(); + return b; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + skipBytesOutsideBounds(); + if (offsetFromStart + sourceStart > targetEnd) { + return -1; + } + len = (int) Math.min(len, targetEnd - offsetFromStart - sourceStart + 1); + int bytesRead = in.read(b, off, len); + if (bytesRead != -1) { + offsetFromStart += bytesRead; + } + // This call is made again to ensure that source stream is fully consumed when it reaches end of target range. + skipBytesOutsideBounds(); + return bytesRead; + } + + /** + * Skips specified number of bytes of input. + * @param n the number of bytes to skip + * @return the actual number of bytes skipped + * @throws IOException if an I/O error has occurred + */ + public long skip(long n) throws IOException { + byte[] buf = new byte[512]; + long total = 0; + while (total < n) { + long len = n - total; + len = in.read(buf, 0, len < buf.length ? (int) len : buf.length); + if (len == -1) { + return total; + } + offsetFromStart += len; + total += len; + } + return total; + } +} diff --git a/libs/encryption-sdk/src/main/java/org/opensearch/encryption/keyprovider/CryptoMasterKey.java b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/keyprovider/CryptoMasterKey.java new file mode 100644 index 0000000000000..6f014c9b4d99b --- /dev/null +++ b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/keyprovider/CryptoMasterKey.java @@ -0,0 +1,84 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.encryption.keyprovider; + +import org.opensearch.common.crypto.DataKeyPair; +import org.opensearch.common.crypto.MasterKeyProvider; + +import javax.crypto.spec.SecretKeySpec; + +import java.io.Closeable; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Map; + +import com.amazonaws.encryptionsdk.CryptoAlgorithm; +import com.amazonaws.encryptionsdk.DataKey; +import com.amazonaws.encryptionsdk.EncryptedDataKey; +import com.amazonaws.encryptionsdk.MasterKey; +import com.amazonaws.encryptionsdk.exception.AwsCryptoException; + +public class CryptoMasterKey extends MasterKey implements Closeable { + private final MasterKeyProvider keyProvider; + private final String keyProviderName; + private final String cryptoAlgorithm; + + public CryptoMasterKey(MasterKeyProvider keyProvider, String keyProviderName, String cryptoAlgorithm) { + this.keyProvider = keyProvider; + this.keyProviderName = keyProviderName; + this.cryptoAlgorithm = cryptoAlgorithm; + } + + @Override + public String getProviderId() { + return keyProviderName; + } + + @Override + public String getKeyId() { + return keyProvider.getKeyId(); + } + + @Override + public DataKey generateDataKey(CryptoAlgorithm algorithm, Map encryptionContext) { + DataKeyPair dataKeyPairResponse = keyProvider.generateDataPair(); + final SecretKeySpec key = new SecretKeySpec(dataKeyPairResponse.getRawKey(), cryptoAlgorithm); + return new DataKey<>(key, dataKeyPairResponse.getEncryptedKey(), getKeyId().getBytes(StandardCharsets.UTF_8), this); + } + + @Override + public DataKey encryptDataKey(CryptoAlgorithm algorithm, Map encryptionContext, DataKey dataKey) { + throw new UnsupportedOperationException("Multiple data-key encryption is not supported."); + } + + @Override + public DataKey decryptDataKey( + CryptoAlgorithm algorithm, + Collection encryptedDataKeys, + Map encryptionContext + ) throws AwsCryptoException { + if (encryptedDataKeys == null || encryptedDataKeys.isEmpty()) { + throw new IllegalArgumentException("No encrypted data key passed for decryption."); + } + EncryptedDataKey encryptedDataKey = encryptedDataKeys.iterator().next(); + final String keyId = new String(encryptedDataKey.getProviderInformation(), StandardCharsets.UTF_8); + if (!this.getKeyId().equals(keyId)) { + throw new IllegalArgumentException("Invalid provider info present in encrypted key."); + } + + byte[] encryptedKey = encryptedDataKey.getEncryptedDataKey(); + byte[] rawKey = keyProvider.decryptKey(encryptedKey); + return new DataKey<>(new SecretKeySpec(rawKey, cryptoAlgorithm), encryptedKey, keyId.getBytes(StandardCharsets.UTF_8), this); + } + + @Override + public void close() throws IOException { + keyProvider.close(); + } +} diff --git a/libs/encryption-sdk/src/main/java/org/opensearch/encryption/keyprovider/package-info.java b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/keyprovider/package-info.java new file mode 100644 index 0000000000000..611b095a54250 --- /dev/null +++ b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/keyprovider/package-info.java @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/** + * Key provider package specific to encryption sdk + */ +package org.opensearch.encryption.keyprovider; diff --git a/libs/encryption-sdk/src/main/java/org/opensearch/encryption/package-info.java b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/package-info.java new file mode 100644 index 0000000000000..1fa008797ce87 --- /dev/null +++ b/libs/encryption-sdk/src/main/java/org/opensearch/encryption/package-info.java @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/** + * Crypto plugin to for encryption and decryption use cases. + */ +package org.opensearch.encryption; diff --git a/libs/encryption-sdk/src/test/java/org/opensearch/encryption/CryptoManagerFactoryTests.java b/libs/encryption-sdk/src/test/java/org/opensearch/encryption/CryptoManagerFactoryTests.java new file mode 100644 index 0000000000000..fb5c477232bc4 --- /dev/null +++ b/libs/encryption-sdk/src/test/java/org/opensearch/encryption/CryptoManagerFactoryTests.java @@ -0,0 +1,92 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.encryption; + +import org.opensearch.common.crypto.CryptoHandler; +import org.opensearch.common.crypto.MasterKeyProvider; +import org.opensearch.common.unit.TimeValue; +import org.opensearch.test.OpenSearchTestCase; +import org.junit.Before; + +import java.util.Collections; + +import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManager; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class CryptoManagerFactoryTests extends OpenSearchTestCase { + + private CryptoManagerFactory cryptoManagerFactory; + + @Before + public void setup() { + cryptoManagerFactory = new CryptoManagerFactory( + "ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384", + TimeValue.timeValueDays(2), + 10 + ); + } + + public void testGetOrCreateCryptoManager() { + MasterKeyProvider mockKeyProvider = mock(MasterKeyProvider.class); + when(mockKeyProvider.getEncryptionContext()).thenReturn(Collections.emptyMap()); + + CryptoManager cryptoManager = cryptoManagerFactory.getOrCreateCryptoManager( + mockKeyProvider, + "keyProviderName", + "keyProviderType", + () -> {} + ); + + assertNotNull(cryptoManager); + } + + public void testCreateCryptoProvider() { + CachingCryptoMaterialsManager mockMaterialsManager = mock(CachingCryptoMaterialsManager.class); + MasterKeyProvider mockKeyProvider = mock(MasterKeyProvider.class); + when(mockKeyProvider.getEncryptionContext()).thenReturn(Collections.emptyMap()); + + CryptoHandler cryptoHandler = cryptoManagerFactory.createCryptoProvider( + "ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384", + mockMaterialsManager, + mockKeyProvider + ); + + assertNotNull(cryptoHandler); + } + + public void testCreateMaterialsManager() { + MasterKeyProvider mockKeyProvider = mock(MasterKeyProvider.class); + when(mockKeyProvider.getEncryptionContext()).thenReturn(Collections.emptyMap()); + + CachingCryptoMaterialsManager materialsManager = cryptoManagerFactory.createMaterialsManager( + mockKeyProvider, + "keyProviderName", + "ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384" + ); + + assertNotNull(materialsManager); + } + + public void testCreateCryptoManager() { + CryptoHandler mockCryptoHandler = mock(CryptoHandler.class); + CryptoManager cryptoManager = cryptoManagerFactory.createCryptoManager( + mockCryptoHandler, + "keyProviderName", + "keyProviderType", + null + ); + assertNotNull(cryptoManager); + } + + public void testUnsupportedAlgorithm() { + expectThrows(IllegalArgumentException.class, () -> new CryptoManagerFactory("Unsupported_algo", TimeValue.timeValueDays(2), 10)); + } +} diff --git a/libs/encryption-sdk/src/test/java/org/opensearch/encryption/MockKeyProvider.java b/libs/encryption-sdk/src/test/java/org/opensearch/encryption/MockKeyProvider.java new file mode 100644 index 0000000000000..a5e74534ef32b --- /dev/null +++ b/libs/encryption-sdk/src/test/java/org/opensearch/encryption/MockKeyProvider.java @@ -0,0 +1,109 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.encryption; + +import javax.crypto.spec.SecretKeySpec; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Map; + +import com.amazonaws.encryptionsdk.CryptoAlgorithm; +import com.amazonaws.encryptionsdk.DataKey; +import com.amazonaws.encryptionsdk.MasterKey; +import com.amazonaws.encryptionsdk.exception.AwsCryptoException; +import com.amazonaws.encryptionsdk.exception.UnsupportedProviderException; + +@SuppressWarnings({ "rawtypes", "unchecked" }) +public class MockKeyProvider extends MasterKey { + + private static final String keyId = "test-key-id"; + + public static byte[] loadFile(String file) { + byte[] content; + try { + InputStream in = MockKeyProvider.class.getResourceAsStream(file); + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + for (String line; (line = bufferedReader.readLine()) != null;) { + stringBuilder.append(line); + } + content = stringBuilder.toString().getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + throw new IllegalArgumentException("File " + file + " cannot be read correctly."); + } + String text = new String(content, StandardCharsets.UTF_8); + + String[] byteValues = text.substring(1, text.length() - 1).split(","); + byte[] bytes = new byte[byteValues.length]; + + for (int i = 0, len = bytes.length; i < len; i++) { + bytes[i] = Byte.parseByte(byteValues[i].trim()); + } + + return bytes; + } + + private static final byte[] rawKey = loadFile("/raw_key"); + private static final byte[] encryptedKey = loadFile("/encrypted_key"); + + @Override + public String getProviderId() { + return "sample-provider-id"; + } + + @Override + public String getKeyId() { + return "Sample-key-id"; + } + + @Override + public DataKey encryptDataKey(CryptoAlgorithm algorithm, Map encryptionContext, DataKey dataKey) { + throw new UnsupportedOperationException("Multiple data-key encryption is not supported."); + } + + @Override + public DataKey generateDataKey(CryptoAlgorithm algorithm, Map encryptionContext) { + final SecretKeySpec key = new SecretKeySpec(rawKey, algorithm.getDataKeyAlgo()); + return new DataKey(key, encryptedKey, getKeyId().getBytes(StandardCharsets.UTF_8), this); + } + + @Override + public DataKey decryptDataKey(CryptoAlgorithm algorithm, Collection collection, Map encryptionContext) + throws UnsupportedProviderException, AwsCryptoException { + return new DataKey<>( + new SecretKeySpec(rawKey, algorithm.getDataKeyAlgo()), + encryptedKey, + keyId.getBytes(StandardCharsets.UTF_8), + this + ); + } + + static class DataKeyPair { + private final byte[] rawKey; + private final byte[] encryptedKey; + + public DataKeyPair(byte[] rawKey, byte[] encryptedKey) { + this.rawKey = rawKey; + this.encryptedKey = encryptedKey; + } + + public byte[] getRawKey() { + return this.rawKey; + } + + public byte[] getEncryptedKey() { + return this.encryptedKey; + } + } + +} diff --git a/libs/encryption-sdk/src/test/java/org/opensearch/encryption/NoOpCryptoHandlerTests.java b/libs/encryption-sdk/src/test/java/org/opensearch/encryption/NoOpCryptoHandlerTests.java new file mode 100644 index 0000000000000..5e3836fd10988 --- /dev/null +++ b/libs/encryption-sdk/src/test/java/org/opensearch/encryption/NoOpCryptoHandlerTests.java @@ -0,0 +1,95 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.encryption; + +import org.opensearch.common.crypto.DecryptedRangedStreamProvider; +import org.opensearch.common.crypto.EncryptedHeaderContentSupplier; +import org.opensearch.common.io.InputStreamContainer; +import org.opensearch.test.OpenSearchTestCase; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class NoOpCryptoHandlerTests extends OpenSearchTestCase { + + public void testInitEncryptionMetadata() { + NoOpCryptoHandler cryptoProvider = new NoOpCryptoHandler(); + Object encryptionMetadata = cryptoProvider.initEncryptionMetadata(); + assertNotNull(encryptionMetadata); + } + + public void testAdjustContentSizeForPartialEncryption() { + NoOpCryptoHandler cryptoProvider = new NoOpCryptoHandler(); + long originalSize = 1000L; + long adjustedSize = cryptoProvider.adjustContentSizeForPartialEncryption(new Object(), originalSize); + assertEquals(originalSize, adjustedSize); + } + + public void testEstimateEncryptedLengthOfEntireContent() { + NoOpCryptoHandler cryptoProvider = new NoOpCryptoHandler(); + long originalSize = 2000L; + long estimatedSize = cryptoProvider.estimateEncryptedLengthOfEntireContent(new Object(), originalSize); + assertEquals(originalSize, estimatedSize); + } + + public void testEstimateDecryptedLength() { + NoOpCryptoHandler cryptoProvider = new NoOpCryptoHandler(); + long originalSize = 1500L; + long estimatedSize = cryptoProvider.estimateDecryptedLength(new Object(), originalSize); + assertEquals(originalSize, estimatedSize); + } + + public void testCreateEncryptingStream() { + NoOpCryptoHandler cryptoProvider = new NoOpCryptoHandler(); + InputStreamContainer inputStream = randomStream(); + InputStreamContainer encryptedStream = cryptoProvider.createEncryptingStream(new Object(), inputStream); + assertEquals(inputStream, encryptedStream); + } + + public void testCreateEncryptingStreamOfPart() { + NoOpCryptoHandler cryptoProvider = new NoOpCryptoHandler(); + InputStreamContainer inputStream = randomStream(); + InputStreamContainer encryptedStream = cryptoProvider.createEncryptingStreamOfPart(new Object(), inputStream, 2, 1); + assertEquals(inputStream, encryptedStream); + } + + private InputStreamContainer randomStream() { + byte[] bytes = randomAlphaOfLength(10).getBytes(); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); + int offset = randomIntBetween(0, bytes.length - 1); + return new InputStreamContainer(byteArrayInputStream, bytes.length, offset); + } + + public void testLoadEncryptionMetadata() throws IOException { + NoOpCryptoHandler cryptoProvider = new NoOpCryptoHandler(); + EncryptedHeaderContentSupplier supplier = (start, length) -> { throw new UnsupportedOperationException("Not implemented"); }; + Object encryptionMetadata = cryptoProvider.loadEncryptionMetadata(supplier); + assertNotNull(encryptionMetadata); + } + + public void testCreateDecryptingStream() { + NoOpCryptoHandler cryptoProvider = new NoOpCryptoHandler(); + InputStream encryptedStream = randomStream().getInputStream(); + InputStream decryptedStream = cryptoProvider.createDecryptingStream(encryptedStream); + assertEquals(encryptedStream, decryptedStream); + } + + public void testCreateDecryptingStreamOfRange() { + NoOpCryptoHandler cryptoProvider = new NoOpCryptoHandler(); + Object cryptoContext = new Object(); + long startPos = 0L; + long endPos = 100L; + DecryptedRangedStreamProvider streamProvider = cryptoProvider.createDecryptingStreamOfRange(cryptoContext, startPos, endPos); + assertNotNull(streamProvider); + InputStream stream = randomStream().getInputStream(); + InputStream decryptedStream = streamProvider.getDecryptedStreamProvider().apply(stream); // Replace with your encrypted input stream + assertEquals(stream, decryptedStream); + } +} diff --git a/libs/encryption-sdk/src/test/java/org/opensearch/encryption/TrimmingStreamTests.java b/libs/encryption-sdk/src/test/java/org/opensearch/encryption/TrimmingStreamTests.java new file mode 100644 index 0000000000000..f0d957d81e1e1 --- /dev/null +++ b/libs/encryption-sdk/src/test/java/org/opensearch/encryption/TrimmingStreamTests.java @@ -0,0 +1,125 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.encryption; + +import org.opensearch.test.OpenSearchTestCase; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +public class TrimmingStreamTests extends OpenSearchTestCase { + + static class ReadCountInputStreamTest extends ByteArrayInputStream { + + public ReadCountInputStreamTest(byte[] buf) { + super(buf); + } + + public int getPos() { + return pos; + } + } + + public void testReadInRange() throws IOException { + byte[] data = generateRandomData(100); + ReadCountInputStreamTest input = new ReadCountInputStreamTest(data); + + long sourceStart = generateRandomValue(0, 80); + long sourceEnd = generateRandomValue(sourceStart, 99); + long targetStart = generateRandomValue(sourceStart, sourceEnd); + long targetEnd = generateRandomValue(targetStart, sourceEnd); + + TrimmingStream trimmingStream = new TrimmingStream(sourceStart, sourceEnd, targetStart, targetEnd, input); + + byte[] result = new byte[(int) (sourceEnd - sourceStart + 1)]; + int bytesRead = trimmingStream.read(result, 0, result.length); + + long expectedBytesRead = targetEnd - targetStart + 1; + assertEquals(expectedBytesRead, bytesRead); + assertEquals(sourceEnd - sourceStart + 1, input.getPos()); + } + + public void testReadOutsideRange() throws IOException { + byte[] data = generateRandomData(100); + ReadCountInputStreamTest input = new ReadCountInputStreamTest(data); + + long sourceStart = generateRandomValue(0, 80); + long sourceEnd = generateRandomValue(sourceStart, 99); + long targetStart = generateRandomValue(sourceStart, sourceEnd); + long targetEnd = generateRandomValue(targetStart, sourceEnd); + + TrimmingStream trimmingStream = new TrimmingStream(sourceStart, sourceEnd, targetStart, targetEnd, input); + + byte[] result = new byte[(int) (targetEnd - targetStart + 1)]; + int bytesRead = trimmingStream.read(result, 0, result.length); + + long expectedBytesRead = targetEnd - targetStart + 1; + assertEquals(expectedBytesRead, bytesRead); + assertEquals(sourceEnd - sourceStart + 1, input.getPos()); + + // Try to read more bytes, should return -1 (end of stream) + int additionalBytesRead = trimmingStream.read(result, 0, 50); + assertEquals(-1, additionalBytesRead); + assertEquals(sourceEnd - sourceStart + 1, input.getPos()); + } + + public void testSingleByteReadInRange() throws IOException { + byte[] data = generateRandomData(100); + ReadCountInputStreamTest input = new ReadCountInputStreamTest(data); + + long sourceStart = generateRandomValue(0, 80); + long sourceEnd = generateRandomValue(sourceStart, 99); + long targetStart = generateRandomValue(sourceStart, sourceEnd); + long targetEnd = generateRandomValue(targetStart, sourceEnd); + + TrimmingStream trimmingStream = new TrimmingStream(sourceStart, sourceEnd, targetStart, targetEnd, input); + + int bytesRead = 0; + int value; + while ((value = trimmingStream.read()) != -1) { + bytesRead++; + } + + long expectedBytesRead = targetEnd - targetStart + 1; + assertEquals(expectedBytesRead, bytesRead); + assertEquals(sourceEnd - sourceStart + 1, input.getPos()); + } + + public void testInvalidInputs() { + assertThrows(IllegalArgumentException.class, () -> new TrimmingStream(-10, 60, 20, 40, new ByteArrayInputStream(new byte[100]))); + assertThrows(IllegalArgumentException.class, () -> new TrimmingStream(10, 60, 40, 20, new ByteArrayInputStream(new byte[100]))); + } + + public void testSourceSameAsTarget() throws IOException { + byte[] data = generateRandomData(100); + ReadCountInputStreamTest input = new ReadCountInputStreamTest(data); + + long sourceStart = generateRandomValue(0, 80); + long sourceEnd = generateRandomValue(sourceStart, 99); + TrimmingStream trimmingStream = new TrimmingStream(sourceStart, sourceEnd, sourceStart, sourceEnd, input); + + byte[] result = new byte[(int) (sourceEnd - sourceStart + 1)]; + int bytesRead = trimmingStream.read(result, 0, result.length); + + assertEquals(sourceEnd - sourceStart + 1, bytesRead); + assertEquals(sourceEnd - sourceStart + 1, input.getPos()); + } + + private byte[] generateRandomData(int length) { + byte[] data = new byte[length]; + for (int i = 0; i < length; i++) { + data[i] = (byte) (Math.random() * 256 - 128); + } + return data; + } + + private long generateRandomValue(long min, long max) { + return min + (long) (Math.random() * (max - min + 1)); + } +} diff --git a/libs/encryption-sdk/src/test/resources/encrypted_key b/libs/encryption-sdk/src/test/resources/encrypted_key new file mode 100644 index 0000000000000..da4e503581585 --- /dev/null +++ b/libs/encryption-sdk/src/test/resources/encrypted_key @@ -0,0 +1 @@ +[1, 2, 1, 0, 120, -96, 18, 71, -6, 90, -126, -39, -16, 94, -113, -46, 71, 85, 35, -66, -117, -108, -59, 88, -81, 64, -118, -74, -102, 50, 103, 16, -76, 23, 19, 20, 67, 1, -11, 55, -3, 32, -89, -16, 1, -40, 59, 76, -2, -61, -49, -97, 34, 14, 0, 0, 0, 126, 48, 124, 6, 9, 42, -122, 72, -122, -9, 13, 1, 7, 6, -96, 111, 48, 109, 2, 1, 0, 48, 104, 6, 9, 42, -122, 72, -122, -9, 13, 1, 7, 1, 48, 30, 6, 9, 96, -122, 72, 1, 101, 3, 4, 1, 46, 48, 17, 4, 12, -63, 67, 37, -51, 85, 75, 7, -64, -78, 52, 102, 26, 2, 1, 16, -128, 59, -98, -123, 100, 125, -37, 102, -87, -71, 74, 68, 54, 56, -32, 77, 127, -86, -125, -17, 45, 75, -98, 54, -52, -15, -56, -47, -88, -12, -128, 113, -5, -18, -14, 127, 114, -9, 47, -112, -38, 39, 2, -89, 117, 64, -2, 47, -81, 52, 27, -118, 37, 79, -64, 58, -3, 10, -115, 122, 124] \ No newline at end of file diff --git a/libs/encryption-sdk/src/test/resources/raw_content_for_crypto_test b/libs/encryption-sdk/src/test/resources/raw_content_for_crypto_test new file mode 100644 index 0000000000000..c93b6161ac8d6 --- /dev/null +++ b/libs/encryption-sdk/src/test/resources/raw_content_for_crypto_test @@ -0,0 +1,25 @@ +ewogICJmaWxlSW5mb3MiOiBbCiAgICB7CiAgICAgICJuYW1lIjogIl80LmZubSIsCiAgICAgICJyZW1vdGVfc +GF0aCI6ICIyYzYwMzNmNmZlZTY0NTY1YTU3YzQzZWVmZThmY2QzMS9kdW1teS1jb2xsZWN0aW9uMi9kMDRmYz +AyZi0wMDQ0LTRhYmYtYjgzMy0xMGE0YTA5M2VkNTcvMC8wL2luZGljZXMvMSIsCiAgICAgICJzaXplIjogOTQz +CiAgICB9LAogICAgewogICAgICAibmFtZSI6ICJfMl9MdWNlbmU4MF8wLmR2ZCIsCiAgICAgICJyZW1vdGVfcGF +0aCI6ICIyYzYwMzNmNmZlZTY0NTY1YTU3YzQzZWVmZThmY2QzMS9kdW1teS1jb2xsZWN0aW9uMi9kMDRmYzAyZi0wMDQ0LTRhYmYtYjg +zMy0xMGE0YTA5M2VkNTcvMC8wL2luZGljZXMvMSIsCiAgICAgICJzaXplIjogMzU1CiAgICB9CiAgXQp9 +ewogICJja3BfZmlsZSI6IHsKICAgICJuYW1lIjogInRyYW5zbG9nLTguY2twIiwKICAgICJyZW1vdGVfcGF0aCI6ICIyYz +YwMzNmNmZlZTY0NTY1YTU3YzQzZWVmZThmY2QzMS9kdW1teS1jb2xsZWN0aW9uMi9kMDRmYzAyZi0wMDQ0LTRhYmYtYjgzMy0 +xMGE0YTA5M2VkNTcvMC8wL3RyYW5zbG9nLzEiLAogICAgInNpemUiOiAwCiAgfSwKICAidGxvZ192ZXJzaW9uIjogewogICAgIjg +iOiAiMmM2MDMzZjZmZWU2NDU2NWE1N2M0M2VlZmU4ZmNkMzEvZHVtbXktY29sbGVjdGlvbjIvZDA0ZmMwMmYtMDA0NC00YWJmLWI4MzMtMT +BhNGEwOTNlZDU3LzAvMC90cmFuc2xvZy8xIgogIH0KfQ== +ewogICJmaWxlSW5mb3MiOiBbCiAgICB7CiAgICAgICJuYW1lIjogIl80LmZubSIsCiAgICAgICJyZW1vdGVfcGF0aCI6ICIyYzYwMzNmNmZl +ZTY0NTY1YTU3YzQzZWVmZThmY2QzMS9kdW1teS1jb2xsZWN0aW9uMi9kMDRmYzAyZi0wMDQ0LTRhYmYtYjgzMy0xMGE0YTA5M2VkNTcvMC8wL2luZG +ljZXMvMSIsCiAgICAgICJzaXplIjogOTQzCiAgICB9LAogICAgewogICAgICAibmFtZSI6ICJfNC5mZHQiLAogICAgICAicmVtb3RlX3BhdGgiOiAi +MmM2MDMzZjZmZWU2NDU2NWE1N2M0M2VlZmU4ZmNkMzEvZHVtbXktY29sbGVjdGlvbjIvZDA0ZmMwMmYtMDA0NC00YWJmLWI4MzMtMTBhNGEwOTNlZDU3 +LzAvMC9pbmRpY2VzLzEiLAogICAgICAic2l6ZSI6IDQ1MTMKICAgIH0sCiAgICB7CiAgICAgICJuYW1lIjogInNlZ21lbnRzX2MiLAogICAgICAicmVtb3R +lX3BhdGgiOiAiMmM2MDMzZjZmZWU2NDU2NWE1N2M0M2VlZmU4ZmNkMzEvZHVtbXktY29sbGVjdGlvbjIvZDA0ZmMwMmYtMDA0NC00YWJmLWI4MzM +tMTBhNGEwOTNlZDU3LzAvMC9pbmRpY2VzLzEiLAogICAgICAic2l6ZSI6IDM1NQogICAgfQogIF0KfQ== +ewogICJja3BfZmlsZSI6IHsKICAgICJuYW1lIjogInRyYW5zbG9nLTcuY2twIiwKICAgICJyZW1vdGVfcGF0aCI6ICIyYzYwMzNmNmZlZ +TY0NTY1YTU3YzQzZWVmZThmY2QzMS9kdW1teS1jb2xsZWN0aW9uMi9kMDRmYzAyZi0wMDQ0LTRhYmYtYjgzMy0xMGE0YTA5M2VkNTcvMC8wL3RyY +W5zbG9nLzEiLAogICAgInNpemUiOiAwCiAgfSwKICAidGxvZ192ZXJzaW9uIjogewogICAgIjYiOiAiMmM2MDMzZjZmZWU2NDU2NWE1N2M0M2VlZ +mU4ZmNkMzEvZHVtbXktY29sbGVjdGlvbjIvZDA0ZmMwMmYtMDA0NC00YWJmLWI4MzMtMTBhNGEwOTNlZDU3LzAvMC90cmFuc2xvZy8xIiwKICAgICI3Ijo +gIjJjNjAzM2Y2ZmVlNjQ1NjVhNTdjNDNlZWZlOGZjZDMxL2R1bW15LWNvbGxlY3Rpb24yL2QwNGZjMDJmLTAwNDQtNGFiZi1iODMzLTEwYTRhMDkzZW +Q1Ny8wLzAvdHJhbnNsb2cvMSIKICB9Cn0= + diff --git a/libs/encryption-sdk/src/test/resources/raw_key b/libs/encryption-sdk/src/test/resources/raw_key new file mode 100644 index 0000000000000..3c4f8b54cbb6a --- /dev/null +++ b/libs/encryption-sdk/src/test/resources/raw_key @@ -0,0 +1 @@ +[57, 59, -48, -8, -44, 9, -78, 16, 106, -80, 66, -41, 66, 43, -88, 7, 47, -23, -16, -43, 99, 104, -8, -74, 46, -117, -111, -41, -39, -69, 5, 117] \ No newline at end of file diff --git a/plugins/ingest-attachment/build.gradle b/plugins/ingest-attachment/build.gradle index 17213b96a25f3..2fe5b93704585 100644 --- a/plugins/ingest-attachment/build.gradle +++ b/plugins/ingest-attachment/build.gradle @@ -89,7 +89,7 @@ dependencies { api "org.apache.james:apache-mime4j-core:${versions.mime4j}" api "org.apache.james:apache-mime4j-dom:${versions.mime4j}" // EPUB books - api 'org.apache.commons:commons-lang3:3.13.0' + api "org.apache.commons:commons-lang3:${versions.commonslang}" // Microsoft Word files with visio diagrams api 'org.apache.commons:commons-math3:3.6.1' // POIs dependency diff --git a/plugins/repository-azure/build.gradle b/plugins/repository-azure/build.gradle index 9da2e58c55271..26e2b4813b8a5 100644 --- a/plugins/repository-azure/build.gradle +++ b/plugins/repository-azure/build.gradle @@ -70,7 +70,7 @@ dependencies { api 'org.codehaus.woodstox:stax2-api:4.2.1' implementation "com.fasterxml.woodstox:woodstox-core:${versions.woodstox}" runtimeOnly "com.google.guava:guava:${versions.guava}" - api 'org.apache.commons:commons-lang3:3.13.0' + api "org.apache.commons:commons-lang3:${versions.commonslang}" testImplementation project(':test:fixtures:azure-fixture') }