forked from opensearch-project/OpenSearch
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Vikas Bansal <43470111+vikasvb90@users.noreply.github.com>
- Loading branch information
Showing
22 changed files
with
3,247 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
libs/encryption-sdk/licenses/aws-encryption-sdk-java-1.7.0.jar.sha1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
51704a672e65456d37f444c5992c079feff31218 |
1 change: 0 additions & 1 deletion
1
libs/encryption-sdk/licenses/aws-encryption-sdk-java-2.4.0.jar.sha1
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
140 changes: 140 additions & 0 deletions
140
libs/encryption-sdk/src/main/java/org/opensearch/encryption/frame/AwsCrypto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/* | ||
* 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.frame; | ||
|
||
import org.opensearch.common.io.InputStreamContainer; | ||
|
||
import java.io.InputStream; | ||
import java.util.Map; | ||
|
||
import com.amazonaws.encryptionsdk.CommitmentPolicy; | ||
import com.amazonaws.encryptionsdk.CryptoAlgorithm; | ||
import com.amazonaws.encryptionsdk.CryptoMaterialsManager; | ||
import com.amazonaws.encryptionsdk.ParsedCiphertext; | ||
import com.amazonaws.encryptionsdk.exception.AwsCryptoException; | ||
import com.amazonaws.encryptionsdk.internal.LazyMessageCryptoHandler; | ||
import com.amazonaws.encryptionsdk.internal.MessageCryptoHandler; | ||
import com.amazonaws.encryptionsdk.model.EncryptionMaterialsRequest; | ||
|
||
public class AwsCrypto { | ||
private final CryptoMaterialsManager materialsManager; | ||
private final CryptoAlgorithm cryptoAlgorithm; | ||
|
||
public AwsCrypto(final CryptoMaterialsManager materialsManager, final CryptoAlgorithm cryptoAlgorithm) { | ||
Utils.assertNonNull(materialsManager, "materialsManager"); | ||
this.materialsManager = materialsManager; | ||
this.cryptoAlgorithm = cryptoAlgorithm; | ||
|
||
} | ||
|
||
public EncryptionMetadata createCryptoContext(final Map<String, String> encryptionContext, int frameSize) { | ||
Utils.assertNonNull(encryptionContext, "encryptionContext"); | ||
|
||
EncryptionMaterialsRequest.Builder requestBuilder = EncryptionMaterialsRequest.newBuilder() | ||
.setContext(encryptionContext) | ||
.setRequestedAlgorithm(cryptoAlgorithm) | ||
.setPlaintextSize(0) // To avoid skipping cache | ||
.setCommitmentPolicy(CommitmentPolicy.ForbidEncryptAllowDecrypt); | ||
|
||
return new EncryptionMetadata(frameSize, materialsManager.getMaterialsForEncrypt(requestBuilder.build())); | ||
} | ||
|
||
public InputStreamContainer createEncryptingStream( | ||
final InputStreamContainer stream, | ||
int streamIdx, | ||
int totalStreams, | ||
int frameNumber, | ||
EncryptionMetadata encryptionMetadata | ||
) { | ||
|
||
boolean isLastStream = streamIdx == totalStreams - 1; | ||
boolean firstOperation = streamIdx == 0; | ||
if (stream.getContentLength() % encryptionMetadata.getFrameSize() != 0 && !isLastStream) { | ||
throw new AwsCryptoException( | ||
"Length of each inputStream should be exactly divisible by frame size except " | ||
+ "the last inputStream. Current frame size is " | ||
+ encryptionMetadata.getFrameSize() | ||
+ " and inputStream length is " | ||
+ stream.getContentLength() | ||
); | ||
} | ||
final MessageCryptoHandler cryptoHandler = getEncryptingStreamHandler(frameNumber, firstOperation, encryptionMetadata); | ||
CryptoInputStream<?> cryptoInputStream = new CryptoInputStream<>(stream.getInputStream(), cryptoHandler, isLastStream); | ||
cryptoInputStream.setMaxInputLength(stream.getContentLength()); | ||
|
||
long encryptedLength = 0; | ||
if (streamIdx == 0) { | ||
encryptedLength = encryptionMetadata.getCiphertextHeaderBytes().length; | ||
} | ||
if (streamIdx == (totalStreams - 1)) { | ||
encryptedLength += estimateOutputSizeWithFooter( | ||
encryptionMetadata.getFrameSize(), | ||
encryptionMetadata.getNonceLen(), | ||
encryptionMetadata.getCryptoAlgo().getTagLen(), | ||
stream.getContentLength(), | ||
encryptionMetadata.getCryptoAlgo() | ||
); | ||
} else { | ||
encryptedLength += estimatePartialOutputSize( | ||
encryptionMetadata.getFrameSize(), | ||
encryptionMetadata.getNonceLen(), | ||
encryptionMetadata.getCryptoAlgo().getTagLen(), | ||
stream.getContentLength() | ||
); | ||
} | ||
return new InputStreamContainer(cryptoInputStream, encryptedLength, -1); | ||
} | ||
|
||
public MessageCryptoHandler getEncryptingStreamHandler( | ||
int frameStartNumber, | ||
boolean firstOperation, | ||
EncryptionMetadata encryptionMetadata | ||
) { | ||
return new LazyMessageCryptoHandler(info -> new EncryptionHandler(encryptionMetadata, firstOperation, frameStartNumber)); | ||
} | ||
|
||
public long estimatePartialOutputSize(int frameLen, int nonceLen, int tagLen, long contentLength) { | ||
return FrameEncryptionHandler.estimatePartialSizeFromMetadata(contentLength, false, frameLen, nonceLen, tagLen); | ||
} | ||
|
||
public long estimateOutputSizeWithFooter(int frameLen, int nonceLen, int tagLen, long contentLength, CryptoAlgorithm cryptoAlgorithm) { | ||
return FrameEncryptionHandler.estimatePartialSizeFromMetadata(contentLength, true, frameLen, nonceLen, tagLen) | ||
+ getTrailingSignatureSize(cryptoAlgorithm); | ||
} | ||
|
||
public long estimateDecryptedSize(int frameLen, int nonceLen, int tagLen, long contentLength, CryptoAlgorithm cryptoAlgorithm) { | ||
long contentLenWithoutTrailingSig = contentLength - getTrailingSignatureSize(cryptoAlgorithm); | ||
return FrameDecryptionHandler.estimateDecryptedSize(contentLenWithoutTrailingSig, frameLen, nonceLen, tagLen); | ||
} | ||
|
||
public int getTrailingSignatureSize(CryptoAlgorithm cryptoAlgorithm) { | ||
return EncryptionHandler.getAlgoTrailingLength(cryptoAlgorithm); | ||
} | ||
|
||
public CryptoInputStream<?> createDecryptingStream(final InputStream inputStream) { | ||
|
||
final MessageCryptoHandler cryptoHandler = DecryptionHandler.create(materialsManager); | ||
return new CryptoInputStream<>(inputStream, cryptoHandler, true); | ||
} | ||
|
||
public CryptoInputStream<?> createDecryptingStream( | ||
final InputStream inputStream, | ||
final long size, | ||
final ParsedCiphertext parsedCiphertext, | ||
final int frameStartNum, | ||
boolean isLastPart | ||
) { | ||
|
||
final MessageCryptoHandler cryptoHandler = DecryptionHandler.create(materialsManager, parsedCiphertext, frameStartNum); | ||
CryptoInputStream<?> cryptoInputStream = new CryptoInputStream<>(inputStream, cryptoHandler, isLastPart); | ||
cryptoInputStream.setMaxInputLength(size); | ||
return cryptoInputStream; | ||
} | ||
|
||
} |
109 changes: 109 additions & 0 deletions
109
libs/encryption-sdk/src/main/java/org/opensearch/encryption/frame/CipherHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
/* | ||
* Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except | ||
* in compliance with the License. A copy of the License is located at | ||
* | ||
* http://aws.amazon.com/apache2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file 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. | ||
*/ | ||
|
||
package org.opensearch.encryption.frame; | ||
|
||
import javax.crypto.Cipher; | ||
import javax.crypto.SecretKey; | ||
import javax.crypto.spec.GCMParameterSpec; | ||
|
||
import java.security.GeneralSecurityException; | ||
import java.security.spec.AlgorithmParameterSpec; | ||
|
||
import com.amazonaws.encryptionsdk.CryptoAlgorithm; | ||
import com.amazonaws.encryptionsdk.exception.AwsCryptoException; | ||
import com.amazonaws.encryptionsdk.exception.BadCiphertextException; | ||
|
||
/** | ||
* This class provides a cryptographic cipher handler powered by an underlying block cipher. The | ||
* block cipher performs authenticated encryption of the provided bytes using Additional | ||
* Authenticated Data (AAD). | ||
* | ||
* <p>This class implements a method called cipherData() that encrypts or decrypts a byte array by | ||
* calling methods on the underlying block cipher. | ||
*/ | ||
public class CipherHandler { | ||
private final int cipherMode_; | ||
private final SecretKey key_; | ||
private final CryptoAlgorithm cryptoAlgorithm_; | ||
private final Cipher cipher_; | ||
|
||
/** | ||
* Process data through the cipher. | ||
* | ||
* <p>This method calls the <code>update</code> and <code>doFinal</code> methods on the underlying | ||
* cipher to complete processing of the data. | ||
* | ||
* @param nonce the nonce to be used by the underlying cipher | ||
* @param contentAad the optional additional authentication data to be used by the underlying | ||
* cipher | ||
* @param content the content to be processed by the underlying cipher | ||
* @param off the offset into content array to be processed | ||
* @param len the number of bytes to process | ||
* @return the bytes processed by the underlying cipher | ||
* @throws AwsCryptoException if cipher initialization fails | ||
* @throws BadCiphertextException if processing the data through the cipher fails | ||
*/ | ||
public byte[] cipherData(byte[] nonce, byte[] contentAad, final byte[] content, final int off, final int len) { | ||
if (nonce.length != cryptoAlgorithm_.getNonceLen()) { | ||
throw new IllegalArgumentException("Invalid nonce length"); | ||
} | ||
final AlgorithmParameterSpec spec = new GCMParameterSpec(cryptoAlgorithm_.getTagLen() * 8, nonce, 0, nonce.length); | ||
|
||
try { | ||
cipher_.init(cipherMode_, key_, spec); | ||
if (contentAad != null) { | ||
cipher_.updateAAD(contentAad); | ||
} | ||
} catch (final GeneralSecurityException gsx) { | ||
throw new AwsCryptoException(gsx); | ||
} | ||
try { | ||
return cipher_.doFinal(content, off, len); | ||
} catch (final GeneralSecurityException gsx) { | ||
throw new BadCiphertextException(gsx); | ||
} | ||
} | ||
|
||
/** | ||
* Create a cipher handler for processing bytes using an underlying block cipher. | ||
* | ||
* @param key the key to use in encrypting or decrypting bytes | ||
* @param cipherMode the mode for processing the bytes as defined in {@link Cipher#init(int, | ||
* java.security.Key)} | ||
* @param cryptoAlgorithm the cryptography algorithm to be used by the underlying block cipher. | ||
*/ | ||
public CipherHandler(final SecretKey key, final int cipherMode, final CryptoAlgorithm cryptoAlgorithm) { | ||
this.cipherMode_ = cipherMode; | ||
this.key_ = key; | ||
this.cryptoAlgorithm_ = cryptoAlgorithm; | ||
this.cipher_ = buildCipherObject(cryptoAlgorithm); | ||
} | ||
|
||
private static Cipher buildCipherObject(final CryptoAlgorithm alg) { | ||
try { | ||
// Right now, just GCM is supported | ||
return Cipher.getInstance("AES/GCM/NoPadding"); | ||
} catch (final GeneralSecurityException ex) { | ||
throw new IllegalStateException("Java does not support the requested algorithm", ex); | ||
} | ||
} | ||
} |
Oops, something went wrong.